【问题标题】:Filtering Item's Metadata in msbuild在 msbuild 中过滤项目的元数据
【发布时间】:2017-09-29 00:20:33
【问题描述】:

我想用修改后的元数据创建一个新的项目集合。 例如,更改 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 项目都有其正确的包含目录。 (以便 ClCompile 标识等于 IncludeDirs 键)。 我尝试添加一个条件,例如:Condition="'%(IncludeDirs.key)'=='%(ClCompile.Identity)'",但没有任何成功。
我本可以直接使用 IncludeDirs:&lt;Message Text="%(IncludeDirs.key) : @(IncludeDirs)"/&gt;,但我觉得这没有抓住重点,因为 Compile 集合应该包含所有元数据。

我错过了什么?

【问题讨论】:

    标签: msbuild


    【解决方案1】:

    您可以使用一个额外的目标来收集所需物品。 见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
    

    【讨论】:

    • 而不是 我们在 Microsoft .目标文件是:当然,如果已经有条件,你“和”它。
    • 呃,我只是不知道如何使代码在评论中看起来正确。
    • 那个答案是不正确的,我相信,无趣的沼泽。这是我在尝试使用“更清洁”模式时得到的结果:错误 MSB4116:“CopySourceAsContent”目标上的条件“'%(SupportedFramework.Identity)' != ''”引用了项目元数据。对项目元数据的引用并非全部归于目标条件,除非它们是项目转换的一部分。
    • 是否需要指定Outputs="_Non_Existent_Item_To_Batch"?如果是这样,选择的名称是唯一命名的输出是否重要?
    【解决方案2】:

    在 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 binder 需要一些改进。

    丹(msbuild)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-29
      • 1970-01-01
      • 1970-01-01
      • 2021-10-24
      • 2015-02-19
      相关资源
      最近更新 更多