在自定义目标中计算的编译器附加选项
Posted
技术标签:
【中文标题】在自定义目标中计算的编译器附加选项【英文标题】:Compiler Additional Options computed in a custom Target 【发布时间】:2016-05-21 16:27:03 【问题描述】:我有一个 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 分支名称)。 但是当查看 Detailed Build Output 时,Value 似乎是空的:
1>ClCompile
1> ..\FOO.cpp
1> AdditionalOptions = /DBRANCHNAME= /DMORE=BAR
我尝试了几个小时,但没有找到解决方案,我真的希望有人帮助这里出了什么问题......
a) 属性 BranchName 是否在全球范围内不可用?我尝试从其他自定义目标打印属性并且效果很好!
b) 还是在执行我的 Target 之前评估/构建了 ClCompile.AdditionalOptions?在这种情况下,我该如何重新评估?
c) ...
我非常感谢任何输入。
【问题讨论】:
a) 是的,它是 b) 是的,因为它是在目标之外全局定义的,它在目标运行之前被评估,这就是你的问题。我不是 100% 确定,但将 itemDefinitionGroup 与 ClCompile inside GetBranchName_TARGET 应该可以工作 @stijn:谢谢。您的评论使我找到了完美的解决方案。就像 stukselbax 的答案一样。谢谢! 【参考方案1】:您应该熟悉 msbuild 评估过程,如 here 所述:
当 MSBuild 引擎开始处理构建文件时,它会以自上而下的方式以多遍方式进行评估。这些通行证在以下列表中按顺序描述:
加载所有环境和全局属性,以及工具集属性。例如,在 Microsoft Visual Studio 2010 中,C++ 在 MSBuild 4.0 工具集中定义了多个属性。 评估遇到的属性并处理导入 评估项目定义 评估项目 使用任务进行评估 开始构建和读取目标
因此,在您的情况下,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的功能。
【讨论】:
以上是关于在自定义目标中计算的编译器附加选项的主要内容,如果未能解决你的问题,请参考以下文章
TFS2008递归复制文件并不总是有效(编译vs2003)(AfterCompile目标)
在自定义 UINavigationBar 中绘图,附加到顶部
gcc编译器选项-Wl,--no-undefined(告诉链接器在链接过程中不允许有未定义的符号)(gcc编译器和链接器是分离的工具,它们需要通过选项来进行通信)