Дополнительные параметры компилятора, вычисленные в пользовательской цели
У меня есть пользовательская цель 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 начинает обрабатывать файл сборки, он оценивается многопроходным способом сверху вниз. Эти проходы описаны по порядку в следующем списке:
- Загрузить всю среду, глобальные свойства и свойства набора инструментов. Например, в Microsoft Visual Studio 2010 C++ определяет несколько свойств в наборе инструментов MSBuild 4.0.
- Оцените свойства и обработайте импорт как обнаруженный
- Оценить определения предметов
- Оценивать предметы
- Оценивать, используя задачи
- Начать сборку и чтение целей
Итак, в вашем случае, 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, чтобы включить, например, только ваши источники. На самом деле, вы ищете возможность изменить метаданные элемента после того, как он был объявлен.