xanatos
xanatos

Reputation: 111930

I can't build multiple configuration(s) of a project at the same time in Visual Studio, but I can with MSBuild

I want to build two configurations at the same time of a project. Let's say that when I want to build the release version, but I want to build even the debug version (the opposite isn't true).

Starting with Use a single Visual Studio solution to build both x86 and x64 at the same time? I've tried adding to the .csproj:

<Target Name="AfterBuild">
    <MSBuild Condition=" '$(Configuration)' == 'Release' " Projects="$(MSBuildProjectFile)" Properties="Configuration=Debug" RunEachTargetSeparately="true" />
</Target>

And if I try to build the project through MSBuild,

MSBuild ConsoleApplication64.csproj /p:Configuration=Release /p:Platform=x86

it works correctly. The two configurations are built correctly and everything is good.

The problem is if I try to build it with Visual Studio: the release version is built correctly, and then it begins to build the debug version, and it gives me:

Copying file from "obj\x86\Debug\ConsoleApplication64.exe" to "bin\Debug\ConsoleApplication64. c:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(2868,9): error MSB3021: Unable to copy file "obj\x86\Debug\ConsoleApplication64.exe" to "bin\Debug\ConsoleApplication64.exe". Could not find file 'obj\x86\Debug\ConsoleApplication64.exe'.

Pre-conditions:

(Note that to have those messages I've activated the verbosity: normal from menu ToolsOptionsProjects and SolutionsBuild and RunMSBuild project build output verbosity.

After comparing the output of the two "half" runs, the difference is that in the "working" half the csc executable is called, and in the other one it isn't:

Release half:

Task "Csc" (TaskId:13) c:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\Csc.exe /noconfig /nowarn:1701,1702 /nostdlib+ /platform:x86 /errorreport:prompt /warn:4 /define:TRACE /reference:"C:\Programmi\Reference Assemblies\Microsoft\Framework.NETFramework\v4.0\Profile\Client\Microsoft.CSharp.dll" /reference:"C:\Programmi\Reference Assemblies\Microsoft\Framework.NETFramework\v4.0\Profile\Client\mscorlib.dll" /reference:"C:\Programmi\Reference Assemblies\Microsoft\Framework.NETFramework\v4.0\Profile\Client\System.Core.dll" /reference:"C:\Programmi\Reference Assemblies\Microsoft\Framework.NETFramework\v4.0\Profile\Client\System.dll" /debug:pdbonly /filealign:512 /optimize+ /out:obj\x86\Release\ConsoleApplication64.exe /target:exe Program.cs Properties\AssemblyInfo.cs "C:\Documents and Settings\m.alberti-cons\Impostazioni locali\Temp.NETFramework,Version=v4.0,Profile=Client.AssemblyAttributes.cs" (TaskId:13) Done executing task "Csc". (TaskId:13)

Debug half:

Task "Csc" (TaskId:41) Done executing task "Csc". (TaskId:41)

After some more tests I've noticed that if the two halves use the same DefineConstants then there isn't any problem and everything works, but if they are different (as in release/debug) then it doesn't work. :-(

Upvotes: 1

Views: 2717

Answers (1)

KMoraz
KMoraz

Reputation: 14164

You can't build inside Visual Studio because of MSBuild's incremental build mechanism that skips targets marked as already run. The real question here is how to break this incremental build. This question is very related.

If you build with /verbosity=diag you will notice MSBuild reports a bunch of these:

Target "AssignTargetPaths" skipped. Previously built successfully.

Microsoft aware of this behavior and consider this by design.

A possible workaround, which I strongly advise against it, is invoking the second build using the Exec task. The Exec task is merely a command line shell which will eat everything you will feed it with, but in your case it can break the incremental build chain.

<Exec Command="$(MSBuildToolsPath)\msbuild $(MSBuildProjectFile) /p:Configuration=Debug" Condition=" '$(Configuration)' == 'Release'" />

Upvotes: 2

Related Questions