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.
...