在自定义目标中计算的编译器附加选项

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 工具集中定义了多个属性。 评估遇到的属性并处理导入 评估项目定义 评估项目 使用任务进行评估 开始构建和读取目标

因此,在您的情况下,ClCompileItemDefinitionGroup 在执行 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的功能。

【讨论】:

以上是关于在自定义目标中计算的编译器附加选项的主要内容,如果未能解决你的问题,请参考以下文章

如何在自定义 Xcode 项目模板中创建或定义新目标

OpenCV 无法在自定义目录中编译

TFS2008递归复制文件并不总是有效(编译vs2003)(AfterCompile目标)

在自定义 UINavigationBar 中绘图,附加到顶部

如何在自定义原型方法中附加 socket.io 事件?

gcc编译器选项-Wl,--no-undefined(告诉链接器在链接过程中不允许有未定义的符号)(gcc编译器和链接器是分离的工具,它们需要通过选项来进行通信)