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

我有一个 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:

  1. 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.
  2. Evaluate properties and process imports as encountered
  3. Evaluate item definitions
  4. Evaluate items
  5. Evaluate using tasks
  6. Start build and reading targets

因此,在您的情况下,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 的功能.

https://stackoverflow.com/questions/37365451/

相关文章:

amazon-s3 - DynamoDB 与 S3 平面文件?

java - 我不能同时使用 ActionListener 和 KeyListener

php - Laravel 自定义分页

android - 调用 overridePendingTransiton 时应用程序卡住

javascript - 使用在 Safari 中不起作用的 javascript 禁用键盘快捷键?

php - Laravel 验证器不区分数字和字符串

android - 如何杀死 fragment ?

jenkins - 在非交互式 shell 中运行 docker 命令

macos - XAMPP 错误 - #1932 - 引擎中不存在表 '---'

javascript - 为什么 tinymce 没有出现在动态添加的文本区域