The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

使用 Directory.Build.props 自訂方案中所有專案共用的 MSBuild 屬性值

我們在建置 .NET 專案時,有許多可自訂的建置操作是由 MSBuild 的屬性(Properties)所控制的。重要的是要知道如何以及在哪裡設定屬性值,以達到期望的效果。一般來說,你可以在執行 msbuild.exe 命令列工具的時候指定屬性值,也可以在專案檔(*.csproj)中加入屬性設定,也可以在專案目錄中加入 Directory.Build.props 屬性定義檔。今天這篇文章,我就打算來介紹這個 Directory.Build.props 檔案的用法,以簡化我們方案中各專案的設定。

image

如果想知道有哪些 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,可選用的值有 NoneMinimumRecommendedAll

  • 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 套件,以及程式碼分析器規則集設定,更能夠幫助團隊提升程式碼品質!👍

相關連結

留言評論