MSBuild项目是构建系统的输入,通常代表文件(文件在Include
属性中指定)。根据项目的元素名称将项目分组为项目类型。项目类型是可以用作任务参数的项目的命名列表。任务使用项目值执行构建过程的步骤。
在porject file中创建item
将项目文件中的项目声明为ItemGroup元素的子元素。子元素的名称是项目类型。Include
元素的属性指定要包含在该项目类型中的项目(文件)。例如,以下XML创建名为的项目类型Compile
,其中包括两个文件。
<ItemGroup>
<Compile Include = "file1.cs"/>
<Compile Include = "file2.cs"/>
</ItemGroup>
项目file2.cs不会替代项目file1.cs;而是将文件名附加到Compile
项目类型的值列表中。
以下XML通过在一个Include
属性中声明两个文件来创建相同的项目类型。请注意,文件名用分号分隔。
<ItemGroup>
<Compile Include = "file1.cs;file2.cs"/>
</ItemGroup>
Include
属性是相对于项目文件的文件夹$(MSBuildProjectPath)进行解释的路径,即使该项目位于导入的文件
在执行期间创建项目
在构建的评估阶段,将为目标元素以外的项目分配值。在后续执行阶段中,可以通过以下方式创建或修改项目:
-
该CreateItem任务可以发出一个项目。不建议使用此用法。
-
从.NET Framework 3.5开始,
Target
元素可能包含可能包含项目元素的ItemGroup元素。
项目文件中的参考项目
要在整个项目文件中引用项目类型,请使用语法@(<ItemType>)。例如,您可以使用来引用上一个示例中的项目类型@(Compile)
。通过使用此语法,可以通过将项目类型指定为该任务的参数来将项目传递给任务。
1,声明某个项目
<CSFile Include="form1.cs"/>
<VBFile Include="form1.vb"/>
2,声明多个项目
<CSFile Include="form1.cs;form2.cs"/>
<VBFile Include="form1.vb;form2.vb"/>
3.通过通配符指定输入:
将所有.jpg文件包含在Images目录和子目录中:Include="Images\**\*.jpg"
包括所有以img开头的.jpg文件 :Include="Images\**\img*.jpg"
将名称以jpgs结尾的所有文件包括在目录中:Include="Images\**\*jpgs\*.*" or Include="Images\**\*jpgs\*"
4,将项目传递给任务
将所有Visual C#或Visual Basic文件用作输入
使用Include
类似于以下内容的属性:
<CSC Sources="@(CSFile)">...</CSC>
要么
<VBC Sources="@(VBFile)">...</VBC>
<Project DefaultTargets="Compile"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
<PropertyGroup>
<Builtdir>built</Builtdir>
</PropertyGroup>
<ItemGroup>
<CSFile Include="Form1.cs"/>
<CSFile Include="AssemblyInfo.cs"/>
<Reference Include="System.dll"/>
<Reference Include="System.Data.dll"/>
<Reference Include="System.Drawing.dll"/>
<Reference Include="System.Windows.Forms.dll"/>
<Reference Include="System.XML.dll"/>
</ItemGroup>
<Target Name="PreBuild">
<Exec Command="if not exist $(builtdir) md $(builtdir)"/>
</Target>
<Target Name="Compile" DependsOnTargets="PreBuild">
<Csc Sources="@(CSFile)"
References="@(Reference)"
OutputAssembly="$(builtdir)\$(MSBuildProjectName).exe"
TargetType="exe" />
</Target>
</Project>
使用通配符指定项目
例如,您可以.cs
通过使用项目文件中的以下元素来指定包含项目文件的目录中的所有文件。
<CSFile Include="*.cs"/>
以下元素选择驱动器.vb
上的所有文件D:
:
<VBFile Include="D:/**/*.vb"/>
使用排除属性
项目元素可以包含Exclude
属性,该属性从项目类型中排除特定项目(文件)。
<ItemGroup>
<CSFile Include="*.cs" Exclude="DoNotBuild.cs"/>
</ItemGroup>
该Exclude
属性仅影响该Include
属性在包含它们的item元素中添加的项目。以下示例不会排除文件Form1.cs,该文件已添加到前面的item元素中。
<Compile Include="*.cs" />
<Compile Include="*.res" Exclude="Form1.cs">
项目元数据
除了Include
和Exclude
属性中的信息外,项目还可能包含元数据
元数据是键值对的集合,这些键值对在项目文件中声明为item元素的子元素。子元素的名称是元数据的名称,子元素的值是元数据的值。
元数据与包含它的item元素相关联。例如,以下将Culture
元数据添加值Fr
到CSFile项类型的one.cs和two.cs项中。
<ItemGroup>
<CSFile Include="one.cs;two.cs">
<Culture>Fr</Culture>
</CSFile>
</ItemGroup>
一个项目可以具有零个或多个元数据值。您可以随时更改元数据值。如果将元数据设置为空值,则可以有效地将其从构建中删除。
项目文件中的参考项目元数据
您可以使用语法%(<ItemMetadataName>)引用整个项目文件中的项目元数据。如果存在歧义,则可以使用项目类型的名称来限定引用。例如,您可以指定%(<ItemType.ItemMetaDataName>)。
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Stuff Include="One.cs" >
<Display>false</Display>
</Stuff>
<Stuff Include="Two.cs">
<Display>true</Display>
</Stuff>
</ItemGroup>
<Target Name="Batching">
<Message Text="@(Stuff)" Condition=" '%(Display)' == 'true' "/>
</Target>
</Project>
通过使用元数据来转换项目类型
您可以使用元数据将项目列表转换为新的项目列表。例如,您可以使用表达式CppFiles
将具有表示.cpp文件的项目的项目类型转换为.obj文件的相应列表@(CppFiles -> '%(Filename).obj')
。
以下代码创建一个CultureResource
项目类型,其中包含EmbeddedResource
带有Culture
元数据的所有项目的副本。该Culture
元数据值将成为新的元数据的价值CultureResource.TargetDirectory
。
<Target Name="ProcessCultureResources">
<ItemGroup>
<CultureResource Include="@(EmbeddedResource)"
Condition="'%(EmbeddedResource.Culture)' != ''">
<TargetDirectory>%(EmbeddedResource.Culture) </TargetDirectory>
</CultureResource>
</ItemGroup>
</Target>
项目定义
默认元数据添加到任何项目类型。像众所周知的元数据一样,默认元数据与您指定的项目类型的所有项目相关联。您可以在项目定义中显式覆盖默认元数据
在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>
加性和多重定义
添加定义或使用多个ItemDefinitionGroups时,请记住以下几点:
-
其他元数据规范已添加到该类型。
-
最后的规范优先。
当您有多个ItemDefinitionGroups时,每个后续规范都将其元数据添加到先前的定义中。例如:
<ItemDefinitionGroup>
<i>
<m>m1</m>
<n>n1</n>
</i>
</ItemDefinitionGroup>
<ItemDefinitionGroup>
<i>
<o>o1</o>
</i>
</ItemDefinitionGroup>
在该示例中,元数据“ o”被添加到“ m”和“ n”。
另外,还可以添加先前定义的元数据值。例如:
<ItemDefinitionGroup>
<i>
<m>m1</m>
</i>
</ItemDefinitionGroup>
<ItemDefinitionGroup>
<i>
<m>%(m);m2</m>
</i>
</ItemDefinitionGroup>
在此示例中,先前为元数据“ m”(m1)定义的值被添加到新值(m2),因此最终值为“ m1; m2”。
目标的项目组中项目的属性
1,remove 属性
Remove
属性从项目类型中删除特定的项目(文件)
下面的示例从“编译”项类型中删除每个.config文件。
<Target>
<ItemGroup>
<Compile Remove="*.config"/>
</ItemGroup>
</Target>
2,KeepMetadata属性
如果在目标内生成项目,则item元素可以包含KeepMetadata
属性。如果指定了此属性,则仅将用分号分隔的名称列表中指定的元数据从源项目传输到目标项目。此属性的空值等效于不指定它。
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
ToolsVersion="4.0">
<ItemGroup>
<FirstItem Include="rhinoceros">
<Class>mammal</Class>
<Size>large</Size>
</FirstItem>
</ItemGroup>
<Target Name="MyTarget">
<ItemGroup>
<SecondItem Include="@(FirstItem)" KeepMetadata="Class" />
</ItemGroup>
<Message Text="FirstItem: %(FirstItem.Identity)" />
<Message Text=" Class: %(FirstItem.Class)" />
<Message Text=" Size: %(FirstItem.Size)" />
<Message Text="SecondItem: %(SecondItem.Identity)" />
<Message Text=" Class: %(SecondItem.Class)" />
<Message Text=" Size: %(SecondItem.Size)" />
</Target>
</Project>
<!--
Output:
FirstItem: rhinoceros
Class: mammal
Size: large
SecondItem: rhinoceros
Class: mammal
Size:
-->
因为KeepMetadata="Class",所以将FirstItem里面的class元素赋值给了SecondItem 的class元素,而size则没有赋值,所以为空
3.RemoveMetadata属性
如果在目标内生成项目,则item元素可以包含RemoveMetadata
属性。如果指定了此属性,则所有元数据都会从源项目传输到目标项目,但其名称包含在以分号分隔的名称列表中的元数据除外。此属性的空值等效于不指定它。
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MetadataToRemove>Size;Material</MetadataToRemove>
</PropertyGroup>
<ItemGroup>
<Item1 Include="stapler">
<Size>medium</Size>
<Color>black</Color>
<Material>plastic</Material>
</Item1>
</ItemGroup>
<Target Name="MyTarget">
<ItemGroup>
<Item2 Include="@(Item1)" RemoveMetadata="$(MetadataToRemove)" />
</ItemGroup>
<Message Text="Item1: %(Item1.Identity)" />
<Message Text=" Size: %(Item1.Size)" />
<Message Text=" Color: %(Item1.Color)" />
<Message Text=" Material: %(Item1.Material)" />
<Message Text="Item2: %(Item2.Identity)" />
<Message Text=" Size: %(Item2.Size)" />
<Message Text=" Color: %(Item2.Color)" />
<Message Text=" Material: %(Item2.Material)" />
</Target>
</Project>
<!--
Output:
Item1: stapler
Size: medium
Color: black
Material: plastic
Item2: stapler
Size:
Color: black
Material:
-->
因为最开始定义去除的元素有<MetadataToRemove>Size;Material</MetadataToRemove>,所以item1中的这两个元素没有传递,只传递了color
4,KeepDuplicates属性
如果在目标内生成项目,则item元素可以包含KeepDuplicates
属性。KeepDuplicates
是一个Boolean
属性,用于指定如果该项目与现有项目完全相同,则是否应将其添加到目标组。
如果源项目和目标项目具有相同的包含值,但元数据不同,则即使将项目设置为KeepDuplicates
,也会添加该项目false
。此属性的空值等效于不指定它。
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Item1 Include="hourglass;boomerang" />
<Item2 Include="hourglass;boomerang" />
</ItemGroup>
<Target Name="MyTarget">
<ItemGroup>
<Item1 Include="hourglass" KeepDuplicates="false" />
<Item2 Include="hourglass" />
</ItemGroup>
<Message Text="Item1: @(Item1)" />
<Message Text=" %(Item1.Identity) Count: @(Item1->Count())" />
<Message Text="Item2: @(Item2)" />
<Message Text=" %(Item2.Identity) Count: @(Item2->Count())" />
</Target>
</Project>
<!--
Output:
Item1: hourglass;boomerang
hourglass Count: 1
boomerang Count: 1
Item2: hourglass;boomerang;hourglass
hourglass Count: 2
boomerang Count: 1
-->