MSBuild 項目
MSBuild 項目是建置系統的輸入,而且它們通常代表檔案 (檔案是在 Include
屬性中指定)。 項目 (Item) 會依據它們的項目 (Element) 名稱分組為項目 (Item) 類型。 項目類型是具名的項目清單,可用來做為工作的參數。 工作會使用項目值來執行建置程序的步驟。
由於項目是根據其所屬的項目類型來命名,因此可交換使用「項目」和「項目值」等詞彙。
在專案檔中建立項目
您會將專案檔中的項目 (Item) 宣告為 ItemGroup 項目 (Element) 的子項目 (Element)。 有效的項目名稱以大寫或小寫字母或底線 (_
) 開頭;有效的後續字元包括英數字元 (字母或數字)、底線和連字號 (-
)。 子項目 (Element) 的名稱是項目 (Item) 的類型。 項目 (Element) 的 Include
屬性會指定要包含於該項目 (Item) 類型的項目 (Item) (檔案)。 例如,下列 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)
) 解譯的路徑,即使項目位於匯入的檔案中,例如 .targets
檔案。
執行期間建立項目
Target 項目 (Element) 以外的項目 (Item) 值是在組建的評估階段所指派。 在後續的執行階段,可以使用下列方式來建立或修改項目:
任何工作均可發出項目。 若要發出項目 (Item),Task 項目 (Element) 必須含有具
ItemName
屬性的子系 Output 項目 (Element)。CreateItem 工作可以發出項目。 這種使用方式已過時。
Target
元素可能會包含 ItemGroup 元素,其中可能包含 Item 元素。
參考專案檔中的項目
若要在整個專案檔中參考項目類型,您可以使用語法 @(ItemType)
。 例如,您應該使用 @(Compile)
,來參考前一個範例中的項目類型。 使用下列語法,您可以藉由指定項目類型做為工作的參數,來將項目傳遞給該工作。 如需詳細資訊,請參閱如何:選取要建置的檔案。
根據預設,項目類型的項目在展開時會以分號 (;) 分隔。 您可以使用語法 @(ItemType, 'separator')
來指定非預設的分隔符號。 如需詳細資訊,請參閱如何:顯示以逗號分隔的項目清單。
使用萬用字元指定項目
您可以使用 **
、*
和 ?
萬用字元指定一組檔案作為組建的輸入,而不是個別列出每個檔案。
?
萬用字元會比對單一字元。*
萬用字元會比對零或多個字元。**
萬用字元會循序比對部分路徑。
例如,您可以在專案檔中使用下列項目,來指定包含該專案檔之目錄中的所有 .cs
檔案。
<CSFile Include="*.cs"/>
下列項目會選取 D:
磁碟機上的所有 .vb
檔案:
<VBFile Include="D:/**/*.vb"/>
如果您想要在沒有萬用字元展開的項目中包含常值 *
或 ?
字元,您必須逸出萬用字元。
如需萬用字元的詳細資訊,請參閱如何:選取要建置的檔案。
使用 Exclude 屬性
Item 項目 (Element) 可以包含 Exclude
屬性,以從項目 (Item) 類型中排除特定的項目 (Item) (檔案)。 Exclude
屬性通常會與萬用字元搭配使用。 例如,下列 XML 會將目錄中的每個 .cs 檔案新增至 CSFile
項目類型,但 DoNotBuild.cs 檔案除外。
<ItemGroup>
<CSFile Include="*.cs" Exclude="DoNotBuild.cs"/>
</ItemGroup>
Exclude
屬性只會影響包含這兩者之 Item 項目 (Element) 中由 Include
屬性所加入的項目 (Item)。 下列範例不會排除 Form1.cs 檔案,這是在前一個 Item 項目中新增的檔案。
<Compile Include="*.cs" />
<Compile Include="*.res" Exclude="Form1.cs">
如需詳細資訊,請參閱如何︰從組建中排除檔案。
項目中繼資料
在 Include
和 Exclude
屬性中,除了資訊,項目可能還會包含中繼資料。 若工作需要更多關於項目的資訊,就會使用此中繼資料,或使用此中繼資料來批次處理工作和目標。 如需詳細資訊,請參閱批次處理。
中繼資料是一個索引鍵值組的集合,可在專案檔中宣告為 Item 項目的子項目。 子項目的名稱是中繼資料的名稱,而子項目的值是中繼資料的值。
中繼資料會與包含它的 Item 項目相關聯。 例如,下列 XML 會將值為 Fr
的 Culture
中繼資料新增至 CSFile
項目類型的 one.cs 和 two.cs 項目。
<ItemGroup>
<CSFile Include="one.cs;two.cs">
<Culture>Fr</Culture>
</CSFile>
</ItemGroup>
項目可以有零或多個中繼資料值。 您可以隨時變更中繼資料值。 如果您將中繼資料設為空值,就能有效地從組建中移除它。
在專案檔中參考項目中繼資料
您可以使用語法 %(ItemMetadataName)
,在整個專案檔中參考項目中繼資料。 如果發生模稜兩可的情況,您可以使用項目類型的名稱來限定參考。 例如,您可以指定 %(ItemType.ItemMetaDataName)
。 下列範例會使用 Display
中繼資料來批次處理 Message
工作。 如需如何使用項目中繼資料進行批次處理的詳細資訊,請參閱工作批次處理中的項目中繼資料。
<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>
已知的項目中繼資料
將項目加入至項目類型時,即會為該項目指派一些已知的中繼資料。 例如,所有項目都具有已知的中繼資料 %(Filename)
,其值為項目的檔案名稱 (不含副檔名)。 如需詳細資訊,請參閱已知的項目中繼資料。
使用中繼資料轉換項目類型
您可以使用中繼資料,來將項目清單轉換為新的項目清單。 例如,您可以使用運算式 @(CppFiles -> '%(Filename).obj')
,將含有代表 .cpp
檔案之項目的項目類型 CppFiles
轉換為 .obj
檔案的對應清單。
下列程式碼會建立 CultureResource
項目類型,其中包含所有具 Culture
中繼資料之 EmbeddedResource
項目的複本。 Culture
中繼資料值會成為新中繼資料 CultureResource.TargetDirectory
的值。
<Target Name="ProcessCultureResources">
<ItemGroup>
<CultureResource Include="@(EmbeddedResource)"
Condition="'%(EmbeddedResource.Culture)' != ''">
<TargetDirectory>%(EmbeddedResource.Culture) </TargetDirectory>
</CultureResource>
</ItemGroup>
</Target>
如需項目的更多作業,請參閱 MSBuild 項目函式和轉換。
項目定義
您可以使用 ItemDefinitionGroup 元素,將預設的中繼資料加入至任何項目類型。 如同已知的中繼資料,預設的中繼資料會與您指定之項目類型的所有項目相關聯。 您可以在項目定義中明確覆寫預設的中繼資料。 例如,下列 XML 會為 Compile
項目 one.cs 和 three.cs,提供值為 "Monday" 的中繼資料 BuildDay
。 此程式碼會為項目 two.cs 提供值為 "Tuesday" 的中繼資料 BuildDay
。
<ItemDefinitionGroup>
<Compile>
<BuildDay>Monday</BuildDay>
</Compile>
</ItemDefinitionGroup>
<ItemGroup>
<Compile Include="one.cs;three.cs" />
<Compile Include="two.cs">
<BuildDay>Tuesday</BuildDay>
</Compile>
</ItemGroup>
如需詳細資訊,請參閱項目定義。
目標 ItemGroup 中的項目屬性
Target
元素可能會包含 ItemGroup 元素,其中可能包含 Item 元素。 如果已針對 ItemGroup
(位於 Target
) 中的項目指定本節中的屬性,則它們是有效的。
移除屬性
Remove
屬性會移除項目類型中的特定項目 (檔案)。 此屬性是在 .NET Framework 3.5 中引入的 (僅限目標內部)。 從 MSBuild 15.0 開始,支援內部和外部目標。
下列範例會從 Compile
項目類型移除每個 .config
檔案。
<Target>
<ItemGroup>
<Compile Remove="*.config"/>
</ItemGroup>
</Target>
MatchOnMetadata 屬性
MatchOnMetadata
屬性只適用於參考其他項目 (例如,Remove="@(Compile);@(Content)"
) 的 Remove
屬性,並指示 Remove
作業根據指定中繼資料名稱的值比對項目,而不是根據項目值進行比對。
B Remove="@(A)" MatchOnMetadata="M"
的比對規則:從具有中繼資料 M
的 B
中移除所有項目,其針對 M
的中繼資料值 V
符合 A
中具有值為 V
之中繼資料 M
的任何項目。
<Project>
<ItemGroup>
<A Include='a1' M1='1' M2='a' M3="e"/>
<A Include='b1' M1='2' M2='x' M3="f"/>
<A Include='c1' M1='3' M2='y' M3="g"/>
<A Include='d1' M1='4' M2='b' M3="h"/>
<B Include='a2' M1='x' m2='c' M3="m"/>
<B Include='b2' M1='2' m2='x' M3="n"/>
<B Include='c2' M1='2' m2='x' M3="o"/>
<B Include='d2' M1='3' m2='y' M3="p"/>
<B Include='e2' M1='3' m2='Y' M3="p"/>
<B Include='f2' M1='4' M3="r"/>
<B Include='g2' M3="s"/>
<B Remove='@(A)' MatchOnMetadata='M1;M2'/>
</ItemGroup>
<Target Name="PrintEvaluation">
<Message Text="%(B.Identity) M1='%(B.M1)' M2='%(B.M2)' M3='%(B.M3)'" />
</Target>
</Project>
在此範例中,項目值 b2
、c2
和 d2
會從項目 B
中移除,因為:
- 來自
B
的b2
和c2
會與M1=2
和M2=x
上來自A
的b1
進行比對 - 來自
B
的d2
會與M1=3
和M2=y
上來自A
的c1
進行比對
Message
工作會輸出下列內容:
a2 M1='x' M2='c' M3='m'
e2 M1='3' M2='Y' M3='p'
f2 M1='4' M2='' M3='r'
g2 M1='' M2='' M3='s'
MSBuild 中 MatchOnMetadata
的範例使用方式:
<_TransitiveItemsToCopyToOutputDirectory Remove="@(_ThisProjectItemsToCopyToOutputDirectory)" MatchOnMetadata="TargetPath" MatchOnMetadataOptions="PathLike" />
這一行會從 _ThisProjectItemsToCopyToOutputDirectory
中移除與 _TransitiveItemsToCopyToOutputDirectory
中的項目具有相同 TargetPath
中繼資料值的項目
MatchOnMetadataOptions 屬性
指定 MatchOnMetadata
用來比對項目之間中繼資料值的字串比對策略 (不區分大小寫的情況下,中繼資料名稱一律相符)。 可能的值為 CaseSensitive
、CaseInsensitive
或 PathLike
。 預設值是 CaseSensitive
。
PathLike
會將路徑感知正規化套用至正規化斜線方向、忽略尾端斜線、排除 .
和 ..
等值,並將所有相對路徑變成目前目錄的絕對路徑。
KeepMetadata 屬性
如果在目標內產生項目 (Item),則 Item 項目 (Element) 可以包含 KeepMetadata
屬性。 如果指定了這個屬性,只會將以分號分隔之名稱清單中指定的中繼資料從來源項目傳輸到目標項目。 若此屬性的值為空值,就相當於未指定它。 KeepMetadata
屬性是在 .NET Framework 4.5 中引入的。
下列範例示範如何使用 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:
-->
RemoveMetadata 屬性
如果在目標內產生項目 (Item),則 Item 項目 (Element) 可以包含 RemoveMetadata
屬性。 如果指定了此屬性,則會將所有中繼資料從來源項目傳輸到目標項目,但名稱位於以分號分隔之名稱清單內的中繼資料除外。 若此屬性的值為空值,就相當於未指定它。 RemoveMetadata
屬性是在 .NET Framework 4.5 中引入的。
下列範例示範如何使用 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:
-->
如需項目的更多作業,請參閱 MSBuild 項目函式。
KeepDuplicates 屬性
如果在目標內產生項目 (Item),則 Item 項目 (Element) 可以包含 KeepDuplicates
屬性。 KeepDuplicates
為 Boolean
屬性,會指定項目如果與現有項目完全重複,是否應加入目標群組。
如果來源和目標項目具有相同的 Include
值,但中繼資料不同,則即使 KeepDuplicates
設定為 false
,也會加入該項目。 若此屬性的值為空值,就相當於未指定它。 KeepDuplicates
屬性是在 .NET Framework 4.5 中引入的。
下列範例示範如何使用 KeepDuplicates
屬性。
<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
-->
由於除了項目值之外,KeepDuplicates
屬性也會考量項目的中繼資料,因此務必知道中繼資料發生什麼事情。 例如,請參閱使用中繼資料項目函式時偵測重複項目。
更新目標外部 ItemGroup 中項目的中繼資料
目標外部的項目可透過 Update
屬性更新其現有的中繼資料。 此屬性不適用於目標之下的項目。
<Project>
<PropertyGroup>
<MetadataToUpdate>pencil</MetadataToUpdate>
</PropertyGroup>
<ItemGroup>
<Item1 Include="stapler">
<Size>medium</Size>
<Color>black</Color>
<Material>plastic</Material>
</Item1>
<Item1 Include="pencil">
<Size>small</Size>
<Color>yellow</Color>
<Material>wood</Material>
</Item1>
<Item1 Include="eraser">
<Color>red</Color>
</Item1>
<Item1 Include="notebook">
<Size>large</Size>
<Color>white</Color>
<Material>paper</Material>
</Item1>
<Item2 Include="notebook">
<Size>SMALL</Size>
<Color>YELLOW</Color>
</Item2>
<!-- Metadata can be expressed either as attributes or as elements -->
<Item1 Update="$(MetadataToUpdate);stapler;er*r;@(Item2)" Price="10" Material="">
<Color>RED</Color>
</Item1>
</ItemGroup>
<Target Name="MyTarget">
<Message Text="Item1: %(Item1.Identity)
Size: %(Item1.Size)
Color: %(Item1.Color)
Material: %(Item1.Material)
Price: %(Item1.Price)" />
</Target>
</Project>
<!--
Item1: stapler
Size: medium
Color: RED
Material:
Price: 10
Item1: pencil
Size: small
Color: RED
Material:
Price: 10
Item1: eraser
Size:
Color: RED
Material:
Price: 10
Item1: notebook
Size: large
Color: RED
Material:
Price: 10
-->
在 MSBuild 16.6 版和更新版本中,Update
屬性支援合格的中繼資料參考,以利從兩個或多個項目匯入中繼資料。
<Project>
<ItemGroup>
<Item1 Include="stapler">
<Size>medium</Size>
<Color>black</Color>
<Material>plastic</Material>
</Item1>
<Item1 Include="pencil">
<Size>small</Size>
<Color>yellow</Color>
<Material>wood</Material>
</Item1>
<Item1 Include="eraser">
<Size>small</Size>
<Color>red</Color>
<Material>gum</Material>
</Item1>
<Item1 Include="notebook">
<Size>large</Size>
<Color>white</Color>
<Material>paper</Material>
</Item1>
<Item2 Include="pencil">
<Size>MEDIUM</Size>
<Color>RED</Color>
<Material>PLASTIC</Material>
<Price>10</Price>
</Item2>
<Item3 Include="notebook">
<Size>SMALL</Size>
<Color>BLUE</Color>
<Price>20</Price>
</Item3>
<!-- Metadata can be expressed either as attributes or as elements -->
<Item1 Update="@(Item2);er*r;@(Item3)" Size="%(Size)" Color="%(Item2.Color)" Price="%(Item3.Price)" Model="2020">
<Material Condition="'%(Item2.Material)' != ''">Premium %(Item2.Material)</Material>
</Item1>
</ItemGroup>
<Target Name="MyTarget">
<Message Text="Item1: %(Item1.Identity)
Size: %(Item1.Size)
Color: %(Item1.Color)
Material: %(Item1.Material)
Price: %(Item1.Price)
Model: %(Item1.Model)" />
</Target>
</Project>
<!--
Item1: stapler
Size: medium
Color: black
Material: plastic
Price:
Model:
Item1: pencil
Size: small
Color: RED
Material: Premium PLASTIC
Price:
Model: 2020
Item1: eraser
Size: small
Color:
Material: gum
Price:
Model: 2020
Item1: notebook
Size: large
Color:
Material: paper
Price: 20
Model: 2020
-->
備註:
- 不合格的中繼資料 (
%(MetadataName)
) 會繫結至正在更新的項目類型 (上述範例中的Item1
)。 合格的中繼資料 (%(Item2.Color)
) 會在 Update 運算式中擷取的相符項目類型集合內繫結。 - 如果項目在多個參照項目之內和之間多次符合:
- 系統會從每個參照項目類型擷取最後出現的項目 (因此每個項目類型都會擷取一個項目)。
- 這符合目標之下的工作項目批次處理行為。
- 其中可以放置 %() 參考:
- 中繼資料
- 中繼資料條件
- 中繼資料名稱比對不區分大小寫。
在目標的 ItemGroup 中更新項目的中繼資料
中繼資料也可經由表達能力比 Update
差的語法在目標內修改:
<Project>
<ItemGroup>
<Item1 Include="stapler">
<Size>medium</Size>
<Color>black</Color>
<Material>plastic</Material>
</Item1>
<Item1 Include="pencil">
<Size>small</Size>
<Color>yellow</Color>
<Material>wood</Material>
</Item1>
<Item1 Include="eraser">
<Size>small</Size>
<Color>red</Color>
<Material>gum</Material>
</Item1>
<Item1 Include="notebook">
<Size>large</Size>
<Color>white</Color>
<Material>paper</Material>
</Item1>
<Item2 Include="pencil">
<Size>MEDIUM</Size>
<Color>RED</Color>
<Material>PLASTIC</Material>
<Price>10</Price>
</Item2>
<Item2 Include="ruler">
<Color>GREEN</Color>
</Item2>
</ItemGroup>
<Target Name="MyTarget">
<ItemGroup>
<!-- Metadata can be expressed either as attributes or as elements -->
<Item1 Size="GIGANTIC" Color="%(Item2.Color)">
<Material Condition="'%(Item2.Material)' != ''">Premium %(Item2.Material)</Material>
</Item1>
</ItemGroup>
<Message Text="Item1: %(Item1.Identity)
Size: %(Item1.Size)
Color: %(Item1.Color)
Material: %(Item1.Material)
Price: %(Item1.Price)
Model: %(Item1.Model)" />
</Target>
</Project>
<!--
Item1: stapler
Size: GIGANTIC
Color: GREEN
Material: Premium PLASTIC
Price:
Model:
Item1: pencil
Size: GIGANTIC
Color: GREEN
Material: Premium PLASTIC
Price:
Model:
Item1: eraser
Size: GIGANTIC
Color: GREEN
Material: Premium PLASTIC
Price:
Model:
Item1: notebook
Size: GIGANTIC
Color: GREEN
Material: Premium PLASTIC
Price:
Model:
-->