Including the Nemerle compiler in code repository - msbuild

I'm trying to include the Nemerle compiler into my source code repository so that it can be built without Nemerle being installed in the build server. Currently my source code directory looks like this:
- [MySolutionFolder]
--- [.build]
------ [Nemerle]
--------- [net-4.0]
------------ ncc.exe
------------ ncc32.dll
------------ Nemerle.dll
------------ Nemerle.MSBuild.targets
------------ { all other Nemerle requirements }
--- [MyNemerleProjectFolder]
------ MyNemerleProject.nproj
------ { various .n files }
--- MySolution.sln
--- build.bat
The build.bat file is a simple script which calls MSBuild on the .sln file.
In my .nproj file, I changed the line
<Nemerle Condition=" '$(Nemerle)' == '' ">$(NemerleBinPathRoot)\$(NemerleVersion)</Nemerle>
to:
<Nemerle Condition=" '$(Nemerle)' == '' ">$(SolutionDir).build\Nemerle\$(NemerleVersion)</Nemerle>
After this change, I can successfully build from the command line script, however I cannot open the solution in Visual Studio. When opening the solution, VS complains that it cannot find MySolutionFolder\MyNemerleProjectFolder\.build\Nemerle\net-4.0\Nemerle.MSBuild.targets
Why is visual studio looking for a .build directory under the project folder rather than the solution folder? Is there a workaround for this?
If I change it to:
<Nemerle Condition=" '$(Nemerle)' == '' >$(ProjectDir)..\.build\Nemerle\$(NemerleVersion)</Nemerle>
Then the solution will open in visual studio, but the build fails - also the command line build fails..

Try to use $(MSBuildProjectDirectory) instead of $(ProjectDir).
For example:
<Nemerle Condition=" '$(Bootstrapping)' == 'true' ">$(MSBuildProjectDirectory)\..\Boot\$(NemerleVersion)</Nemerle>
<Nemerle Condition=" '$(Bootstrapping)' == 'false' ">$(NemerleBinPathRoot)\$(NemerleVersion)</Nemerle>

Sounds like a bug in the Visual Studio.
What you can do is to specify a pre-build event, which will create a symbolic link from $(ProjectDir).build to $(SolutionDir).build.
Hackish, yes.

Related

How to avoid Visual Studio 2022 to add project configuration to output path

Visual Studio 2022 is adding subfolders to the base output path.
Is there a way to prevent it from adding Release/Debug subfolders to the output path?
Visual Studio 2022 - Project properties
The output path is a concatenation of a bunch of MSBuild properties. Depending on your project type, it can happen in the project file, in a targets file you import explicitly, or in an implicit import such as via an MSBuild SDK. In any of these cases, you should be able to override it by setting the value explicitly in your project file.
Taking the 3rd case as an example (using the Microsoft.NET.Sdk), in Microsoft.NET.DefaultOutputPaths.targets you'll find the defaults specified like this:
<BaseOutputPath Condition="'$(BaseOutputPath)' == ''">bin\</BaseOutputPath>
<BaseOutputPath Condition="!HasTrailingSlash('$(BaseOutputPath)')">$(BaseOutputPath)\</BaseOutputPath>
<OutputPath Condition="'$(OutputPath)' == '' and '$(PlatformName)' == 'AnyCPU'">$(BaseOutputPath)$(Configuration)\</OutputPath>
<OutputPath Condition="'$(OutputPath)' == '' and '$(PlatformName)' != 'AnyCPU'">$(BaseOutputPath)$(PlatformName)\$(Configuration)\</OutputPath>
<OutputPath Condition="!HasTrailingSlash('$(OutputPath)')">$(OutputPath)\</OutputPath>
Notice how the $(OutputPath) is basically appending the $(Configuration) to the $(BaseOutputPath).
If you want to always have the same output path, you can set <OutputPath>Your\Desired\Path</OutputPath> in your project file. Once you've set the value, this default logic above will be skipped based on the now-false condition ('$(OutputPath)' is no longer empty).
However, this may break incremental build if you build different configurations without deleting the contents of the output folder between builds.
I know this is an old question, but here's the full solution based on Microsoft's Debugger Settings:
Click on Project > [name of project]
In Build > Output, change the Base output path to C:\ [full directory path] \ [name of project]
Click on Project > Edit Project File
Add to PropertyGroup>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<OutputPath>C:\[full directory path]\[name of project]</OutputPath>
In my case - with a Nunit test project it didn't help either. The Debug and Release folders were always created.
I had to make the following changes in the project file:
From:
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<IsPackable>false</IsPackable>
<BaseOutputPath>bin\</BaseOutputPath>
<BaseIntermediateOutputPath>obj\</BaseIntermediateOutputPath>
</PropertyGroup>
to:
(add the two false values and BaseOutputPath --> OutputPath and BaseIntermediateOutputPath --> IntermediateOutputPath)
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<IsPackable>false</IsPackable>
<OutputPath>bin\</OutputPath>
<IntermediateOutputPath>obj\</IntermediateOutputPath>
</PropertyGroup>

Visual Studio - Could not copy the file "obj\Debug\[file].exe" because it was not found

So, I'm trying to build a project I just installed Visual Studio to build this specific project (it is in vb6 so I needed to use the Visual Basic tools extension because i had Visual Studio 2015 installed). I have no programming knowledge on this area, only web.
And when I try to build it it gives me this error:
------ Build started: Project: Proyecto1, Configuration: Debug x86 ------
C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Common.CurrentVersion.targets(3812,5):
error MSB3030: Could not copy the file "obj\Debug\Proyecto1.exe"
because it was not found. Done building project "Proyecto1.vb6proj" --
FAILED.
Build FAILED.
Then I click on the error and it send me to that piece of code
<!-- Copy the build product (.dll or .exe). -->
<Copy
SourceFiles="#(IntermediateAssembly)"
DestinationFolder="$(OutDir)"
SkipUnchangedFiles="$(SkipCopyUnchangedFiles)"
OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
Retries="$(CopyRetryCount)"
RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
UseHardlinksIfPossible="$(CreateHardLinksForCopyFilesToOutputDirectoryIfPossible)"
Condition="'$(CopyBuildOutputToOutputDirectory)' == 'true' and '$(SkipCopyBuildProduct)' != 'true'">
<Output TaskParameter="DestinationFiles" ItemName="MainAssembly"/>
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
</Copy>
<Message Importance="High" Text="$(MSBuildProjectName) -> #(MainAssembly->'%(FullPath)')" Condition="'$(CopyBuildOutputToOutputDirectory)' == 'true' and '$(SkipCopyBuildProduct)'!='true'" />
I already saw the existent questions for this problem and the solutions didn't worked for me.
In my case it was like #Hans says it was my Antivirus fault (Avast) I disabled it to test if that was the problem, deleted the bin and debug folders and re-opened the solution and it worked perfectly.
P.D. Remember to add you solution folder to your antivirus exclusions.

What configuration and platform does msbuild use by default when building a solution file or project files

If I execute msbuild from the command line with my solution file or project file as input without setting configuration and platform how does msbuild determine which configuration and platform to use for each project in the solution or the single project file?
In case of solution files - both msbuild and xbuild try to find Debug config and Mixed platforms platform, but if that doesn't exist then it falls back to the first one that it can find under SolutionConfigurationPlatforms in the .sln file. Keep in mind that this is just solution level config/platform, and it uses the mapping in ProjectConfigurationPlatforms in the .sln file to determine the config/platform to use for the project.
In case of project files, the *proj files usually have the default Configuration and Platform specified. But if even that is missing then the Microsoft.Common.*targets file chooses Debug|AnyCPU as the default.
Update: default specification in the csproj might look like this:
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
...
It's essentially saying "if $(Configuration) is unspecified, then set it to Debug", and similar for Platform.

What invokes _CopyWebApplication?

I've used AstroGrep and searched both C:\Windows\Microsoft.NET and C:\Program Files (x86)\MSBuild
and I can't find anything that refers to _CopyWebApplication besides the file itself. I also tried to search for webapplication to see if something was importing that file, no luck. I have vs2008 and vs2010 ultimate installed.
I'm troubleshooting my override not working.
Where is this target being imported/invoked?
_CopyWebApplication target is defined in the file: C:\Program Files\MSBuild\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets
This target invocation is set by this property :
<PropertyGroup>
...
<PrepareForRunDependsOn Condition="!$(Disable_CopyWebApplication)">
$(PrepareForRunDependsOn);
_CopyWebApplication;
_BuiltWebOutputGroupOutput
</PrepareForRunDependsOn>
</PropertyGroup>
Resulting in this chain of call :
Build --> CoreBuild --> PrepareForRun --> _CopyWebApplication
Apparently the individual project files themselves have the call to _CopyWebApplication embedded. 'C:\Program Files\MSBuild\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets' I thought it was going to be part of the default targets that was deciding to include or invoke this target file.
I am a team member and we build the project on the server via Hudson , the problem happened to be my version of VS. it seems that VS 2013 is buggy that comments this line in csproj file:
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
I Uncommented it committed on the server . Problem was solved
but each time VS 2013 Comments This line.

Overriding MSBuildExtensionsPath in the MSBuild task is flaky

This is already cross-posted at MS Connect:
https://connect.microsoft.com/VisualStudio/feedback/details/560451
I am attempting to override the property $(MSBuildExtensionsPath) when building a solution containing a C# web application project via msbuild. I am doing this because a web application csproj file imports the file "$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v9.0\WebApplications\Microsoft.WebApplication.targets". This file is installed by Visual Studio to the standard $(MSBuildExtensionsPath) location (C:\Program Files\MSBuild). I would like to eliminate the dependency on this file being installed on the machine (I would like to keep my build servers as "clean" as possible). In order to do this, I would like to include the Microsoft.WebApplication.targets in source control with my project, and then override $(MSBuildExtensionsPath) so that the csproj will import this included version of Microsoft.WebApplication.targets. This approach allows me to remove the dependency without requiring me to manually modify the web application csproj file.
This scheme works fine when I build my solution file from the command line, supplying the custom value of $(MSBuildExtensionsPath) at the command line to msbuild via the /p flag. However, if I attempt to build the solution using the MSBuild task in a custom msbuild project file (overriding MSBuildExtensionsPath using the "Properties" attribute), it fails because the web app csproj file is attempting to import the Microsoft.WebApplication.targets from the "standard" Microsoft.WebApplication.targets location (C:\Program Files\MSBuild). Notably, if I run msbuild using the "Exec" task in my custom project file, it works. Even more notably, the FIRST time I run the build using the "MSBuild" task AFTER I have run the build using the "EXEC" task (or directly from the command line), the build works.
Has anyone seen behavior like this before? Am I crazy? Is anyone aware of the root cause of this problem, a possible workaround, or whether this is a legitimate bug in MSBuild?
Steps to Reproduce:
1) Create a new empty solution in MSVS 2008 (Fake.sln)
2) Add a new C# web application to the solution (WebApplication1.csproj)
3) Close MSVS
4) Copy the contents of "C:\Program Files\MSBuild\" to a directory called "MSBuildExtensions" in the directory containing your solution.
5) rename the directory "C:\Program Files\MSBuild\Microsoft\VisualStudio\v9.0\WebApplications" so that WebApplication1.csproj will not be able to import Microsoft.WebApplication.targets from that location.
6) Create a custom MSBuild project file called "TestBuild.proj" in the same directory as the solution. It should have the following content:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="BuildMSBuild">
<PropertyGroup>
<MSBuildExtensionsPath>$(MSBuildProjectDirectory)\MSBuildExtensions\</MSBuildExtensionsPath>
<BuildThis>Fake.sln</BuildThis>
</PropertyGroup>
<Target Name="BuildMSBuild">
<MSBuild Projects="$(BuildThis)" Properties="MSBuildExtensionsPath=$(MSBuildExtensionsPath);" Targets="Clean" />
<MSBuild Projects="$(BuildThis)" Properties="MSBuildExtensionsPath=$(MSBuildExtensionsPath);"/>
</Target>
</Project>
7) execute "msbuild TestBuild.proj" from a MSVS command prompt (note: the build may succeed the first time, but will fail if you run more than once)
Did you try setting the environment variable MSBuildExtensionPath in the CMD prompt and then running your build?
For example:
C:\> SET MSBuildExtensionsPath=C:\My\MSBuild\Extensons
Then on this project file:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build">
<Message Text='MSBuildExtensionsPath="$(MSBuildExtensionsPath)"' />
</Target>
</Project>
you will get the following output:
c:\Users\chuckeng\Desktop\ConsoleApplication1>"C:\Windows\Microsoft.NET\Framework\v3.5\MSBuild.exe" my.proj
Microsoft (R) Build Engine Version 3.5.30729.4926
[Microsoft .NET Framework, Version 2.0.50727.4927]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 6/25/2010 1:04:05 PM.
Project "c:\my.proj" on node 0 (default targets).
MSBuildExtensionsPath="C:\My\MSBuild\Extensons"
Done Building Project "c:\my.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.03
This works from v4.0 as well. Although, support is generally better in v4.0 for things like this. And, v4.0 is 100% backward compatible (bugs not withstanding). So, you can build your v3.5 and prior projects with v4.0. Just select ToolsVersion 3.5.
msbuild my.proj /tv:3.5
Hope this helps...
Chuck England
Visual Studio
Program Manager - MSBuild
This is a bug in MSBuild 3.5 but it is fixed in MSBuild 4.
If you can, switch to MSBuild 4 (you still can compile your 3.5 projects), otherwise you'll have to override the property in the project file.
It works fine if you override MSBuildExtensionsPath directly in the web app .csproj file.
<PropertyGroup>
<MSBuildExtensionsPath>C:\Users\madgnome\Desktop\msbuild</MSBuildExtensionsPath>
<!-- It works too with relative path -->
<!--<MSBuildExtensionsPath>..\msbuild</MSBuildExtensionsPath>-->
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
Don't know if this might help anyone in the future, but I was able to use the following at the top of my file and it works as I would expect in both 32 and 64 bit build environments.
<PropertyGroup>
<MSBuildExtensionsPath Condition=" '$(MSBuildExtensionsPath64)' != '' ">$(MSBuildExtensionsPath64)</MSBuildExtensionsPath>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\ExtensionPack\4.0\MSBuild.ExtensionPack.tasks"/>