在msbuild中过滤项目的元数据

时间:2011-02-16 12:14:45

标签: msbuild

我想创建一个带有修改过的元数据的新项目集合。 例如,更改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>

问题是如何在Compile项目组上过滤IncludeDirs,这样每个Compile项目的右边都包含dir。 (以便ClCompile标识等于IncludeDirs键)。 我尝试添加条件如:Condition="'%(IncludeDirs.key)'=='%(ClCompile.Identity)'"但没有任何成功 我本可以直接使用IncludeDirs:<Message Text="%(IncludeDirs.key) : @(IncludeDirs)"/>但我觉得这一点错过了,因为Compile集合应该包含所有的元数据。

我在这里想念的是什么?

2 个答案:

答案 0 :(得分:4)

您可以使用一个额外的目标来收集所需的项目。 请参阅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

答案 1 :(得分:3)

使用属性函数可以在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)