MSBuild 專案是建置系統的輸入,而且通常代表檔案(檔案是在 屬性中 Include 指定)。 項目會根據其項目名稱分組為項目類型。 項目類型是可做為工作參數的專案命名清單。 工作會使用專案值來執行建置程式的步驟。
由於專案是由其所屬的項目類型來命名,因此可以交替使用「專案」和「專案值」等字詞。
在項目檔中建立專案
您可以將項目檔中的專案宣告為 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)即使項目位於如檔案的匯入檔案中也一 .targets 樣。
在執行期間建立專案
在組建的評估階段, 在 Target 元素外部的專案會指派值。 在後續執行階段期間,您可以透過下列方式建立或修改專案:
CreateItem 工作可以發出專案。 此使用方式已被取代。
Target元素可能包含可能包含項目元素的 ItemGroup 元素。
參考項目檔中的專案
若要在整個項目檔中參考項目類型,請使用語法 @(ItemType)。 例如,您會使用 @(Compile)參考上一個範例中的項目類型。 藉由使用此語法,您可以將項目類型指定為該工作的參數,以將專案傳遞至工作。 如需詳細資訊,請參閱 如何:選取要建置的檔案。
根據預設,專案類型的專案會以分號分隔(;)展開時。 您可以使用 語法 @(ItemType, 'separator') 來指定預設值以外的分隔符。 如需詳細資訊,請參閱 如何:顯示以逗號分隔的項目清單。
使用通配符來指定專案
您可以使用 **、 *和 ? 通配符,將檔案群組指定為組建的輸入,而不是個別列出每個檔案。
-
?通配符符合單一字元。 -
*通配符符合零個或多個字元。 -
**通配符序列符合部分路徑。
例如,您可以使用項目檔中的下列元素,指定目錄中包含專案檔的所有 .cs 檔案。
<CSFile Include="*.cs"/>
下列元素會選取磁碟驅動器上D:的所有.vb檔案:
<VBFile Include="D:/**/*.vb"/>
如果您想要在沒有通配符展開的專案中包含常值 * 或 ? 字元,則必須 逸出通配符。
如需通配符的詳細資訊,請參閱 如何:選取要建置的檔案。
使用 Exclude 屬性
項目專案可以包含 Exclude 屬性,該屬性會從項目類型中排除特定專案(檔案)。 屬性 Exclude 通常與通配符搭配使用。 例如,下列 XML 會將目錄中的每個 .cs 檔案新增至 CSFile 項目類型,但 DoNotBuild.cs 檔案除外。
<ItemGroup>
<CSFile Include="*.cs" Exclude="DoNotBuild.cs"/>
</ItemGroup>
屬性 Exclude 只會影響包含兩者之專案之專案元素中的 屬性所加入 Include 的專案。 下列範例不會排除在上述項目專案中新增的 檔案Form1.cs。
<Compile Include="*.cs" />
<Compile Include="*.res" Exclude="Form1.cs">
如需詳細資訊,請參閱 如何:從組建中排除檔案。
項目元數據
除了 和 Exclude 屬性中的Include資訊之外,專案也可以包含元數據。 此元數據可供需要專案的詳細資訊或批次工作和目標的工作使用。 如需詳細資訊,請參閱 Batching。
元數據是項目檔中宣告為專案專案的子專案之索引鍵/值組集合。 子專案的名稱是元數據的名稱,而子專案的值則是元數據的值。
元數據與包含元數據的專案專案相關聯。 例如,下列 XML 會將具有 值的Fr元數據新增Culture至專案類型的one.cs和two.cs專案CSFile。
<ItemGroup>
<CSFile Include="one.cs;two.cs">
<Culture>Fr</Culture>
</CSFile>
</ItemGroup>
專案可以有零個或多個元數據值。 您可以隨時變更元數據值。 如果您將元數據設定為空值,則會有效地從組建中移除它。
參考項目檔中的項目元數據
您可以使用 語法 %(ItemMetadataName),在整個項目檔中參考項目元數據。 如果存在模棱兩可,您可以使用專案類型的名稱來限定參考。 例如,您可以指定 %(ItemType.ItemMetaDataName)。 下列範例會 Display 使用元數據來批處理工作 Message 。 如需如何使用專案元數據進行批處理的詳細資訊,請參閱 工作批處理中的專案元數據。
<Project>
<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檔案的專案的項目轉換成對應的檔案清單.obj的項目類型CppFiles。
下列程式代碼會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 ,並以 「Monday」 值 three.cs 元數據 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 元素。 當針對 中的 ItemGroup 專案指定屬性時, Target本節中的屬性是有效的。
拿掉屬性
屬性 Remove 會從專案類型中移除特定專案(檔案)。 此屬性是在 .NET Framework 3.5 中引進的(僅限目標內部)。 從 MSBuild 15.0 開始,支持內外目標。
下列範例會從Compile項目類型中移除每個.config檔案。
<Target>
<ItemGroup>
<Compile Remove="*.config"/>
</ItemGroup>
</Target>
MatchOnMetadata 屬性
屬性 MatchOnMetadata 只適用於 Remove 參考其他項目的屬性(例如 Remove="@(Compile);@(Content)"),並指示 Remove 作業根據指定元數據名稱的值比對專案,而不是根據專案值比對。
比對B Remove="@(A)" MatchOnMetadata="M"規則:從中移除具有元數據M的所有專案B,其元數據值MV會比對值 元數據MV的任何A專案。
<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 中移除,因為:
-
b2和c2fromBmatch 對b1onAM1=2和M2=x -
d2fromBmatches from fromc1AonM1=3andM2=y
工作 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'
<_TransitiveItemsToCopyToOutputDirectory Remove="@(_ThisProjectItemsToCopyToOutputDirectory)" MatchOnMetadata="TargetPath" MatchOnMetadataOptions="PathLike" />
這一行會從 _TransitiveItemsToCopyToOutputDirectory 中移除具有相同 TargetPath 元數據值的專案 _ThisProjectItemsToCopyToOutputDirectory
MatchOnMetadataOptions 屬性
指定用來 MatchOnMetadata 比對項目之間元數據值的字串比對策略(元數據名稱一律不區分大小寫)。 可能的值為 CaseSensitive、CaseInsensitive 或 PathLike。 預設值是 CaseSensitive。
PathLike 將路徑感知正規化套用至正規化斜線方向、忽略尾端斜線、消除 . 和 ..等值,並將所有相對路徑設為絕對相對於目前目錄。
KeepMetadata 屬性
如果專案是在目標內產生,則專案專案可以包含 KeepMetadata 屬性。 如果指定這個屬性,只有以分號分隔的名稱清單中指定的元數據,才會從來源專案傳送至目標專案。 這個屬性的空白值相當於不指定它。 屬性 KeepMetadata 是在 .NET Framework 4.5 中引進的。
下列範例說明如何使用 KeepMetadata 屬性。
<Project>
<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 屬性
如果專案是在目標內產生,則專案專案可以包含 RemoveMetadata 屬性。 如果指定這個屬性,則所有元數據都會從來源專案傳輸到目標專案,但名稱包含在以分號分隔的名稱清單中以外的元數據除外。 這個屬性的空白值相當於不指定它。 屬性 RemoveMetadata 是在 .NET Framework 4.5 中引進的。
下列範例說明如何使用 RemoveMetadata 屬性。
<Project>
<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 屬性
如果專案是在目標內產生,則專案專案可以包含 KeepDuplicates 屬性。
KeepDuplicates 是屬性 Boolean ,指定如果專案與現有專案完全重複,是否應該將專案加入目標群組。
如果來源和目標專案具有相同 Include 的值,但不同的元數據,即使 KeepDuplicates 設定為 false,也會加入專案。 這個屬性的空白值相當於不指定它。 屬性 KeepDuplicates 是在 .NET Framework 4.5 中引進的。
下列範例說明如何使用 KeepDuplicates 屬性。
<Project>
<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因為 屬性除了專案值之外,也會考慮專案的元數據,因此請務必知道元數據發生的情況。 例如,請參閱 使用元數據專案函式時偵測重複專案。
更新 Target 外部 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:
-->