mcpField
P
property-patterns

property-patterns

github.com/dotnet開発5.8k3.2k 回インストール1 日前に更新
リポジトリ

property-patterns について

MSBuildプロパティの標準的なパターンを記録したリファレンススキルです。既定値、条件、値の結合、パス、評価順序を扱い、MSBuildプロジェクトファイルの保守に役立ちます。

主な機能

  1. 01上書き可能な条件付き既定値
  2. 02入れ子の条件付きプロパティグループ
  3. 03セミコロンによるプロパティ結合
  4. 04パス正規化パターン
  5. 05ターゲットフレームワークとバージョンのガード
  6. 06評価順序とフォールバックの指針

活用シーン

  1. 01呼び出し側が上書きできる既定値の定義
  2. 02定数や警告コードの安全な追加
  3. 03プロジェクトファイル間のパス正規化

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/dotnet/skills --skill property-patterns

インストール後、Claude Code で/property-patternsを入力して読み込まれたか確認します。

詳細

MSBuild プロパティのパターン

MSBuild リポジトリにおける、標準的なプロパティの定義と操作のパターンです。

条件付きの既定値 — 基本パターン

呼び出し元が上書きできるよう、プロパティがまだ設定されていない場合にのみ設定します。

<PropertyGroup>
  <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
  <Platform Condition="'$(Platform)' == ''">AnyCPU</Platform>
  <BuildInParallel Condition="'$(BuildInParallel)' == ''">true</BuildInParallel>
</PropertyGroup>
ルール
  • 常に両辺を引用符で囲みます:'$(Prop)' == ''
  • .props:上書き可能な既定値を作成します。.targets:フォールバックを作成します。
  • 条件のないプロパティは、先にインポートされた内容から上書きできません。

入れ子になった条件付きグループ

関連するプロパティを共通の条件の下にまとめます。

<PropertyGroup Condition="$(TargetFramework.StartsWith('net4'))">
  <DefineConstants>$(DefineConstants);FEATURE_APARTMENT_STATE</DefineConstants>
  <DefineConstants>$(DefineConstants);FEATURE_APM</DefineConstants>
  <FeatureAppDomain>true</FeatureAppDomain>
</PropertyGroup>

<PropertyGroup Condition="'$([MSBuild]::GetTargetFrameworkIdentifier('$(TargetFramework)'))' == '.NETCoreApp'">
  <NetCoreBuild>true</NetCoreBuild>
  <DefineConstants>$(DefineConstants);RUNTIME_TYPE_NETCORE</DefineConstants>
</PropertyGroup>

各プロパティで同じ条件を繰り返さないよう、PropertyGroup に外側の Condition を指定します。

警告: 単一ターゲットのプロジェクトでは、プロジェクト本体が評価されるまで、.props ファイル内の $(TargetFramework) は空です。TargetFramework を条件にしたプロパティグループは、値を常に利用できる .targets ファイル(またはプロジェクトファイル自体)に配置してください。

結合 — セミコロンによる連結

リストを保持するプロパティではセミコロンを使用します。値を追加する際は、必ず既存の値を含めてください。

<PropertyGroup>
  <DefineConstants>$(DefineConstants);MY_FEATURE</DefineConstants>
  <NoWarn>$(NoWarn);NU5131;IDE0005</NoWarn>
  <LibraryTargetFrameworks>$(FullFrameworkTFM);$(LatestDotNetCoreForMSBuild);netstandard2.0</LibraryTargetFrameworks>
</PropertyGroup>

パスの正規化と末尾のスラッシュ


<PropertyGroup>
  <OutDir Condition="'$(OutDir)' != '' and !HasTrailingSlash('$(OutDir)')">$(OutDir)\</OutDir>
</PropertyGroup>


<PropertyGroup>
  <TargetRefPath>$([MSBuild]::NormalizePath('$(TargetDir)', 'ref', '$(TargetFileName)'))</TargetRefPath>
</PropertyGroup>


<PropertyGroup>
  <MSBuildProjectExtensionsPath
      Condition="'$([System.IO.Path]::IsPathRooted('$(MSBuildProjectExtensionsPath)'))' == 'false'">
    $([System.IO.Path]::Combine('$(MSBuildProjectDirectory)', '$(MSBuildProjectExtensionsPath)'))
  </MSBuildProjectExtensionsPath>
</PropertyGroup>
推奨されるパス関数
関数用途
$([MSBuild]::NormalizePath(...))パスを結合して正規化します(クロスプラットフォーム対応)
$([System.IO.Path]::Combine(...))パスの各要素を結合します
$([System.IO.Path]::IsPathRooted(...))絶対パスかどうかを確認します
HasTrailingSlash(...)末尾にスラッシュがあるかどうかを確認します
$([MSBuild]::GetDirectoryNameOfFileAbove(...))ディレクトリツリーを上にたどります
$(MSBuildThisFileDirectory)現在のファイルがあるディレクトリ

ターゲットフレームワーク検出ヘルパー


<PropertyGroup Condition="'$([MSBuild]::GetTargetFrameworkIdentifier('$(TargetFramework)'))' == '.NETCoreApp'">
  <NetCoreBuild>true</NetCoreBuild>
</PropertyGroup>


<PropertyGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net472'))">
  <UseFrozenVersions>true</UseFrozenVersions>
</PropertyGroup>


<PropertyGroup Condition="$([MSBuild]::IsOSPlatform('windows'))">
  <DefineConstants>$(DefineConstants);TEST_ISWINDOWS</DefineConstants>
</PropertyGroup>

ガードプロパティ

二重インポートを防ぐため、ファイルがインポート済みであることを示します。


<PropertyGroup>
  <MySDKPropsImported>true</MySDKPropsImported>
</PropertyGroup>


<Import Project="MySDK.props" Condition="'$(MySDKPropsImported)' != 'true'" />

MSBuild のバージョンによる機能の切り替え

<PropertyGroup Condition="$([MSBuild]::AreFeaturesEnabled('17.10'))">
  <UseNewBehavior>true</UseNewBehavior>
</PropertyGroup>

フォールバックチェーン

まず優先するソースから設定し、次にフォールバックします。

<PropertyGroup>
  <TlbExpPath>$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPathToDotNetFrameworkSdkFile('tlbexp.exe'))</TlbExpPath>
  <TlbExpPath Condition="'$(TlbExpPath)' == ''">$(_NetFxToolsDir)TlbExp.exe</TlbExpPath>
</PropertyGroup>

後勝ち — 評価順序

MSBuild はプロパティを上から下へ評価します。最後に割り当てられた値が有効になります。


<MyProp>value1</MyProp>        

<MyProp>value2</MyProp>        

<MyProp Condition="'$(MyProp)' == ''">value3</MyProp>  

後からインポートされる .targets のプロパティは、先にインポートされる .props およびプロジェクトファイル内のプロパティを上書きします。

よくある落とし穴

  • 引用符で囲まれていない条件($(X)==true)は、プロパティが空の場合に失敗します。常に両辺を引用符で囲んでください。
  • DefineConstants の上書き(<DefineConstants>MY_CONST</DefineConstants>)を行うと、それまでの定数がすべて失われます。必ず $(DefineConstants); を使って追加してください。
  • ハードコードされた絶対パスは移植性を損ないます。$(MSBuildThisFileDirectory) または $([MSBuild]::NormalizePath(...)) を使用してください。
  • 既定値に Condition がないと、プロパティを上書きできなくなります。既定値として設定する値には Condition="'$(Prop)' == ''" を追加してください。

コメント