The following is taken from a regular VS2010 C++ project.
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
If i edit PreprocessorDefinitions
i can set a definition that is used by the preprocessor. I can see this in my code via #ifdef
etc.
However if i use the following
<Target Name="NormalBuild" Condition=" '$(_InvalidConfigurationWarning)' != 'true' " DependsOnTargets="_DetermineManagedStateFromCL;CustomBeforeBuild;$(BuildDependsOn)" Returns="@(ManagedTargetPath)">
<ItemGroup>
<ManagedTargetPath Include="$(TargetPath)" Condition="'$(ManagedAssembly)' == 'true'" />
</ItemGroup>
<Message Text="PreprocessorDefinitions: $(PreprocessorDefinitions)" Importance="High" />
</Target>
<Target Name="TestBuild" Returns="@(ManagedTargetPath)">
<MSBuild Projects="demo.vcxproj" Targets="NormalBuild" Properties="PreprocessorDefinitions=THISGETSSETBUTDOESNOTHING"/>
</Target>
i can also see via the message that PreprocessorDefinitions
contains the value i set via Properties="PreprocessorDefinitions=THISGETSSETBUTDOESNOTHING"
but i can not control my build using #ifdef
etc.
If i use a regular setup and try to output PreprocessorDefinitions
using <Message Text="PreprocessorDefinitions: $(PreprocessorDefinitions)"
the field is actually blank and does not contain the expected <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
although i can use any one of those keys to control my build using #ifdef
etc.
Properties
element?This can be done without modifying the original project: the first thing done in Microsoft.Cpp.Targets
, which is normally one of the last things imported in a normal C++ project, is to check if there's a property called ForceImportBeforeCppTargets
and if so, import it.
So suppose you want to add ADDITIONAL
to the preprocessor definitions you create a file 'override.props' like this (for full automation use the WritelinesToFile
task to create the file):
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>%(PreprocessorDefinitions);ADDITIONAL</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
</Project>
And call
<MSBuild Projects="demo.vcxproj"
Properties="ForceImportBeforeCppTargets=override.props"/>
or from the command line that would be
msbuild demo.vcxproj /p:ForceImportBeforeCppTargets=override.props
Note as richb points out in the comment, the above only works if override.props can be found by msbuild's lookup rules. To make sure it is always found just specify the full path.
Update
Some years later, in msbuild 15 and beyond, there are new ways to customise builds. Same principle as above, but simpler: msbuild will automatically pick up the file named Directory.Build.props
in the project file's directory or even all directories above that, without needing additional commandline options (so, also works from within VS without problems). And the project files also became a bit less verbose as well:
<Project>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>%(PreprocessorDefinitions);ADDITIONAL</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
</Project>
Based on @Kevin answer you need to define a user-defined macro in a PropertySheet. Then create a Preprocessor which refers to the user-defined macro. You can now use the new preprocessor value in your code. Finally, for the build, you can change the value of user-defined macro with /p
flag.
In here I defined a user-defined value like mymacro
and a preprocessor value like VAL
.
Now you can simply compile the project with /p:mymacro="\"some thing new\""
.
#include <iostream>
int main() {
std::cout << VAL << std::endl;
getchar();
}
yourproject.vcxproj
:
<ClCompile>
...
<PreprocessorDefinitions>VAL=$(mymacro);%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
msbuild yourproject.vcxproj /p:mymacro="\"some thing new\""
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With