views:

1173

answers:

3

Here's what I'm trying to do:

  • A single build script
  • That script builds two executables from the same Visual Studio project.
  • The first compiled .exe has a small amount of code disabled.
  • The other compiled .exe has everything enabled.

I've been reading up on conditional compilation and that takes care of my needs as far as enabling/disabling blocks of code.

I just can't figure out how to control conditional compilation from a build script using msbuild.

Is there a way to manipulate conditional compilation variables from a build script or some other way to accomplish what I'm trying to do?

+4  A: 

Use build configurations in your project file. Set the parameters in a PropertyGroup that is optionally included based on the configuration. The configuration can then also define the output path for the two different versions of the assembly.

For the version that needs to remove some code use a configuration that includes the PropertyGroup.

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'CompiledOutDebug|AnyCPU' ">
   <DefineConstants>$(DefineConstants);MY_CONDITIONAL_COMPILATION_CONSTANT</DefineConstants>
</PropertyGroup>

Then use an MSBuild script that calls the project MSBuild script twice and uses the Properties attribute of the MSBuild task to specify the configuration to build:

<Target Name="Build">
    <MSBuild Projects="MyProject.csproj;" 
             Targets="Build" 
             Properties="Configuration=Release" />
    <MSBuild Projects="MyProject.csproj"
             Targets="Build"
             Properties="Configuration=CompiledOutDebug" />
  </Target>
Hamish Smith
Hamish, your Condition isn't quite correct, but I up voted anyway because you got the concept right on for a repeatable build.
Ants
Thanks. It was meant to illustrate the concept. I'll look at it again though.
Hamish Smith
It looks like you can do this inside Visual Studio as well.http://msdn.microsoft.com/en-us/library/kwybya3w(VS.80).aspx
Mark Biek
I kind of prefer the separate MSBuild file as I can run it locally or on a continuous integration server. We tried to keep everything in the project file but it ends up complicated and VS occasionally decides to rewrite sections of it for you.
Hamish Smith
You don't need a separate target. You can do the same thing with one target and specifying the DefineConstant property.
Franci Penov
+1  A: 

Hamish beat me to it.

Here's an alternate solution using the same concepts:

At the command line:

msbuild -t:Clean
msbuild
CopyOutputDirForWithoutDefine.cmd
msbuild -t:Clean
msbuild -property:DefineConstants=MY_CONDITIONAL_COMPILE_CONSTANT
CopyOutputDirForWithDefine.cmd

The 1st and 3rd 'msbuild -t:Clean' ensures that you don't have left over turds from previous builds. The 2nd 'msbuild' builds without the conditional define, while the 4rth builds with the conditional define.

If the above are just a couple on shot items, then a batch file maybe enough. I recommend learning a bit of MSBuild and actually scripting everything in a MSBuild file as Hamish has done.

Ants
I couldn't get DefineConstants to work with VB .NET.
Mark Biek
Note that VB uses commas (?) as DefineConstants separators, whereas C# is more forgiving (semicolons, commas, ...)
Brian
+1  A: 

If you don't want to create a separate target for the two compilations, you can do it by specifying the conditional define in the DefineConstants property when you call the build the second time:

<Target Name="Build">
    <MSBuild Projects="MyProject.csproj;"
             Targets="Build"
             Properties="Configuration=Debug" />
    <MSBuild Projects="MyProject.csproj"
             Targets="Build"
             Properties="Configuration=Debug;
                         AssemblyName=$(AssemblyName)_Conditional;
                         DefineConstants=$(DefineConstants);CONDITIONAL_DEFINE" />
</Target>

Note that if you do it this way, you need to also overwrite the AssemblyName, otherwise your second build might pick intermediate files from the first build.

You should also look at the MSBuild task docs on MSDN, there are some interesting tidbits there.

Franci Penov
Nice. Hadn't spotted that. Thanks.
Hamish Smith