「VC PlusPlus:MSBuild バッチ処理変数」の版間の差分
(→概要) |
|||
139行目: | 139行目: | ||
BatchItem->BatchPath=[a.txt;b.txt;a.txt] | BatchItem->BatchPath=[a.txt;b.txt;a.txt] | ||
</syntaxhighlight> | </syntaxhighlight> | ||
だからといって絶対にTarget内部のItemGroupでバッチ機能を使ってはいけないというわけではなく、以下のように一か所に集約するような使い方をするとうまく動いたりもするので、そういう工夫がわかっている人にはできるというところが、またややこしい。 | |||
<syntaxhighlight lang="xml"> | |||
<Target Name="Test" AfterTargets="AfterResourceCompile"> | |||
<ItemGroup> | |||
<preBatch Include='a/a.txt' /> | |||
<preBatch Include='b/b.txt' /> | |||
<preBatch Include='c/c.txt' /> | |||
<Batch Include='@(preBatch)' BatchPath="%(Filename)%(Extension)" /> | |||
</ItemGroup> | |||
<Message Text="Batch=[@(Batch)]" Importance='High' /> | |||
<Message Text="Batch->BatchPath=[@(Batch->'%(BatchPath)')]" Importance='High' /> | |||
</Target> | |||
</syntaxhighlight> | |||
出力結果 | |||
<syntaxhighlight lang="text"> | |||
Batch=[a/a.txt;b/b.txt;c/c.txt] | |||
Batch->BatchPath=[a.txt;b.txt;c.txt] | |||
</syntaxhighlight> | |||
2024年2月10日 (土) 17:22時点における版
概要
バッチ処理は%(Batch)のように記述する変数です。
バッチ処理の定義の基礎
例えば、以下のように書いた<ItemGroup>~</ItemGroup>があったとしたら
<ItemGroup>
<Batch Include="1" Element="en-US" />
<Batch Include="2" Element="ja-JP" />
</ItemGroup>
%(Element)というバッチ処理がアイテムグループBatchの中に設定されたことになり、Batchの中のバッチとして扱う範囲の呼び出しができます。Includeに示した値はファイルなので、プロジェクトで読み込むには、vcxprojファイルのあるフォルダと同じ階層に1や2という名前のファイルが必要になります。Projectタグ直下に置くItemGroupの中のタグには最初の定義で要素IncludeかUpdateかRemoveが必須です。例えば以下のような使い方ができます。
<Target Name="BatchTarget">
<ItemGroup>
<Batch Condition=" '%(Element)' == 'en-US' ">
<ConditionEnUSBatch>true</ConditionEnUSBatch>
</Batch>
</ItemGroup>
<Message Text="Batch = @(Batch->'%(Element)')" Importance="High" />
</Target>
出力結果
Batch = en-US;ja-JP
この時、実は%(Element)だけではなく、%(Identity)というものもBatchの中設定されていてIncludeという要素の値に対応しています。%(Element)がen-USを示す内容のときだけConditionの中で示された比較が成立し、%(ConditionEnUSBatch)もBatchの中にできていて、以下のようにして出力することができます。
<Target Name="BatchTarget">
<ItemGroup>
<Batch Condition=" '%(Element)' == 'en-US' ">
<ConditionEnUSBatch>true</ConditionEnUSBatch>
</Batch>
</ItemGroup>
<Message Text="Batch = {@(Batch->' Element = %(Element), Identity = %(Identity), ConditionEnUSBatch = %(ConditionEnUSBatch)')}" Importance="High" />
</Target>
出力結果
Batch = { Element = en-US, Identity = 1, ContitionEnUSBatch = true; Element = ja-JP, Identity = 2, ContitionEnUSBatch =}
と表現できることになります。
さらに、このようにBatchの中のという指定をするために使った@(Batch->' ')を以下のように記述することもできます。
<Target Name="BatchTarget">
<ItemGroup>
<Batch Condition=" '%(Element)' == 'en-US' ">
<ConditionEnUSBatch>true</ConditionEnUSBatch>
</Batch>
</ItemGroup>
<Message Text="%(Batch.Element)" Importance="High" />
</Target>
出力結果
en-US
ja-JP
このように、%(Batch.Element)とすると、バッチ処理の機能が働き、その要素の分だけメッセージ出力処理が繰り返されます。@(Batch->' ')の中にバッチがあった時はその中のメッセージが;区切りで繰り返される感じになります。
バッチ処理の例外
以下のようにTarget内で定義したItemGroupでバッチを呼び出しても評価順序が正しくないため思い通りの結果は得られません。ちゅういして使いましょうとマイクロソフトのWebsiteに記載されていたので、そこは注意したいですね。
<Target Name="Test" AfterTargets="AfterResourceCompile">
<ItemGroup>
<BatchItem Include='a/a.txt' BatchPath='%(Filename)%(Extension)' />
<BatchItem Include='a/b.txt' BatchPath='%(Filename)%(Extension)' />
<BatchItem Include='b/a.txt' BatchPath='%(Filename)%(Extension)' />
</ItemGroup>
<Message Text="BatchItem=[@(i)]" Importance='High' />
<Message Text="BatchItem->Include=[@(BatchItem->'%(Identity)')]" Importance='High' />
<Message Text="BatchItem->BatchPath=[@(BatchItem->'%(BatchPath)')]" Importance='High' />
</Target>
実行結果
BatchItem=[a/a.txt;a/b.txt;b/a.txt;b/a.txt]
BatchItem->Include=[a/a.txt;a/b.txt;b/a.txt;b/a.txt]
BatchItem->BatchPath=[;b.txt;a.txt;a.txt]
%(Filename)や%(Extension)ように、定義しなくても使えるバッチというのもあります。が、上記のように、Targetの中でバッチを使うとまだ評価されていないだとかスコープだとかの都合で動作が保証されず思い通りの結果は得られません。
以下のようにすると期待していたものに近い結果が得られます。
<ItemGroup>
<BatchItem Include='a/a.txt' BatchPath='%(Filename)%(Extension)' />
<BatchItem Include='a/b.txt' BatchPath='%(Filename)%(Extension)' />
<BatchItem Include='b/a.txt' BatchPath='%(Filename)%(Extension)' />
</ItemGroup>
<Target Name="Test" AfterTargets="AfterResourceCompile">
<Message Text="BatchItem=[@(BatchItem)]" Importance='High' />
<Message Text="BatchItem->Include=[@(BatchItem->'%(Identity)')]" Importance='High' />
<Message Text="BatchItem->BatchPath=[@(BatchItem->'%(BatchPath)')]" Importance='High' />
</Target>
実行結果
BatchItem=[a/a.txt;a/b.txt;b/a.txt]
BatchItem->Include=[a/a.txt;a/b.txt;b/a.txt]
BatchItem->BatchPath=[a.txt;b.txt;a.txt]
だからといって絶対にTarget内部のItemGroupでバッチ機能を使ってはいけないというわけではなく、以下のように一か所に集約するような使い方をするとうまく動いたりもするので、そういう工夫がわかっている人にはできるというところが、またややこしい。
<Target Name="Test" AfterTargets="AfterResourceCompile">
<ItemGroup>
<preBatch Include='a/a.txt' />
<preBatch Include='b/b.txt' />
<preBatch Include='c/c.txt' />
<Batch Include='@(preBatch)' BatchPath="%(Filename)%(Extension)" />
</ItemGroup>
<Message Text="Batch=[@(Batch)]" Importance='High' />
<Message Text="Batch->BatchPath=[@(Batch->'%(BatchPath)')]" Importance='High' />
</Target>
出力結果
Batch=[a/a.txt;b/b.txt;c/c.txt]
Batch->BatchPath=[a.txt;b.txt;c.txt]
バッチ処理の変数で既に定義されている機能
- %(Filename):
- ファイルの名前部分を取得します。
- 例: file.txt の場合、file を返します。
- %(Extension):
- ファイルの拡張子部分を取得します。
- 例: file.txt の場合、.txt を返します。
- %(RecursiveDir):
- 再帰的に検索されたファイルのディレクトリパスを取得します。
- 例: C:\project\src\file.txt の場合、src\ を返します。
- %(Identity):
- 項目の識別子(通常はファイルパス)を取得します。
- 例: @(Compile->'%(Identity)') は、Compileアイテムのファイルパスを取得します。
- %(ModifiedTime):
- ファイルの最終更新日時を取得します。
- 例: @(Compile->'%(ModifiedTime)') は、Compileアイテムの最終更新日時を取得します。
- %(CreatedTime):
- ファイルの作成日時を取得します。
- 例: @(Compile->'%(CreatedTime)') は、Compileアイテムの作成日時を取得します。
- %(FullPath):
- ファイルのフルパスを取得します。
- 例: @(Compile->'%(FullPath)') は、Compileアイテムのフルパスを取得します。