我們在建置 .NET 專案時,有許多可自訂的建置操作是由 MSBuild 的屬性(Properties)所控制的。重要的是要知道如何以及在哪裡設定屬性值,以達到期望的效果。一般來說,你可以在執行 msbuild.exe
命令列工具的時候指定屬性值,也可以在專案檔(*.csproj
)中加入屬性設定,也可以在專案目錄中加入 Directory.Build.props
屬性定義檔。今天這篇文章,我就打算來介紹這個 Directory.Build.props
檔案的用法,以簡化我們方案中各專案的設定。
如果想知道有哪些 MSBuild 屬性可用,可參考 MSBuild 常見屬性 文件。
MSBuild 其是一個相當複雜的工具,相對的也非常靈活與強大,這篇文章我不打算講得太複雜,只打算帶入一個情境,幫助大家理解有哪些地方可以透過 Directory.Build.props
來客製化專案的建置流程。對於更深入的 MSBuild 設定,可以參考 Customize your build 文件。
首先,你要知道的一個重點是,當你在建置特定專案時,你的 *.csproj
裡面就包含了許多 MSBuild 屬性(Properties)與目標(Targets)定義,這些定義有些是從其他地方匯入的。我以 ASP.NET Core 專案為例,你的 *.csproj
檔案中,第一行就會匯入特定專案類型的所有屬性與目標:
<Project Sdk="Microsoft.NET.Sdk.Web">
...
</Project>
這段定義其實就是幫你匯入 C:\Program Files\dotnet\sdk\8.0.100\Sdks\Microsoft.NET.Sdk.Web
目錄下的 *.props
與 *.targets
檔案,這些檔案就是定義了 ASP.NET Core 專案的所有屬性與目標,其中當然也包含了預設匯入的 namespace 與需要參考的 NuGet 套件。
當我們在建置專案時,除了先載入上述 <Project>
匯入的哪些屬性外,還會從當前目錄找尋一個名為 Directory.Build.props
的檔案,如果有找到的話,就會載入這個檔案中的屬性定義。這個檔案的位置可以是當前專案目錄,也可以是當前專案目錄的上層目錄,也可以是當前專案目錄的上上層目錄,以此類推。如果你的方案中有多個專案,而你希望這些專案都共用同一組屬性定義,那麼你就可以在方案目錄中加入一個 Directory.Build.props
檔案,這樣所有專案都會共用這個檔案中的屬性定義。
瞭解這點之後,我們就可以來介紹一些常見的使用案例了。
設定所有專案都要用 SonarAnalyzer.CSharp 套件來進行程式碼分析
假設你的方案中有多個專案,而你希望這些專案都共用同一組 NuGet 套件,那麼你就可以在方案目錄中加入一個 Directory.Build.props
檔案,並在這個檔案中加入下列內容:
<Project>
<ItemGroup>
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.17.0.82934">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
你沒看錯,只要簡單設定一下,預設你的「每個專案」都會自動加入 SonarAnalyzer.CSharp 套件參考,如此一來你的整個方案下所有專案都不需要再設定 NuGet 參考了,而且都可以透過 SonarAnalyzer.CSharp 套件來進行程式碼分析,是不是方常方便呢!👍
設定所有專案都要將 Warnings 視為 Errors
在某些要求高品質的專案,我們需要強制團隊成員認真面對所有的編譯警告(Compiler Warning),這時候我們可以在 Directory.Build.props
檔案中加入 <PropertyGroup>
設定,並加入兩個重要的屬性:
<Project>
<PropertyGroup>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.17.0.82934">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
設定所有專案都要套用一致的程式碼風格
我們可以透過 .editorconfig
定義 C# 的程式碼風格,但是如果你的方案中有多個專案,而你希望這些專案都共用同一組程式碼風格,那麼你就可以在方案目錄中加入一個 Directory.Build.props
檔案,並在這個檔案中加入下列內容:
<Project>
<PropertyGroup>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
</PropertyGroup>
</Project>
詳細介紹可參考 .NET code style rule options - .NET | Microsoft Learn 文件。
設定所有專案都要使用相同的 Nullable 設定
我們可以透過 *.csproj
定義 C# 的 Nullable 設定,但是如果你的方案中有多個專案,而你希望這些專案都共用同一組 Nullable 設定,那麼你就可以在方案目錄中加入一個 Directory.Build.props
檔案,並在這個檔案中加入下列內容:
<Project>
<PropertyGroup>
<Nullable>enable</Nullable>
<NoWarn>CS8618</NoWarn>
</PropertyGroup>
</Project>
設定所有專案都要使用相同的 TargetFramework 版本
我們可以透過 *.csproj
定義 C# 的 TargetFramework 設定,但是如果你的方案中有多個專案,而你希望這些專案都共用同一組 Nullable 設定,那麼你就可以在方案目錄中加入一個 Directory.Build.props
檔案,並在這個檔案中加入下列內容:
<Project>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
</Project>
設定所有專案都要使用相同的程式碼分析器版本
.NET SDK 其實內建許多 Code Analysis (CA) 程式碼分析器規則集,但預設只有啟用一小部分規則而已,如果你希望所有專案都要使用相同的程式碼分析器模式,那麼你就可以在方案目錄中加入一個 Directory.Build.props
檔案,並在這個檔案中加入下列內容:
<Project>
<PropertyGroup>
<AnalysisMode>All</AnalysisMode>
<AnalysisLevel>latest</AnalysisLevel>
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
</PropertyGroup>
</Project>
上述三個屬性的說明如下:
-
AnalysisMode
指定要使用的程式碼分析器模式,預設為 Default
,可選用的值有 None
、Minimum
、Recommended
、All
。
-
AnalysisLevel
由於這些規則集都是跟著 .NET SDK 走的,所以你可以指定分析器的版本,或是直接指定 latest
直接用最新版即可。
-
CodeAnalysisTreatWarningsAsErrors
指定是否將程式碼分析器的警告視為錯誤,預設為 false
。
從 .NET 6 開始,你其實可以忽略 <AnalysisMode>
設定,直接使用 <AnalysisLevel>
來設定即可。
例如以下設定:
<AnalysisMode>Recommended</AnalysisMode>
<AnalysisLevel>latest</AnalysisLevel>
就可以替換成以下設定:
<AnalysisLevel>latest-Recommended</AnalysisLevel>
.NET SDK 內建的規則集可以從這份 AnalyzerReleases.Shipped.md 文件查到。
總結
有了上述幾個使用案例,各位應該不難發現 Directory.Build.props
真的實用的地方,就是可以大幅簡化方案中每個專案的 MSBuild 定義,確保團隊使用一致的設定。若搭配一些程式碼分析器 NuGet 套件,以及程式碼分析器規則集設定,更能夠幫助團隊提升程式碼品質!👍
相關連結