Фильтрация метаданных элемента в msbuild - PullRequest
4 голосов
/ 16 февраля 2011

Я хотел бы создать новую коллекцию элементов с измененными метаданными. Например, измените разделители ClCompile.AdditionalIncludeDirectories. Для этого я сначала создаю коллекцию элементов из метаданных AdditionalIncludeDirectories, а затем преобразую ее:

<ItemGroup>
  <IncludeDirs0 Include="%(ClCompile.AdditionalIncludeDirectories)">
    <key>@(ClCompile)</key>
  </IncludeDirs0>
</ItemGroup>

<ItemGroup>
  <IncludeDirs Include="@(IncludeDirs0 -> '-I %(Identity)', ' ')">
    <key>%(IncludeDirs0.key)</key>
  </IncludeDirs>
</ItemGroup>

<ItemGroup>
  <Compile Include="@(ClCompile)">
    <IncludeDirs>@(IncludeDirs)</IncludeDirs>
  </Compile>
</ItemGroup>

Проблема заключается в том, как отфильтровать IncludeDirs по группе элементов компиляции, чтобы каждый элемент компиляции имел право включать dir. (чтобы идентификатор ClCompile равнялся ключу IncludeDirs). Я попытался добавить условие, например: Condition="'%(IncludeDirs.key)'=='%(ClCompile.Identity)'", но безуспешно.
Я мог бы использовать IncludeDirs напрямую: <Message Text="%(IncludeDirs.key) : @(IncludeDirs)"/>, но я чувствую, что это не так, поскольку коллекция Compile должна содержать все метаданные.

Что мне здесь не хватало?

Ответы [ 2 ]

4 голосов
/ 16 февраля 2011

Вы можете сделать это с одной дополнительной целью, которая собирает необходимые предметы.См. MSBuild Batching .

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <ClCompile Include="1" />
    <ClCompile Include="2">
      <AdditionalIncludeDirectories>2.1;2.2;2.3</AdditionalIncludeDirectories>
    </ClCompile>
  </ItemGroup>              

  <Target Name="TransformClCompile"
          Inputs="%(ClCompile.Identity)"
          Outputs="_Non_Existent_Item_To_Batch_">
    <PropertyGroup>
        <IncludeDirs>%(ClCompile.AdditionalIncludeDirectories)</IncludeDirs>
    </PropertyGroup>
    <ItemGroup>
          <IncludeDirs Include="$(IncludeDirs)" />
          <Compile Include="@(ClCompile)">
            <IncludeDirs>@(IncludeDirs ->'-I %(Identity)', ' ')</IncludeDirs>
          </Compile>
    </ItemGroup>                
  </Target>

  <Target Name="Build" DependsOnTargets="TransformClCompile">
     <Message Text="compile %(Compile.Identity) %(Compile.IncludeDirs)" />
  </Target>
</Project>

Выход:

  compile 1 
  compile 2 -I 2.1 -I 2.2 -I 2.3
3 голосов
/ 02 апреля 2012

Есть способы сделать это более кратко в 4.0+, используя свойства свойств.

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <ClCompile Include="1" />
    <ClCompile Include="2">
      <AdditionalIncludeDirectories>2.1;2.2;2.3</AdditionalIncludeDirectories>
    </ClCompile>
  </ItemGroup>

  <Target Name="Build" >

   <Message Text="compile %(ClCompile.Identity)" Condition="'%(ClCompile.AdditionalIncludeDirectories)' ==''"/>

   <Message Text="compile %(ClCompile.Identity) /I $([System.String]::Join(' /I ', $([System.Text.RegularExpressions.Regex]::Split('%(ClCompile.AdditionalIncludeDirectories)', ';'))))" Condition="'%(ClCompile.AdditionalIncludeDirectories)' !=''"/>

  </Target>

</Project>

Вывод

compile 1
compile 2 /I 2.1 /I 2.2 /I 2.3

Это не так уж и красиво, но это немного лучше, я думаю.Regex.Split должен использоваться вместо String.Split, потому что последний нуждается в массиве разделителей, и это немного сложно получить.

Связыватель MSBuild нуждается в некоторых улучшениях, я думаю.

Дэн (msbuild)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...