Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
MSBuild, öğe listelerini öğe meta verilerine göre farklı kategorilere veya toplu işlemlere böler ve her toplu işlemle bir kez bir hedef veya görev çalıştırır.
Görev gruplama
Görev toplu işlemi, öğe listelerini farklı toplu işlemlere bölmenin ve bu toplu işlerden her birini ayrı olarak bir göreve geçirmenin bir yolunu sağlayarak proje dosyalarınızı basitleştirmenizi sağlar. Toplu işlem, bir proje dosyasının birkaç kez çalıştırılsa bile görevi ve özniteliklerini yalnızca bir kez bildirilmesi gerektiği anlamına gelir.
MSBuild'in bir görev özniteliğinde %(ItemMetaDataName) gösterimini kullanarak bir görevle toplu işlem yapmasını istediğinizi belirtirsiniz. Aşağıdaki örnek, Example öğe listesini Color öğe meta veri değerine göre gruplara böler ve bu grupların her birini ayrı ayrı MyTask görevine iletir.
Uyarı
Görev özniteliklerinin başka bir yerinde öğe listesine başvurmuyorsanız veya meta veri adı belirsiz olabilirse, toplu işlem için kullanılacak öğe meta veri değerini tam olarak nite etmek için %(<ItemCollection.ItemMetaDataName>) gösterimini kullanabilirsiniz.
<Project>
<ItemGroup>
<Example Include="Item1">
<Color>Blue</Color>
</Example>
<Example Include="Item2">
<Color>Red</Color>
</Example>
</ItemGroup>
<Target Name="RunMyTask">
<MyTask
Sources = "@(Example)"
Output = "%(Color)\MyFile.txt"/>
</Target>
</Project>
Daha ayrıntılı toplu işleme örnekleri için bkz . Görev toplu işlemede öğe meta verileri.
Hedef gruplama
MSBuild, hedefi çalıştırmadan önce hedefin giriş ve çıkışlarının güncel olup olmadığını denetler. Hem girişler hem de çıkışlar güncelse hedef atlanır. Hedefin içindeki bir görev toplu işlem kullanıyorsa, MSBuild'in her öğe toplu işlemi için giriş ve çıkışların güncel olup olmadığını belirlemesi gerekir. Aksi takdirde, hedef komutu her vurulduğunda çalıştırılır.
Aşağıdaki örnek, Target gösterimini içeren %(ItemMetadataName), Outputs özniteliğine sahip bir öğe göstermektedir. MSBuild, öğe listesini öğe meta verilerine göre Example toplu işlemlere böler Color ve her toplu işlem için çıkış dosyalarının zaman damgalarını analiz eder. Toplu iş çıktıları güncel değilse hedef çalıştırılır. Aksi takdirde hedef atlanır.
<Project>
<ItemGroup>
<Example Include="Item1">
<Color>Blue</Color>
</Example>
<Example Include="Item2">
<Color>Red</Color>
</Example>
</ItemGroup>
<Target Name="RunMyTask"
Inputs="@(Example)"
Outputs="%(Color)\MyFile.txt">
<MyTask
Sources = "@(Example)"
Output = "%(Color)\MyFile.txt"/>
</Target>
</Project>
Hedef toplu işlemeye başka bir örnek için bkz . Hedef toplu işlemde öğe meta verileri.
Madde ve özellik mutasyonları
Bu bölümde, hedef toplu işlem veya görev toplu işlemi kullanılırken özellikleri ve/veya öğe meta verilerini değiştirmenin etkilerinin nasıl anlaşıldığı açıklanmaktadır.
Hedef toplu işlem ve görev toplu işlemi iki farklı MSBuild işlemi olduğundan, MSBuild'in her durumda hangi toplu işlem biçimini kullandığını tam olarak anlamak önemlidir. Toplu iş söz dizimi %(ItemMetadataName) hedefteki bir görevde göründüğünde ancak Hedefteki bir öznitelikte görünmediğinde, MSBuild görev toplu işlemini kullanır. Hedef toplu işlemi belirtmenin tek yolu, genellikle Outputs özniteliği olan Target özniteliğinde toplu işlem söz dizimini kullanmaktır.
Hem hedef toplu işlem hem de görev toplu işlemiyle toplu işlerin bağımsız olarak çalıştırılacağı düşünülebilir. Tüm toplu işlemler, özellik ve öğe meta veri değerlerinin aynı ilk durumunun bir kopyasıyla başlar. Toplu yürütme sırasında özellik değerlerinin mutasyonları diğer toplu işlemler tarafından görülemez. Aşağıdaki örneği inceleyin:
<ItemGroup>
<Thing Include="2" Color="blue" />
<Thing Include="1" Color="red" />
</ItemGroup>
<Target Name="DemoIndependentBatches">
<ItemGroup>
<Thing Condition=" '%(Color)' == 'blue' ">
<Color>red</Color>
<NeededColorChange>true</NeededColorChange>
</Thing>
</ItemGroup>
<Message Importance="high"
Text="Things: @(Thing->'%(Identity) is %(Color); needed change=%(NeededColorChange)')"/>
</Target>
Çıktı şudur:
Target DemoIndependentBatches:
Things: 2 is red; needed change=true;1 is red; needed change=
ItemGroup hedefte örtük bir görevdir ve %(Color) özniteliğinde Condition ile görev gruplaması gerçekleştirilir. İki ayrı grup var: biri kırmızı için, diğeri mavi için. özelliği %(NeededColorChange) yalnızca meta veriler maviyse %(Color) ayarlanır ve ayar yalnızca mavi toplu iş çalıştırıldığında koşulla eşleşen tek tek öğeyi etkiler. Görev Message özniteliği Text, %(ItemMetadataName) söz dizimi kullanılmasına rağmen toplu işlemi tetiklemez çünkü bir öğe dönüştürmede kullanılır.
Toplu işler bağımsız olarak yürütülür, ancak eşzamanlı olarak yürütülmez. Toplu yürütmede değişen meta veri değerlerine eriştiğinizde bu bir fark yaratır. Toplu yürütmedeki bazı meta verileri temel alan bir özellik ayarladığınızda, özellik son değer kümesini alır:
<PropertyGroup>
<SomeProperty>%(SomeItem.MetadataValue)</SomeProperty>
</PropertyGroup>
Toplu yürütmeden sonra özelliği son değerini %(MetadataValue)korur.
Toplu işler bağımsız olarak çalışsa da, hedef toplu işlem ile görev toplu işlemi arasındaki farkı göz önünde bulundurmanız ve durumunuz için hangi türün geçerli olduğunu bilmeniz önemlidir. Bu ayrımın önemini daha iyi anlamak için aşağıdaki örneği göz önünde bulundurun.
Görevler açık yerine örtük olabilir ve bu da örtük görevlerle görev toplu işlemi gerçekleştiğinde kafa karıştırıcı olabilir. bir PropertyGroup veya ItemGroup öğesi içinde Targetgöründüğünde, gruptaki her özellik bildirimi örtük olarak ayrı bir CreateProperty veya CreateItem görevi gibi işlenir. Bu davranış, hedef toplu işleme tabi tutulduğunda derleme yürütmesinin, hedef toplu işleme tabi tutulmadığında (yani, %(ItemMetadataName) söz dizimi Outputs özniteliğinde olmadığında) farklı olduğu anlamına gelir. Hedef toplu işlendiğinde, ItemGroup hedef başına bir kez yürütülür, ancak hedef toplu işlenmediğinde, veya CreateItem görevlerinin CreateProperty örtük eşdeğerleri görev toplu işlemi kullanılarak toplu işlenir, bu nedenle hedef yalnızca bir kez yürütülür ve gruptaki her öğe veya özellik, görev toplu işlemi kullanılarak ayrı ayrı toplu işler.
Meta verilerin değiştirildiği durumlarda hedef toplu işleme ile görev toplu işleme karşılaştırmasının yapıldığı aşağıdaki örnek gösterilmektedir. Bazı dosyaların bulunduğu A ve B klasörlerinin bulunduğu bir durumu göz önünde bulundurun:
A\1.stub
B\2.stub
B\3.stub
Şimdi bu iki benzer projenin çıkışına bakın.
<ItemGroup>
<StubFiles Include="$(MSBuildThisFileDirectory)**\*.stub"/>
<StubDirs Include="@(StubFiles->'%(RecursiveDir)')"/>
</ItemGroup>
<Target Name="Test1" AfterTargets="Build" Outputs="%(StubDirs.Identity)">
<PropertyGroup>
<ComponentDir>%(StubDirs.Identity)</ComponentDir>
<ComponentName>$(ComponentDir.TrimEnd('\'))</ComponentName>
</PropertyGroup>
<Message Text=">> %(StubDirs.Identity) '$(ComponentDir)' '$(ComponentName)'"/>
</Target>
Çıktı şudur:
Test1:
>> A\ 'A\' 'A'
Test1:
>> B\ 'B\' 'B'
Şimdi hedef toplu işlemi belirten özniteliği kaldırın Outputs .
<ItemGroup>
<StubFiles Include="$(MSBuildThisFileDirectory)**\*.stub"/>
<StubDirs Include="@(StubFiles->'%(RecursiveDir)')"/>
</ItemGroup>
<Target Name="Test1" AfterTargets="Build">
<PropertyGroup>
<ComponentDir>%(StubDirs.Identity)</ComponentDir>
<ComponentName>$(ComponentDir.TrimEnd('\'))</ComponentName>
</PropertyGroup>
<Message Text=">> %(StubDirs.Identity) '$(ComponentDir)' '$(ComponentName)'"/>
</Target>
Çıktı şudur:
Test1:
>> A\ 'B\' 'B'
>> B\ 'B\' 'B'
Başlığın Test1 yalnızca bir kez yazdırıldığına, ancak önceki örnekte iki kez yazdırıldığına dikkat edin. Bu, hedefin toplu işlenmediği anlamına gelir. Sonuç olarak çıkış kafa karıştırıcı bir şekilde farklıdır.
Bunun nedeni, hedef toplu işlemi kullanırken her hedef toplu işlemin tüm özelliklerin ve öğelerin kendi bağımsız kopyasıyla hedefteki her şeyi yürütmesi, ancak özniteliği atladığınızda Outputs özellik grubundaki tek tek satırların ayrı, potansiyel olarak toplu işlenmiş görevler olarak kabul edilmesidir. Bu durumda, ComponentDir görev toplu olarak işlenir (söz dizimini %(ItemMetadataName) kullanır), böylece ComponentName satırı yürütüldüğünde, ComponentDir satırının her iki toplu işlemi de tamamlanmış olur ve çalıştırılan ikinci grup, ikinci satırda görüldüğü gibi değeri belirler.
Meta verileri kullanan özellik işlevleri
Toplu işleme, meta verileri içeren özellik işlevleri tarafından denetlenebilir. Örneğin
$([System.IO.Path]::Combine($(RootPath),%(Compile.Identity)))
Combine bir kök klasör yolunu Derleme öğesi yolu ile birleştirmek için kullanır.
Özellik işlevleri meta veri değerlerinde görünmeyebilir. Örneğin
%(Compile.FullPath.Substring(0,3))
izin verilmiyor.
Özellik işlevleri hakkında daha fazla bilgi için bkz . Özellik işlevleri.
Kendi kendini referans alan meta verilerde öğe toplu işleme
Bir öğe tanımının içinden meta veriye başvurmak için aşağıdaki örneği göz önünde bulundurun:
<ItemGroup>
<i Include='a/b.txt' MyPath='%(Filename)%(Extension)' />
<i Include='c/d.txt' MyPath='%(Filename)%(Extension)' />
<i Include='g/h.txt' MyPath='%(Filename)%(Extension)' />
</ItemGroup>
Herhangi bir hedef dışında ve hedef içinde tanımlandığında davranışın farklı olduğunu unutmayın.
Herhangi bir hedefin dışında öğenin kendi kendine referans veren meta verisi
<Project>
<ItemGroup>
<i Include='a/b.txt' MyPath='%(Filename)%(Extension)' />
<i Include='c/d.txt' MyPath='%(Filename)%(Extension)' />
<i Include='g/h.txt' MyPath='%(Filename)%(Extension)' />
</ItemGroup>
<Target Name='ItemOutside'>
<Message Text="i=[@(i)]" Importance='High' />
<Message Text="i->MyPath=[@(i->'%(MyPath)')]" Importance='High' />
</Target>
</Project>
Meta veri başvurusu her öğe örneği için ayrı ayrı çözülür (önceden tanımlanmış veya oluşturulmuş öğe örneklerinden etkilenmez) ve beklenen çıktıya yol açar.
i=[a/b.txt;c/d.txt;g/h.txt]
i->MyPath=[b.txt;d.txt;h.txt]
Hedef içerisinde öğeye kendine referans veren meta veriler
<Project>
<Target Name='ItemInside'>
<ItemGroup>
<i Include='a/b.txt' MyPath='%(Filename)%(Extension)' />
<i Include='c/d.txt' MyPath='%(Filename)%(Extension)' />
<i Include='g/h.txt' MyPath='%(Filename)%(Extension)' />
</ItemGroup>
<Message Text="i=[@(i)]" Importance='High' />
<Message Text="i->MyPath=[@(i->'%(MyPath)')]" Importance='High' />
</Target>
</Project>
Bu durumda başvurulan meta veriler toplu işleme yol açar ve bu da beklenmeyen ve istenmeyen çıkışlar verir:
i=[a/b.txt;c/d.txt;g/h.txt;g/h.txt]
i->MyPath=[;b.txt;b.txt;d.txt]
Motor, her öğe örneği için önceden var olan tüm öğe örneklerinin meta verilerini uygular (bu nedenle ilk öğe için MyPath boş ve ikinci öğe için b.txt içerir). Daha önceden var olan örnekler söz konusu olduğunda, bu davranış geçerli öğe örneğinin çarpmasına neden olur (bu nedenle g/h.txt öğe örneği sonuçta elde edilen listede iki kez gerçekleşir).
Bu, muhtemelen istenmeyen davranış hakkında açıkça bilgi vermek için, MSBuild'in sonraki sürümleri mesaj iletir MSB4120:
proj.proj(4,11): message : MSB4120: Item 'i' definition within target is referencing self via metadata 'Filename' (qualified or unqualified). This can lead to unintended expansion and cross-applying of pre-existing items. More info: https://aka.ms/msbuild/metadata-self-ref
proj.proj(4,11): message : MSB4120: Item 'i' definition within target is referencing self via metadata 'Extension' (qualified or unqualified). This can lead to unintended expansion and cross-applying of pre-existing items. More info: https://aka.ms/msbuild/metadata-self-ref
proj.proj(5,11): message : MSB4120: Item 'i' definition within target is referencing self via metadata 'Filename' (qualified or unqualified). This can lead to unintended expansion and cross-applying of pre-existing items. More info: https://aka.ms/msbuild/metadata-self-ref
proj.proj(5,11): message : MSB4120: Item 'i' definition within target is referencing self via metadata 'Extension' (qualified or unqualified). This can lead to unintended expansion and cross-applying of pre-existing items. More info: https://aka.ms/msbuild/metadata-self-ref
proj.proj(6,11): message : MSB4120: Item 'i' definition within target is referencing self via metadata 'Filename' (qualified or unqualified). This can lead to unintended expansion and cross-applying of pre-existing items. More info: https://aka.ms/msbuild/metadata-self-ref
proj.proj(6,11): message : MSB4120: Item 'i' definition within target is referencing self via metadata 'Extension' (qualified or unqualified). This can lead to unintended expansion and cross-applying of pre-existing items. More info: https://aka.ms/msbuild/metadata-self-ref
i=[a/b.txt;c/d.txt;g/h.txt;g/h.txt]
i->MyPath=[;b.txt;b.txt;d.txt]
Kendi kendine başvuru kasıtlıysa, gerçek senaryoya ve tam gereksinimlere bağlı olarak birkaç seçeneğiniz vardır:
- Kodu tutma ve iletiyi yoksayma
- Öğeyi hedefin dışında tanımlama
- Yardımcı öğeyi ve dönüştürme işlemini kullanma
Yardımcı öğeyi ve dönüştürme işlemini kullanma
Meta veri başvurusunun neden olduğu toplu işleme davranışını önlemek istiyorsanız, bunu ayrı bir öğe tanımlayıp dönüştürme işlemini kullanarak istenen meta verilerle öğe örnekleri oluşturabilirsiniz:
<Project>
<Target Name='ItemOutside'>
<ItemGroup>
<j Include='a/b.txt' />
<j Include='c/*' />
<i Include='@(j)' MyPath="%(Filename)%(Extension)" />
</ItemGroup>
<Message Text="i=[@(i)]" Importance='High' />
<Message Text="i->MyPath=[@(i->'%(MyPath)')]" Importance='High' />
</Target>
</Project>
İlgili içerik
- ItemMetadata öğesi (MSBuild)
- MSBuild kavramları
- MSBuild başvuru