I have a solution that contains a couple hundred C++ and C# projects. I cannot use MSBuild to directly build any individual project that has project dependencies of a different type because the valid configuration (Deubg/Release) and platform (Win32/AnyCPU/x64) settings are different for different project types.
E.g., if I have a C++ project "CppProj1" with a dependency on a C# project "CsharpProj1", I cannot compile CppProj1 with MSBuild by specifying Release/AnyCPU on the command line because CppProj1 will fail to compile on the unknown platform type. Likewise, specifying Release/Win32 will cause CsharpProj1 to fail to compile. Visual Studio solves this problem by storing a mapping of configuration/platform settings in each solution file, but a huge motivation for using MSBuild is to decouple my build process from the Visual Studio IDE. Is there way to handle this problem without using VS solution files?
There are many ways to do this. A thorough explanation of all of them is covered by more than a dozen pages in the book "MSBuild Trickery" (tricks #19, #80, #104) but I'll summarize the basic mechanisms here.
These tricks have a discussion of the AdditionalProperties metadata. Create an item array for your projects, and specify AdditionalProperties metadata for the Platform property, which will be used when the items are built with the MSBuild task.
In a properties file for your build...
<ItemGroup>
<Project Include="./Folder1/Project1.csproj" />
<Project Include="./Folder2/Project2.vcxproj" />
...
</ItemGroup>
In the Build target...
<ItemGroup>
<Project>
<AdditionalProperties
Condition="'%(Extension)' == '.csproj'">
>Platform=AnyCPU</AdditionalProperties>
<AdditionalProperties
Condition="'%(Extension)' == '.vcxproj'">
>Platform=Win32</AdditionalProperties>
<Project>
</ItemGroup>
<MSBuild Projects=@(Project) ... />
On top of this you can add in detection for 32 vs. 64-bit.
In a common imported property file, declare your own $(__Platform) property that is derived from the value of $(Platform), similar to the above, which creates a "normalized" notion of "Platform" to reference in the rest of the project. This will work in a solution build as well.
<PropertyGroup>
<__Platform
Condition="'$(Platform)' == 'Win32'>Win32</__Platform>
<__Platform
Condition="'$(Platform)' == 'Win64'>Win64</__Platform>
<__Platform
Condition="'$(Platform)' == 'x32'>Win32</__Platform>
<__Platform
Condition="'$(Platform)' == 'x64'>Win64</__Platform>
</PropertyGroup>
<PropertyGroup
Condition="'$(Platform)' == 'AnyCPU'">
<__Platform
Condition="'$(PROCESSOR_ARCHITECTURE)' == 'x86'>Win32</__Platform>
...etc...
</PropertyGroup>
...then later on, for the different project file types, make a custom import that uses this value...
<!-- for C# projects -->
<PropertyGroup>
<OutputPath>bin\$(__Platform).$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(__Platform)...
<!-- for C++ projects -->
<PropertyGroup>
<OutDir>bin\$(__Platform).$(Configuration)\</OutDir>
<IntDir>obj\$(__Platform)...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With