Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

msbuild: set a specific preprocessor #define in the command line

In a C++ file, I have a code like this:

#if ACTIVATE
#   pragma message( "Activated" )
#else
#   pragma message( "Not Activated")
#endif

I want to set this ACTIVE define to 1 with the msbuild command line.

It tried this but it doesn't work:

msbuild /p:DefineConstants="ACTIVATE=1"

Any idea?

like image 604
acemtp Avatar asked Oct 03 '08 11:10

acemtp


4 Answers

I'm a little late to the party (only 4 years or so), but I just had to workaround this problem on a project, and stumbled across this question while searching for a fix. Our solution was to use an environment variable with /D defines in it, combined with the Additional Options box in visual studio.

  1. In Visual Studio, add an environment variable macro, $(ExternalCompilerOptions), to the Additional Options under project options->C/C++->Command Line (remember both Debug and Release configs)
  2. Set the environment variable prior to calling msbuild. Use the /D compiler option to define your macros
    c:\> set ExternalCompilerOptions=/DFOO /DBAR 
    c:\> msbuild

Item #1 ends up looking like this in the vcxproj file:

    <ClCompile>
      <AdditionalOptions>$(ExternalCompilerOptions) ... </AdditionalOptions>
    </ClCompile>

This works for me with VS 2010. We drive msbuild from various build scripts, so the environment variable ugliness is hidden a bit. Note that I have not tested if this works when you need to set the define to specific value ( /DACTIVATE=1 ). I think it would work, but I'm concerned about having multiple '='s in there.

H^2

like image 146
bigh_29 Avatar answered Nov 02 '22 23:11

bigh_29


C++ projects (and solutions) are not (yet ?) integrated in the MSBuild environment. As part of the build process, the VCBuild task is called, which is just a wrapper around vcbuild.exe.

You could :

  • create a specific configuration for your solution where ACTIVATE=1 would be defined, and compile it with devenv.exe (with the /ProjectConfig switch).
  • create your own target file to wrap your own call to the VCBuild task (see the Override parameter)...
  • use vcbuild.exe instead of msbuild.exe. (vcbuild.exe does not seem to have the equivalent of an Override parameter).

Note that your solution would not work for C# projects either unless you tweaked your project files a bit. For reference, here is how I would do this :

  • Add the following code before the call to <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> :
<PropertyGroup Condition=" '$(MyConstants)' != '' ">
  <DefineConstants>$(DefineConstants);$(MyConstants)</DefineConstants>
</PropertyGroup>
  • Call MSBuild like this :
msbuild /p:MyConstants="ACTIVATE=1"
like image 25
Mac Avatar answered Nov 03 '22 00:11

Mac


If you need to define some constant (not just true/false), you can do it the following way:

On command line:

MSBuild /p:MyDefine=MyValue

In vcxproj file (in section <ClCompile>; and/or <ResourceCompile>, depending on where you need it):

<PreprocessorDefinitions>MY_DEFINE=$(MyDefine);$(PreprocessorDefinitions)</PreprocessorDefinitions>

Note that if you don't specify /p:MyDefine=MyValue in a call to MSBuild then empty string will be assigned to MY_DEFINE macro. If it's OK for you, that's it. If not, keep reading.

How to make a macro undefined if corresponding MSBuild parameter is not specified

To have MY_DEFINE macro undefined instead of empty string, you can use the following trick:

<ClCompile>
  ....
  <PreprocessorDefinitions>_DEBUG;_CONSOLE;OTHER_UNCONDITIONAL_MACROS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
  <PreprocessorDefinitions Condition="'$(MyDefine)'!=''">MY_DEFINE=$(MyDefine);%(PreprocessorDefinitions)</PreprocessorDefinitions>
  ....
</ClCompile>

First PreprocessorDefinitions defines unconditional macros. Second PreprocessorDefinitions additionally defines MY_DEFINE macro when MyDefine is not empty string. You can test this by placing the following piece of code into your cpp file:

#define STRINGIZE2(x) #x
#define STRINGIZE(x) STRINGIZE2(x)

#ifndef MY_DEFINE
#pragma message("MY_DEFINE is not defined.")
#else
#pragma message("MY_DEFINE is defined to: [" STRINGIZE(MY_DEFINE) "]")
#endif

and running:

> MSBuild SandBox.sln /p:Configuration=Debug /p:MyDefine=test /t:Rebuild
...
MY_DEFINE is defined to: [test]
...

> MSBuild SandBox.sln /p:Configuration=Debug /p:MyDefine= /t:Rebuild
...
MY_DEFINE is not defined.
...

> MSBuild SandBox.sln /p:Configuration=Debug /t:Rebuild
...
MY_DEFINE is not defined.
...
like image 11
4LegsDrivenCat Avatar answered Nov 02 '22 23:11

4LegsDrivenCat


I think you want:

/p:DefineConstants=ACTIVATE
like image 10
Matt Howells Avatar answered Nov 03 '22 00:11

Matt Howells