MSBuild:用我的自定义目标更新c++预处理器定义



我正在尝试创建一个自定义MSBuild目标,以自动将SVN版本号获取到某些定义中,例如MY_VERSION。那么,我的目标文件(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>

最后,修改项目文件:

<Project ...
<Import Project="get-svn-info.targets" />
...
</Project>

但是编译器说这里的'MY_VERSION':未声明的标识符

std::cout << "Hello World!n" << std::to_string(MY_VERSION) << std::endl;

我做错了什么?为什么PreprocessorDefinitions仍然有旧的值?由于

构建日志输出(很多不重要的?跳过行):

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

ItemDefinitionGroup语法错误。一个ItemDefinitionGroup不能在一个ItemGroup内。

ItemDefinitionGroup将更改后的PreprocessorDefinitions添加为ClCompileItemGroup中的项的默认值。

但是ItemDefinitionGroup不能在Target中使用。

但是我们仍然可以修改ClCompileItemGroup中Items的元数据。

我建议设定两个目标。

<Target Name="GetSvnRevision" BeforeTargets="PrepareForBuild">
<Exec Command="svn info --show-item revision" ConsoleToMSBuild="true">
<Output TaskParameter="ConsoleOutput" PropertyName="SvnRevisionNum" />
</Exec>
...
</Target>
<Target Name="ApplySvnRevision" BeforeTargets="ClCompile">
<ItemGroup>
<ClCompile>
<PreprocessorDefinitions>%(PreprocessorDefinitions);MY_VERSION=$(SvnRevisionNum);</PreprocessorDefinitions>
</ClCompile>
</ItemGroup>
</Target>

'GetSvnRevision'可以提前执行。但是'ApplySvnRevision'应该在编译之前完成。

这个解决方案是有效的,但是也许有一个更优雅的解决方案?毕竟,MY_VERSION不仅可以用于一个文件ConsoleApplication1.cpp?由于

<Target Name="GetSvnRevision" BeforeTargets="PrepareForBuild">
<Exec Command="svn info --show-item revision" ConsoleToMSBuild="true">
<Output TaskParameter="ConsoleOutput" PropertyName="SvnRevisionNum" />
</Exec>
<ItemGroup>
<ClCompile Remove="ConsoleApplication1.cpp" />
<ClCompile Include="ConsoleApplication1.cpp">
<PreprocessorDefinitions>%(PreprocessorDefinitions);MY_VERSION=$(SvnRevisionNum);</PreprocessorDefinitions>
</ClCompile>
</ItemGroup>
<Message Text="ME_VERSION=$(SvnRevisionNum)" Importance="high"></Message>

最新更新