Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MSBuild for projects with both native and managed project references

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?

like image 617
Dan Hermann Avatar asked Oct 09 '22 19:10

Dan Hermann


1 Answers

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.

#80. Define your own Solution mechanics

#19. Consider using the standard extensions path

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.

#104. How to unify Platforms for multiple project types

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)...
like image 170
Brian Kretzler Avatar answered Oct 13 '22 11:10

Brian Kretzler