项定义

MSBuild 2.0 版本可让你使用 ItemGroup 元素在项目文件中实现项目的静态声明。 但是,只能在项级别添加元数据,即使所有项的元数据均相同,也是如此。 从 MSBuild 3.5 开始引入了一个名为 ItemDefinitionGroup 的项目元素,从而克服了这一限制。 使用 ItemDefinitionGroup 可以定义一组项定义,这些项定义将默认元数据值添加到命名项类型中的所有项中。

ItemDefinitionGroup 元素紧跟在项目文件的 Project 元素之后。 项定义提供以下功能:

  • 可为目标外部的项定义全局默认元数据。 也就是说,相同的元数据适用于指定类型的所有项。

  • 项目类型可以有多个定义。 当其他元数据规范添加到该类型中时,最新的规范优先。 (元数据遵循与属性相同的导入顺序。)

  • 元数据可具有累加性。 例如,根据要设置的属性,CDefines 值可以有条件地累积。 例如 MT;STD_CALL;DEBUG;UNICODE

  • 可删除元数据。

  • 可使用条件来控制元数据的包含。

项元数据默认值

在 ItemDefinitionGroup 中定义的项元数据仅是默认元数据的声明。 除非定义一个使用 ItemGroup 包含元数据值的项,否则元数据不适用。

注意

在本主题的诸多示例中,尽管显示了 ItemDefinitionGroup 元素,但为清楚起见,省略了相应的 ItemGroup 定义。

ItemGroup 中显式定义的元数据优先于 ItemDefinitionGroup 中的元数据。 ItemDefinitionGroup 中的元数据仅应用于 ItemGroup 中未定义的元数据。 例如:

<ItemDefinitionGroup>
    <i>
        <m>m1</m>
        <n>n1</n>
    </i>
</ItemDefinitionGroup>
<ItemGroup>
    <i Include="a">
        <o>o1</o>
        <n>n2</n>
    </i>
</ItemGroup>

在本例中,默认元数据“m”应用于项“i”,这是由于项“i”没有显式定义元数据“m”。 但是,默认元数据“n”无法应用于项“i”,这是由于元数据“n”已经由项“i”定义。

注意

XML 元素和参数名均区分大小写。 项元数据和项/属性名均不区分大小写。 因此,应将名称中仅大小写不同的 ItemDefinitionGroup 项视作同一个 ItemGroup。

值源

ItemDefinitionGroup 中定义的元数据的值可能来自许多不同的源,如下所示:

  • PropertyGroup 属性

  • ItemDefinitionGroup 中的项

  • ItemDefinitionGroup 项上的项转换

  • 环境变量

  • 全局属性(来自 MSBuild.exe 命令行)

  • 保留属性

  • ItemDefinitionGroup 中项上的常见元数据

  • CDATA 节 <![CDATA[此处的所有内容均未分析]]>

注意

ItemGroup 中的项元数据在 ItemDefinitionGroup 元数据声明中无用,这是因为已在 ItemGroup 元素之前处理 ItemDefinitionGroup 元素。

累加性和多个定义

当添加定义或使用多个 ItemDefinitionGroup 时,请记住以下几点:

  • 将其他元数据规范添加到此类型中。

  • 最新规范优先。

当拥有多个 ItemDefinitionGroup 时,每个后续规范将其元数据添加至先前的定义。 例如:

<ItemDefinitionGroup>
    <i>
        <m>m1</m>
        <n>n1</n>
    </i>
</ItemDefinitionGroup>
<ItemDefinitionGroup>
    <i>
        <o>o1</o>
    </i>
</ItemDefinitionGroup>

在本例中,向“m”和“n”添加元数据“o”。

此外,还可以添加先前定义的元数据值。 例如:

<ItemDefinitionGroup>
    <i>
        <m>m1</m>
    </i>
</ItemDefinitionGroup>
<ItemDefinitionGroup>
    <i>
        <m>%(m);m2</m>
    </i>
</ItemDefinitionGroup>

在本例中,元数据“m”先前定义的值 (m1) 被添加至新值 (m2),因此最终值为“m1;m2”。

注意

在相同的 ItemDefinitionGroup 中也可能出现这种情况。

当替代先前定义的元数据时,最新规范优先。 在下列示例中,元数据“m”的最终值从“m1”变为“m1a”。

<ItemDefinitionGroup>
    <i>
        <m>m1</m>
    </i>
</ItemDefinitionGroup>
<ItemDefinitionGroup>
    <i>
        <m>m1a</m>
    </i>
</ItemDefinitionGroup>

在 ItemDefinitionGroup 中使用条件

可使用 ItemDefinitionGroup 中的条件来控制元数据的包含。 例如:

<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
    <i>
        <m>m1</m>
    </i>
</ItemDefinitionGroup>

在这种情况下,仅当“Configuration”属性的值为“Debug”时,才包括项“i”上的默认元数据“m1”。

注意

在条件中仅支持本地元数据引用。

对项(而非定义组)而言,在先前的 ItemDefinitionGroup 中定义的元数据的引用是本地的。 也就是说,引用的范围特定于项。 例如:

<ItemDefinitionGroup>
    <test>
        <yes>1</yes>
    </test>
    <i>
        <m>m0</m>
        <m Condition="'%(test.yes)'=='1'">m1</m>
    </i>
</ItemDefinitionGroup>

在上述示例中,项“i”在其条件中引用项“test”。 此种情况永远不会为 true,因为 MSBuild 将 ItemDefinitionGroup 中对另一个项的元数据的引用解释为空字符串。 因此,“m”将设置为“m0”。

  <ItemDefinitionGroup>
    <i>
      <m>m0</m>
      <yes>1</yes>
      <m Condition="'%(i.yes)'=='1'">m1</m>
    </i>
  </ItemDefinitionGroup>

在上述示例中,“m”将设置为值“m1”,作为项“yes”的条件引用项“i”的元数据值。

替代和删除元数据

通过将元数据值设置为其他值,在 ItemDefinitionGroup 元素中定义的元数据可以在之后的 ItemDefinitionGroup 元素中被替代。 还可通过将元数据项设置为空值,高效删除元数据项。 例如:

<ItemDefinitionGroup>
    <i>
        <m>m1</m>
    </i>
</ItemDefinitionGroup>
<ItemDefinitionGroup>
    <i>
        <m></m>
    </i>
</ItemDefinitionGroup>

项“i”仍包含元数据“m”,但此时它的值为空。

元数据范围

ItemDefinitionGroups 在定义的位置具有全局范围和全局属性。 ItemDefinitionGroup 中的默认元数据定义可自引用。 例如,以下示例使用了一个简单的元数据引用:

<ItemDefinitionGroup>
    <i>
        <m>m1</m>
        <m>%(m);m2</m>
    </i>
</ItemDefinitionGroup>

还可使用限定的元数据引用:

<ItemDefinitionGroup>
    <i>
        <m>m1</m>
        <m>%(i.m);m2</m>
    </i>
</ItemDefinitionGroup>

但是,以下项无效:

<ItemDefinitionGroup>
    <i>
        <m>m1</m>
        <m>@(x)</m>
    </i>
</ItemDefinitionGroup>

从 MSBuild 3.5 开始,ItemGroups 可以自引用。 例如:

<ItemGroup>
    <item Include="a">
        <m>m1</m>
        <m>%(m);m2</m>
    </item>
</ItemGroup>