Question

I have a solution with a windows phone class library project, BaseProj, and several WP-projects that references this project, project A, B etc. BaseProj has a LocationHelper-class.

Lets say that project A needs BaseProj to compile with the LocationHelper-class but project B should be built without the ID_CAP_LOCATION-capabillity, so the LocationHelper-class shouldn't be included when BaseProj builds.

I can achieve this with conditional compilation symbols, the question is: How can I get BaseProj to be built with the appropriate symbols depending on whether I'm building project A or B?

After some research I come up with the following solution, in BaseProj.csproj I added

<PropertyGroup Condition=" '$(TestProperty)'==true ">
  <DefineConstants>$(DefineConstants);TEST_SYMBOL</DefineConstants>
</PropertyGroup>

And in B.csproj a property in the ProjectReference:

<ProjectReference Include="..\BaseProj\BaseProj.csproj">
  <Project>{...}</Project>
  <Name>BaseProj</Name>
  <Properties>TestProperty=true</Properties>
</ProjectReference>

Thinking that TEST_SYMBOL should be added when building with B and not with A. This works beautifully when I build with MSBuild. Visual Studio on the other hand completely ignores this, meaning that I get different behavior when I debug and when I make a release build with my build script.

How can I get the behavior I want from MSBuild and Visual Studio?

Was it helpful?

Solution

I came up with a new solution that works both for MSBuild and Visual Studio.

First, BaseProj is set up to build with the location api if the conditional compilation symbol INCLUDE_LOCATION_API is defined.

Projects A and B is set up to build with a pre-build event that executes a powershell script, pre-build.ps1. (refer to this question).

pre-build.ps1 will read the manifest of the current project to determine whether it has the location capability (ID_CAP_LOCATION), and if BaseProj Debug and Release configurations defines INCLUDE_LOCATION_API. If necessary, INCLUDE_LOCATION_API will be added or removed. Since this will modify the BaseProj.csproj, the build script will exit with an error code to prevent the build from complete.

When I build from VS, if BaseProj has correct configurations, it will build normally. If it has the wrong configuration, BaseProj.csproj will be modified and the build fails, but then the next build will succeed.

In my build script, I execute pre-build.ps1 once before the actual build, ensuring that the project has correct configuration. Then MSBuild is executed and project is built successfully.

I Wouldn't consider this best practice, but it gets the job done and I don't need to think about what configurations should be used when switching between projects.

OTHER TIPS

This could be done by defining new project configurations. Assuming you already have Debug and Release configurations, and they are configured with ID_CAP_LOCATION, you can create new configurations, e.g.: Debug_No_Location and Release_No_Location. This is done in Visual Studio' Configuration Manager dialog. Along with project configuration, define corresponding solution configurations as well, to make it easier to build it from Visual Studio. After that remove ID_CAP_LOCATION from Debug_No_Location/Release_No_Location configurations.

It is important to edit all projects in your solution and make sure Intermediate location and Binaries location are different from their Debug/Release configurations, otherwise you will run into problems of mixing binaries between configurations, making incremental build unreliable.

If you want to build both flavors (with Location and without) from VS IDE, you will have to manually switch between configurations. However from command line you can create simple script that calls MSBuild.exe twice. E.g.:

msbuild MySolution.sln /p:Configuration=Debug
msbuild MySolution.sln /p:Configuration=Debug_No_Location
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top