23

I've been through quite a number of articles on Stack Overflow that answered the question "How do I pass preprocessor definitions to the compiler from the MSBuild command line," and they all responded with some variation of:

MSBuild.exe /p:DefineConstants=THING_TO_BE_DEFINED

I have tried every variation that I could come up with:

MSBuild.exe "/p:DefineConstants=THING_TO_BE_DEFINED"
MSBuild.exe /p:DefineConstants="THING_TO_BE_DEFINED"
MSBuild.exe "/p:DefineConstants=THING_TO_BE_DEFINED=1"
MSBuild.exe /p:DefineConstants="THING_TO_BE_DEFINED=1"

...and dozens of others. I've also flirted with overriding PreprocessorDefinitions in similar ways. All of them triggered the #error below:

#include "stdafx.h"

#if !defined(THING_TO_BE_DEFINED)
#error "THING_TO_BE_DEFINED is not defined"
#endif

int _tmain(int argc, _TCHAR* argv[])
{
    return 0;
}

I've been trying this with the simple command-line application above, as well as with a huge game project that I have here. I can only guess that Visual Studio (I'm seeing this with 2005 and 2008) has some default set deep in its bowels that is preventing my command line argument from being applied, but I've found no evidence to support this hypothesis.

Any ideas on how I can get this to work? Why in the name of FSM didn't they stick with good ol' -D THING_TO_BE_DEFINED?

Brian Tompsett - 汤莱恩
  • 5,195
  • 62
  • 50
  • 120
Sniggerfardimungus
  • 10,708
  • 10
  • 46
  • 91

4 Answers4

10

If you are calling MSBuild on the command line you cannot specify the value for DefineConstants. But if you are building a .csproj, or another MSBuild script, then you can specify it. If you create a msbuild file to "replace" your solution file then you can use that an specify the value for that when you build your projects. For example:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <!-- Default value here -->
    <DefineConstants Condition=" '$(DefineConstants)'==''" >DEBUG;TRACE</DefineConstants>
  </PropertyGroup>

  <ItemGroup>
    <Projects Include="one.csproj" />
    <Projects Include="two.csproj" />
  </ItemGroup>

  <Target Name="Build">
    <MSBuild Projects="@(Projects)"
                 Properties="DefineConstants=$(DefineConstants)"/>
  </Target>
</Project>

Then you can use msbuild.exe buid.proj /p:DefineConstants="YourValue;Debug;Trace"

Note the usage of the quotes on the command line.

I have written a blog post a while back about something related to this at http://sedodream.com/2008/05/07/MSBuildBuildingTheSameProjectMultipleTimes.aspx.

Graviton
  • 76,900
  • 138
  • 399
  • 575
Sayed Ibrahim Hashimi
  • 42,483
  • 14
  • 139
  • 172
8

If you want to define TRACE & DEBUG Constants this should work:

msbuild mysln.sln /t:Rebuild /p:Configuration=Release /p:DefineConstants="DEBUG;TRACE"
Robert Muehsig
  • 4,978
  • 2
  • 27
  • 30
  • 6
    The accepted answer is actually incorrect. I have found for my own projects, that DefineConstants is ignored, unless I use the /t:Rebuild option. – A.R. Mar 26 '14 at 16:21
  • 11
    This works, but it OVERWRITES the existing `$(DefineConstants)` variable -- for EVERY PROJECT in the solution! -- I just want to append to it! – BrainSlugs83 Sep 16 '14 at 19:50
  • @BrainSlugs83 so what would you mark as accepted answer? I'm genuinely curious – knocte Sep 19 '20 at 08:29
6

The below are needed modification to the vcxproj for the /p to work.

put <DefineConstants>< /DefineConstants>

under the <PropertyGroup Label=Globals >

<PreprocessorDefinitions>$(DefineConstants);WIN32;_DEBUG;_CONSOLE;UNIT_TEST_SIM;%(PreprocessorDefinitions)

This way MSBuild will know that for the preprocessor it needs to use the values from the DefineConstants which come from the Globals PropertyGroup unless provided from the command line by the /p:DefineConstants="MY_DEFINE"

Moshe
  • 61
  • 1
  • 3
3

For completeness, this is what I found worked when I wanted THING_TO_BE_DEFINED="VALUE WANTED", for VB.NET, and msbuild version 3.5.30729.1, in a batch file:

@msbuild /t:Rebuild /p:Configuration=Release;Platform="Any CPU";
DefineConstants="THING_TO_BE_DEFINED=\"VALUE WANTED\"" mysln.sln

(all on one line of course)

Mark Hurd
  • 10,175
  • 10
  • 62
  • 96
  • 2
    +1 Thank you so much! You are the only one mentioning how to escape double quotes in order to define Strings. – Arnaud Feb 28 '15 at 09:54