I’m trying to create a custom MSBuild target to automatically fetching the SVN revision number into some define, say MY_VERSION. So, my target file (get-svn-info.targets):
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="GetSvnRevision" BeforeTargets="PrepareForBuild">
<Exec Command="svn info --show-item revision" ConsoleToMSBuild="true">
<Output TaskParameter="ConsoleOutput" PropertyName="SvnRevisionNum" />
</Exec>
<ItemGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>%(PreprocessorDefinitions);MY_VERSION=$(SvnRevisionNum);</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
</ItemGroup>
<Message Text="MY_VERSION=$(SvnRevisionNum)" Importance="high"></Message>
</Target>
</Project>
And finally, modified the project file:
<Project ...
<Import Project="get-svn-info.targets" />
...
</Project>
But compiler says that the ‘MY_VERSION’: undeclared identifier here
std::cout << "Hello World!n" << std::to_string(MY_VERSION) << std::endl;
What am I doing wrong? Why does PreprocessorDefinitions still have the old value? Thanks
Build log output (a lot of unimportant? lines skipped):
...
1>Target "GetSvnRevision" in file "D:ConsoleApplication1get-svn-info.targets":
1> Using "Exec" task from assembly "Microsoft.Build.Tasks.Core, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
1> Task "Exec"
1> Task Parameter:ConsoleToMSBuild=True
1> Task Parameter:Command=svn info --show-item revision
1> svn info --show-item revision
1> 30
1> Output Property: SvnRevisionNum=30
1> Done executing task "Exec".
1> Task "Message"
1> Task Parameter:Importance=high
1> Task Parameter:Text=MY_VERSION=30
1> MY_VERSION=30
1> Done executing task "Message".
1>Done building target "GetSvnRevision" in project "ConsoleApplication1.vcxproj".
...
1>Target "ClCompile" in file "C:Program Files (x86)Microsoft Visual Studio2019CommunityMSBuildMicrosoftVCv160Microsoft.CppCommon.targets":
1> Task "CL"
...
1> Task Parameter:
1> Sources=
1> ConsoleApplication1.cpp
1> PreprocessorDefinitions=WIN32;_DEBUG;_CONSOLE;_UNICODE;UNICODE;
...
1> Task Parameter:
1> PreprocessorDefinitions=
1> WIN32
1> _DEBUG
1> _CONSOLE
1> _UNICODE
1> UNICODE
...
1> D:ConsoleApplication1ConsoleApplication1.cpp(9,53): error C2065: 'MY_VERSION': undeclared identifier
1> The command exited with code 2.
1> Done executing task "CL" -- FAILED.
1>Done building target "ClCompile" in project "ConsoleApplication1.vcxproj" -- FAILED.
1>
1>Done building project "ConsoleApplication1.vcxproj" -- FAILED.
...
2
Answers
This solution works, but maybe there is a more elegant solution? After all, the MY_VERSION can be used not only in one file ConsoleApplication1.cpp? Thanks
The syntax for the
ItemDefinitionGroup
is incorrect. AnItemDefinitionGroup
should not be within anItemGroup
.The
ItemDefinitionGroup
will add the changedPreprocessorDefinitions
as a default for items in theClCompile
ItemGroup.But
ItemDefinitionGroup
can’t be used within aTarget
.But we can still alter the metadata of Items in the
ClCompile
ItemGroup.I would suggest making two targets.
‘GetSvnRevision’ can be performed early. But ‘ApplySvnRevision’ should be done just before compiling.