我有一个 msbuild 自定义目标和一个计算值的任务。 任务将输出值作为属性。 我想将此属性用作编译器调用的附加选项。
但当用作附加选项时该属性为空。
我的*.targets 文件如下所示:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="GetBranchName_TASK" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
<ParameterGroup>
<sPath ParameterType="System.String" Required="true" />
<sBranchName ParameterType="System.String" Output="true" />
</ParameterGroup>
<Task>
<Code Type="Fragment" Language="cs">
<![CDATA[
... some Code ...
]]>
</Code>
</Task>
</UsingTask>
<Target Name="GetBranchName_TARGET">
<GetBranchName_TASK sPath="$(MSBuildThisFileDirectory)">
<Output PropertyName="BranchName" TaskParameter="sBranchName" />
</GetBranchName_TASK>
<Message Importance="High" Text="BranchName = $(BranchName)" />
</Target>
<PropertyGroup>
<BuildDependsOn>
GetBranchName_TARGET;
$(BuildDependsOn);
</BuildDependsOn>
</PropertyGroup>
</Project>
我的*.props文件是这样的:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Configuration">
... some Properties here ...
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="IRSGetBranchName.targets" />
<ItemDefinitionGroup>
<ClCompile>
<AdditionalOptions>/DBRANCHNAME=$(BranchName) /DMORE=BAR</AdditionalOptions>
<ClCompile>
<ItemDefinitionGroup>
</Project>
这个 .props 文件然后被导入到几个 .vcxproj
在我的 GetBranchName_TARGET 中作为消息打印的值如预期的那样正确(显示正确的 TFS 分支名称)。 但是当查看详细构建输出时,值似乎是空的:
1>ClCompile
1> ..\FOO.cpp
1> AdditionalOptions = /DBRANCHNAME= /DMORE=BAR
我试了几个小时但没有找到解决办法,我真的希望有人能帮助这里出了什么问题......
a) 属性 BranchName 是否在全局范围内不可用?我尝试从其他自定义目标打印属性,效果很好!
b) 还是 ClCompile.AdditionalOptions 在执行我的 Target 之前评估/构建?在这种情况下,我该如何重新评估?
c) ...
我非常感谢任何输入。
最佳答案
您应该熟悉 msbuild 评估过程,如所述 here :
When the MSBuild engine begins to process a build file, it is evaluated in a top-down fashion in a multi-pass manner. These passes are described in order in the following list:
- Load all environment and global properties, and toolset properties. In Microsoft Visual Studio 2010, for example, C++ defines several properties in the MSBuild 4.0 toolset.
- Evaluate properties and process imports as encountered
- Evaluate item definitions
- Evaluate items
- Evaluate using tasks
- Start build and reading targets
因此,在您的情况下,ClCompile
的 ItemDefinitionGroup
已在执行 GetBranchName_TARGET 之前进行评估。因此,它在设计上是空的。
为了实现预期的行为,您应该添加以下内容:
<Target Name="GetBranchName_TARGET">
<GetBranchName_TASK sPath="$(MSBuildThisFileDirectory)">
<Output PropertyName="BranchName" TaskParameter="sBranchName" />
</GetBranchName_TASK>
<Message Importance="High" Text="BranchName = $(BranchName)" />
<ItemGroup>
<ClCompile>
<AdditionalOptions>/DBRANCHNAME=$(BranchName) /DMORE=BAR</AdditionalOptions>
</ClCompile>
</ItemGroup>
</Target>
例如,您可以在 ClCompile 中使用 Condition
属性,以便仅包含您的源代码。实际上,您正在寻找的是修改 item metadata after it was declared 的功能.
https://stackoverflow.com/questions/37365451/