item-management について
MSBuild の項目グループを扱う開発者向けのリファレンススキルです。項目操作、バッチ処理、変換と、よくあるビルド上の問題を説明します。
主な機能
- 01Include、Remove、Update のパターン
- 02メタデータによる項目のバッチ処理
- 03項目の変換と除外
- 04条件付き項目の追加
- 05生成ファイルと FileWrites の指針
活用シーン
- 01MSBuild ターゲットで項目を追加・変更
- 02項目メタデータごとのタスク実行
- 03変換した項目リストの作成
- 04クリーン処理やソースツリーの問題回避
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ dotnet/ skills --skill item-managementインストール後、Claude Code で/item-managementを入力して読み込まれたか確認します。
詳細
MSBuild 項目管理パターン
Microsoft.Common.CurrentVersion.targets に基づく、項目グループを操作するための標準的なパターンです。
Include / Remove / Update — 3 つの操作
| 操作 | 目的 | 使用する状況 |
|---|---|---|
Include | グループに新しい項目を追加する | 識別子とメタデータを持つ項目を作成する場合 |
Remove | パターンに一致する項目を削除する | ファイルを除外するか、グループを空にする場合 |
Update | 既存の項目のメタデータを変更する | 項目を再追加せずにメタデータを追加または変更する場合 |
Include — 項目を追加する
<ItemGroup>
<Compile Include="Generated\*.cs">
<AutoGen>true</AutoGen>
</Compile>
</ItemGroup>
Remove — 項目を削除する
<ItemGroup>
<Reference Remove="$(AdditionalExplicitAssemblyReferences)" />
<_CleanOrphanFileWrites Include="@(_CleanPriorFileWrites)"
Exclude="@(_CleanCurrentFileWrites)" />
<_Temporary Remove="@(_Temporary)" />
</ItemGroup>
Update — 既存の項目を変更する
<ItemGroup>
<EmbeddedResource Update="@(EmbeddedResource)"
Condition="'%(NuGetPackageId)' == 'Microsoft.CodeAnalysis.Collections'">
<GenerateSource>true</GenerateSource>
<ClassName>Microsoft.CodeAnalysis.Collections.SR</ClassName>
</EmbeddedResource>
</ItemGroup>
Update は項目を追加せず、グループ内にすでにある項目のみを変更します。
項目のバッチ処理 — %(Metadata)
ターゲット属性またはタスクパラメーターに %(Metadata) がある場合、MSBuild は一意のメタデータ値ごとに実行をバッチ処理します。
ターゲットレベルのバッチ処理(Outputs)
<Target Name="GenerateSatelliteAssemblies"
Inputs="$(MSBuildAllProjects);@(_SatelliteAssemblyResourceInputs)"
Outputs="$(IntermediateOutputPath)%(Culture)\$(TargetName).resources.dll">
</Target>
タスクレベルのバッチ処理
<Copy SourceFiles="@(_SourceItems)"
DestinationFiles="@(_SourceItems->'$(OutDir)%(TargetPath)')">
</Copy>
Condition による項目ごとのフィルタリング
<ItemGroup>
<_ResxOutput Include="@(EmbeddedResource->'%(OutputResource)')"
Condition="'%(EmbeddedResource.WithCulture)' == 'false'" />
</ItemGroup>
バッチ処理のルール
ConditionまたはOutputs内の%(Metadata)→ ターゲットは一意の値ごとにバッチ処理されます。- タスクパラメーター内の
%(Metadata)→ タスクは一意の値ごとにバッチ処理されます。 - 同じ式の中で異なる項目グループの
%()を混在させないでください。直積が発生します(「よくある落とし穴」を参照)。
項目変換 — @(Item->'expression')
変換を使うと、各項目に式を適用して新しい項目リストを作成できます。
<Copy SourceFiles="@(IntermediateAssembly)"
DestinationFiles="@(IntermediateAssembly->'$(OutDir)%(Filename)%(Extension)')"/>
<Message Text="Files: @(Compile->'%(Filename)', ', ')" />
除外パターン — Include に対する集合の差
<ItemGroup>
<Compile Include="**\*.cs" Exclude="Generated\**;Tests\**" />
</ItemGroup>
Exclude は Include でのみ機能し、Update や Remove と併用できません。
条件付き項目の追加
<ItemGroup Condition="'$(NetCoreBuild)' == 'true'">
<PackageReference Include="System.IO.Pipelines" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.IO.Pipelines"
Condition="'$(NetCoreBuild)' == 'true'" />
</ItemGroup>
ツール/アナライザーパッケージの PrivateAssets
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" PrivateAssets="all" />
<PackageReference Include="StyleCop.Analyzers" PrivateAssets="all" />
</ItemGroup>
よくある落とし穴
直積によるバッチ処理
異なる 2 つの項目グループから %(Metadata) を参照すると、O(N×M) 回の実行が発生します。
<Exec Command="process %(Source.Identity) with %(Config.Identity)" />
<Exec Command="process %(Source.Identity) with $(ConfigFile)" />
ソースツリー内の生成ファイル
ソースディレクトリではなく、$(IntermediateOutputPath)(obj/)に書き込んでください。ソースツリー内でファイルを生成すると、バージョン管理が煩雑になり、グロブによってコンパイルが重複する原因になることがあります。
FileWrites の不足
ターゲットの実行中に作成したファイルはすべて、dotnet clean をサポートするために @(FileWrites) に追加する必要があります。
コメント
Markdown 対応