はじめに
.NETで開発していると嫌でも利用することになるのがMsBuildです。
最新の.NET 6環境でもdotnet CLIに隠れているだけでMsBuildを利用しているのは同じです。
(一時期は脱MsBuildをしようとしてたらしいですが、辞めたようです)
今回は、複数プロジェクトの設定を一括で変更できる、Directory.Build.target / Directory.Build.propsについて紹介します。
Visual Studio 2017以降で利用できます。
Directory.Build.*
だいたいリポジトリ直下に置くファイルですが、次のような効果を持ちます。
- Directory.Build.props
- csprojの”前”に読み込まれる。
csprojで上書きができる
- csprojの”前”に読み込まれる。
- Directory.Build.target
- csprojの”後”に読み込まれる。
csprojの設定を上書きできる
- csprojの”後”に読み込まれる。
これの仕組みとしては、MsBuildがcsprojをビルドする時に、ドライブルートまで親ディレクトリを遡っていき最初に見つかったファイルを読み込むというものです。
C:\aaa\bbb\ccc\ddd\eee\eee.csproj というパスにプロジェクトがある場合
C:\aaa\bbb\ccc\ddd\eee\
C:\aaa\bbb\ccc\ddd\
C:\aaa\bbb\ccc\
C:\aaa\bbb\
C:\aaa\
C:\
の順番で探索します。
見つかった時点でそれ以上の探索は行われません。
何に使うの?
複数のcsprojから構成されるアプリケーションの場合に有効的に使えます。
例えば、NULL許容参照型を全プロジェクトで有効化する場合、こうなります
<Project>
<PropertyGroup>
<Nullable>true<Nullable>
</PropertyGroup>
</Project>
(ただし、プロダクトでこれをやるとビルド時に大量の警告が出ます‥)
決定論ビルドの有効化や、言語バージョンの指定などもできます。
<Project>
<PropertyGroup>
<Nullable>true<Nullable>
<Deterministic>true</Deterministic>
<LangVersion>9.0</LangVersion>
</PropertyGroup>
</Project>
わかっていないこと
csprojにはSDK styleとそうでない旧式のものが存在します。
これらが混在している場合、特に旧式のcsprojでの挙動がまだよくわかっていません。
Directory.Build.propsでNullableを有効化、csprojの方で個別に無効化してみたのですが、何故かnullableが有効になっていました。
全体的に無効にした上で個別に有効化したらちゃんと意図通り動きました。なんで?
まとめ
NULL安全の導入、言語バージョンの指定にDirectory.Build.propsが使えるという話でした。
破壊的な事もできてしまうので、プロダクトで使う場合は十分注意が必要です。