Дополнительные параметры компилятора, вычисленные в пользовательской цели

У меня есть пользовательская цель 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

Значение, напечатанное как Message в моем GetBranchName_TARGET, является правильным, как и ожидалось (с указанием правильного имени TFS-Branch). Но при просмотре подробных результатов сборки значение кажется пустым:

1>ClCompile
1>    ..\FOO.cpp
1>        AdditionalOptions = /DBRANCHNAME= /DMORE=BAR

Я пытался часами, но не нашел решения, и я действительно надеюсь, что кто-то поможет, что здесь не так...

а) Свойство BranchName недоступно во всем мире? Я пытался распечатать свойство из других пользовательских целей, и это сработало хорошо!

б) Или ClCompile.AdditionalOptions оценивается / строится до того, как моя цель будет оправдана? В этом случае, как я могу переоценить?

в)...

Я очень благодарен за любой вклад.

1 ответ

Решение

Вы должны быть знакомы с процессом оценки msbuild, как описано здесь:

Когда механизм MSBuild начинает обрабатывать файл сборки, он оценивается многопроходным способом сверху вниз. Эти проходы описаны по порядку в следующем списке:

  1. Загрузить всю среду, глобальные свойства и свойства набора инструментов. Например, в Microsoft Visual Studio 2010 C++ определяет несколько свойств в наборе инструментов MSBuild 4.0.
  2. Оцените свойства и обработайте импорт как обнаруженный
  3. Оценить определения предметов
  4. Оценивать предметы
  5. Оценивать, используя задачи
  6. Начать сборку и чтение целей

Итак, в вашем случае, ItemDefinitionGroup за ClCompile был оценен до выполнения 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>

Вы можете использовать Condition атрибут в ClCompile, чтобы включить, например, только ваши источники. На самом деле, вы ищете возможность изменить метаданные элемента после того, как он был объявлен.

Другие вопросы по тегам