MSBuild バッチMSBuild batching

MSBuild では、項目のメタデータに基づいて項目一覧が異なるカテゴリまたはバッチに分割され、バッチごとにターゲットまたはタスクが 1 回実行されます。MSBuild divides item lists into different categories, or batches, based on item metadata, and runs a target or task one time with each batch.

タスクのバッチ処理Task batching

タスクのバッチ処理を利用すると、項目一覧をさまざまバッチに分割し、各バッチをタスクに個別に渡すことができます。プロジェクト ファイルが扱いやすくなります。Task batching allows you to simplify your project files by providing a way to divide item lists into different batches and pass each of those batches into a task separately. つまり、プロジェクト ファイルは複数回実行できますが、タスクとその属性は一回宣言すれば十分です。This means that a project file only needs to have the task and its attributes declared once, even though it can be run several times.

タスク属性の 1 つで %(ItemMetaDataName) という表記を使用して、MSBuild でタスクのバッチ処理を実行することを指定します。You specify that you want MSBuild to perform batching with a task by using the %(ItemMetaDataName) notation in one of the task attributes. 次の例では、Example 項目一覧が Color 項目メタデータ値に基づいてバッチに分割し、各バッチを MyTask タスクに個別に渡します。The following example splits the Example item list into batches based on the Color item metadata value, and passes each of the batches to the MyTask task separately.

注意

タスク属性の他の場所で項目一覧を参照していない場合、またはメタデータ名があいまいな場合は、%(<ItemCollection.ItemMetaDataName>) という表記を使用して、バッチ処理に使用する項目のメタデータの値を完全に修飾できます。If you do not reference the item list elsewhere in the task attributes, or the metadata name may be ambiguous, you can use the %(<ItemCollection.ItemMetaDataName>) notation to fully qualify the item metadata value to use for batching.

<Project
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

    <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>

特定のバッチ処理の例については、「タスクのバッチの項目メタデータ」を参照してください。For more specific batching examples, see Item metadata in task batching.

ターゲットのバッチ処理Target batching

MSBuild では、ターゲットを実行する前に、ターゲットの入力と出力が最新かどうかが確認されます。MSBuild checks if the inputs and outputs of a target are up to date before it runs the target. 入力と出力がどちらも最新である場合、ターゲットはスキップされます。If both inputs and outputs are up to date, the target is skipped. ターゲット内のタスクでバッチ処理が使用される場合、MSBuild では、項目の各バッチの入力と出力が最新かどうかを判断する必要があります。If a task inside of a target uses batching, MSBuild needs to determine if the inputs and outputs for each batch of items is up to date. そうでない場合、ターゲットはヒットするたびに実行されます。Otherwise, the target is executed every time it's hit.

次の例では、%(ItemMetadataName) 表記のある Outputs 属性が含まれる Target 要素を示します。The following example shows a Target element that contains an Outputs attribute with the %(ItemMetadataName) notation. MSBuild は、Color メタデータに基づいて Example 項目一覧をバッチに分割し、バッチごとに出力ファイルのタイムスタンプを分析します。MSBuild will divide the Example item list into batches based on the Color item metadata, and analyze the timestamps of the output files for each batch. バッチからの出力が最新の状態でない場合は、ターゲットが実行されます。If the outputs from a batch aren't up to date, the target is run. 最新の状態であれば、ターゲットはスキップされます。Otherwise, the target is skipped.

<Project
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

    <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>

ターゲットのバッチ処理のもう 1 つの例については、「ターゲットのバッチの項目メタデータ」を参照してください。For another example of target batching, see Item metadata in target batching.

項目とプロパティの変更Item and property mutations

ここでは、ターゲットのバッチ処理またはタスクのバッチ処理を使用しているときに、プロパティや項目メタデータを変更した場合の影響を理解する方法について説明します。This section describes how to understand the effects of changing properties and/or item metadata, when using target batching or task batching.

ターゲットのバッチ処理とタスクのバッチ処理は 2 つの異なる MSBuild 操作であるため、ケースごとに MSBuild でどの形式のバッチ処理が使用されているかを正確に理解することが重要です。Because target batching and task batching are two different MSBuild operations, it is important to understand exactly which form of batching MSBuild uses in each case. ターゲットのタスクにはバッチ処理構文 %(ItemMetadataName) が含まれ、ターゲットの属性には含まれない場合、MSBuild ではタスク バッチ処理が使用されています。When the batching syntax %(ItemMetadataName) appears in a task in a target, but not in an attribute on the Target, then MSBuild uses task batching. ターゲットのバッチ処理を指定する唯一の方法は、ターゲットの属性 (通常は Outputs 属性) でバッチ処理構文を使用することです。The only way to specify target batching is by using the batching syntax on a Target attribute, usually the Outputs attribute.

ターゲットのバッチ処理とタスクのバッチ処理のどちらでも、バッチは独立して実行されると考えることができます。With both target batching and task batching, batches can be considered to run independently. すべてのバッチは、プロパティと項目メタデータの値の同じ初期状態のコピーで開始されます。All batches begin with a copy of the same initial state of property and item metadata values. バッチ実行の間にプロパティ値が変更されても、他のバッチからはわかりません。Any mutations of property values during batch execution is not visible to other batches. 次に例を示します。Consider the following example:

  <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>

出力は次のようになります。The output is:

Target DemoIndependentBatches:
  Things: 2 is red; needed change=true;1 is red; needed change=

ターゲットの ItemGroup は暗黙的にタスクであり、Condition 属性で %(Color) が使用されているので、タスクのバッチ処理が実行されます。The ItemGroup in the target is implicitly a task, and with the %(Color) in the Condition attribute, task batching is performed. 2 つのバッチがあります (red に対して 1 つと、blue に対して 1 つ)。There are two batches: one for red and the other for blue. プロパティ %(NeededColorChange)%(Color) メタデータが blue の場合にのみ設定され、その設定は、blue のバッチが実行されたときに条件が一致した個々の項目にのみ影響します。The property %(NeededColorChange) is only set if the %(Color) metadata is blue, and the setting only affects the individual item that matched the condition when the blue batch was run. %(ItemMetadataName) 構文が指定されていても、Message タスクの Text 属性ではバッチ処理はトリガーされません。これは、それが項目変換の内側で使用されているためです。The Message task's Text attribute does not trigger batching, despite the %(ItemMetadataName) syntax, because it is used inside an item transform.

バッチは個別に実行されますが、並列では実行されません。Batches run independently, but not in parallel. それにより、バッチ実行で変更されるメタデータ値にアクセスするときに違いがあります。That makes a difference when you access metadata values that change in the batched execution. バッチ実行の一部のメタデータに基づいてプロパティを設定する場合、プロパティは "最後" に設定された値になります。In the case where you set a property based on some metadata in the batched execution, the property would take the last value set:

   <PropertyGroup>
       <SomeProperty>%(SomeItem.MetadataValue)</SomeProperty>
   </PropertyGroup>

バッチ実行の後、プロパティでは %(MetadataValue) の最終的な値が保持されます。After batch execution, the property retains the final value of %(MetadataValue).

バッチは個別に実行されますが、ターゲットのバッチ処理とタスクのバッチ処理の違いを考慮し、自分の状況にはどちらの種類が当てはまるかを理解することが重要です。Although batches run independently, it's important to consider the difference between target batching and task batching and know which type applies to your situation. この区別の重要性を理解するために、次の例を考えてみます。Consider the following example to understand better the importance of this distinction.

タスクは明示的ではなく暗黙的な場合があり、タスクのバッチ処理が暗黙的なタスクで発生した場合、混乱を招く可能性があります。Tasks can be implicit, rather than explicit, which can be confusing when task batching occurs with implicit tasks. PropertyGroup 要素または ItemGroup 要素が Target に含まれる場合、グループ内の各プロパティ宣言は、個別の CreateProperty タスクまたは CreateItem タスクと同様に、暗黙的に処理されます。When a PropertyGroup or ItemGroup element appears in a Target, each property declaration in the group is implicitly treated somewhat like a separate CreateProperty or CreateItem task. つまり、ターゲットがバッチ処理されるときと、ターゲットがバッチ処理されないとき (つまり、Outputs 属性に %(ItemMetadataName) 構文がない場合) では、動作が異なります。This means that the behavior is different when the target is batched, versus when the target is not batched (that is, when it lacks the %(ItemMetadataName) syntax in the Outputs attribute). ターゲットがバッチ処理されるときは、ターゲットごとに ItemGroup が 1 回実行されます。一方、ターゲットがバッチ処理されないときは、CreateItem タスクまたは CreateProperty タスクと暗黙的に同等のものがタスク バッチ処理を使用してバッチ処理されるため、ターゲットは 1 回だけ実行され、グループ内の各項目または各プロパティは、タスク バッチ処理を使用して個別にバッチ処理されます。When the target is batched, the ItemGroup executes once per target, but when the target is not batched, the implicit equivalents of the CreateItem or CreateProperty tasks are batched using task batching, so the target only executes once, and each item or property in the group is batched separately using task batching.

次の例では、メタデータが変更される場合のターゲット バッチ処理とタスク バッチ処理の違いを示します。The following example illustrates target batching vs. task batching in the case where metadata is mutated. いくつかのファイルが含まれるフォルダー A と B がある状況について考えます。Consider a situation where you have folders A and B with some files:

A\1.stub
B\2.stub
B\3.stub

これら 2 つの似たプロジェクトの出力を見てみます。Now look at the output of these two similar projects.

    <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>

出力は次のようになります。The output is:

Test1:
  >> A\ 'A\' 'A'
Test1:
  >> B\ 'B\' 'B'

ここで、ターゲットのバッチ処理を指定した Outputs 属性を削除します。Now remove the Outputs attribute that specified target batching.

    <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>

出力は次のようになります。The output is:

Test1:
  >> A\ 'B\' 'B'
  >> B\ 'B\' 'B'

見出し Test1 は 1 回だけ出力されますが、前の例では 2 回出力されたことに注意してください。Notice that the heading Test1 is only printed once, but in the previous example, it was printed twice. つまり、ターゲットはバッチ処理されません。That means the target is not batched. その結果、出力は紛らわしいほど異なります。And as a result, the output is confusingly different.

これは、ターゲットのバッチ処理を使用した場合は、各ターゲットのバッチで、ターゲット内のすべてのものが、すべてのプロパティと項目の独自の独立したコピーを使用して実行されますが、Outputs 属性を省略すると、プロパティ グループの個々の行が個別のタスクとして扱われ、バッチ処理される可能性があるためです。The reason is that when using target batching, each target batch executes everything in the target with its own independent copy of all the properties and items, but when you omit the Outputs attribute, the individual lines in the property group are treated as distinct, potentially batched tasks. この場合、ComponentName 行が実行されるときまでに、ComponentDir 行の両方のバッチが完了し、実行された 2 番目のものによって 2 行目で示される値が決定されているように、ComponentDir タスクはバッチ処理されます (%(ItemMetadataName) 構文が使用されます)。In this case, the ComponentDir task is batched (it uses the %(ItemMetadataName) syntax), so that by the time the ComponentName line executes, both batches of the ComponentDir line have completed, and the second one that ran determined the value as seen in the second line.

メタデータを利用するプロパティ関数Property functions using metadata

バッチ処理は、メタデータを含むプロパティ関数で制御できます。Batching can be controlled by property functions that include metadata. たとえば、オブジェクトに適用されたFor example,

$([System.IO.Path]::Combine($(RootPath),%(Compile.Identity)))

このプロパティ関数は、Combine を使用し、ルート フォルダーパスとコンパイル項目パスを結合します。uses Combine to combine a root folder path with a Compile item path.

プロパティ関数はメタデータ値内に表示されない場合があります。Property functions may not appear within metadata values. たとえば、オブジェクトに適用されたFor example,

%(Compile.FullPath.Substring(0,3))

これは許可されません。is not allowed.

プロパティ関数の詳細については、「プロパティ関数」を参照してください。For more information about property functions, see Property functions.

関連項目See also