FlubuCore 入門:建置 .NET Core 專案

這篇文章要介紹我才剛接觸的一個建置工具:FlubuCore。(最後更新日期:2020-5-27


內容綱要:
  • 為什麼想用 FlubuCore?
  • 安裝
  • 加入 build script 專案
  • 執行 build script
  • 使用 .flubu 檔案
  • 結語

為什麼想用 FlubuCore?

大約兩年前寫了〈Nuke 自動建置入門教學〉和〈使用 Nuke 來打包 Nuget 套件〉,後來就一直在自己的 .NET 專案中使用 Nuke 來寫建置腳本。想嘗試不同的建置工具,倒也不是因為 Nuke 有什麼缺點,而比較像是逛賣場時發現新口味的泡麵——當我發現 FlubuCore,便拿一個手邊的專案來試試看。

FlubuCore 的意思是「Fluent Builder Core」。從名稱便可看出,它跟 Nuke 一樣是自動建置專案的工具、可使用流暢式(fluent)API  寫法、以及支援 .NET Core。雖然它也支援傳統的 .NET Framework,但我只在意 .NET Core,所以本文部分內容可能不適用於 .NET Framework。

以下便是我初次使用 FlubuCore 來建置 .NET Core 專案的筆記。

安裝

用以下指令來安裝 .NET 全域工具:

dotnet tool install --global FlubuCore.Tool

👉本文範例使用的版本是 5.1.8

安裝完成後,將來便可以利用命令列工具 flubu 來建置專案。

要提醒的是,如果你原本已經在建置腳本專案中使用了 FlubuCore,後來要更新到最新的版本,那麼除了更新專案中的 FlubuCore 套件,你還必須更新它的全域工具

dotnet tool update --global flubucore.tool

加入 build script 專案

FlubuCore 跟 Nuke 有個相同之處:它們的建置腳本就是我們平常在寫的 C# 程式。所以第一個步驟就是要在我們的應用程式的方案(solution)中加入一個新的專案,用來寫建置腳本。
註:FlubuCore 有提供命令列工具來快速建立 build script 專案,只是我傾向手動建立,以便經歷每個細節。
這個建置腳本的專案一般建議命名為 "build"、"Build" 或 "_Build" 或 "BuildScript",請不要使用其他不符合慣例的名稱,以免增加自己的麻煩。(flubu 命令列工具會自動搜尋幾個常用的資料夾名稱,稍後有完整列表。)

操作:在 Visual Studio 中開啟應用程式的方案(solution),然後在此方案中加入一個新專案。專案範本選擇 Class Library (.NET Core),專案名稱取名為 "build"。建置腳本專案的所在目錄,我選擇放在整個 repository 工作目錄的最上層。工作目錄的結構看起來會像這樣:


把目錄展開來,會像這樣:

(root)
  + build

    build.csproj
    BuildScript.cs
  + source

    - BuildAll.sln
    + MyApp
    + ClassLibrary1
  + doc
  + output
 

 
其中的 output 目錄是用來存放產品部署的檔案,無需事先建立。

另一種常見的配置是把建置腳本專案放在 source 目錄下,也是沒問題的,只要建置腳本在執行的時候能夠找到你的 solution 的 .sln 檔案就行了(底下範例有展示如何指定 .sln 檔案的所在路徑與檔名)。

Build script 專案建立完成後,加入 FlubuCore 套件:


👉 本文範例後來改成使用 5.1.8 版,所以請安裝 5.1.8 或更新的版本。如果要安裝最新的預覽版,請將上圖中的 Include prerelease 選項打勾。

接著加入一個類別,命名為 "BuildScript.cs"。注意這裡的檔案名稱也是按照慣例來命名的,不要任意取別的名稱。

底下是一個典型的建置腳本:


此建置腳本具備三項任務(targets):
  • clean:清空輸出資料夾(第 36~39 行)。
  • compile:編譯整個 solution(第 41~44 行)。這裡還一併指定了應用程式的版本編號,而版本編號是由外部檔案 ProductVersion.txt 來控制。
  • publish:發佈(第 46~50 行)。發佈的時候,通常會指定一個輸出資料夾。
而且三者有依賴關係,例如 publish 依賴 compile,而 compile 又依賴 clean。所以當你在命令列指定要執行 publish 任務時,就會依序執行 cleancompile、和 publish
補充說明:如果透過 UpdateNetCoreVersionTask 方法來指定應用程式的版本編號,它會去修改專案的.csproj 檔案,並在其中加入 <Version><AssemblyVersion><FileVersion> 等元素。

此範例的 ProductVersion.txt 只是單純的文字檔,裡面只有一行文字,寫著版本編號,例如 "3.1.0"。

第 25 行的 BuildConfiguration 屬性設定為 "Release",代表建置專案時所使用的組態名稱。這個組態名稱就是對應到你在 Visual Studio 的 Configuration Manager 視窗裡建立的組態,通常會有 "Debug" 和 "Release" 兩種組態,可分別為「除錯」和「發行」這兩種場景提供不同的建置與部署設定。

另外,通常我們不需要為 "build"(前面範例中的 "compile" 任務)指定特別的輸出路徑。預設情況下,編譯過的 .DLL 和 .EXE 檔案都會輸出至專案的 bin/debug/[目標框架]/ 目錄下,而一般建議是就讓它們留在那裡。另一方面,當我們要執行打包(pack)、部署(deploy)、發布(publish)等工作時,則通常會指定一個特定的輸出目錄。

建置腳本寫好之後,先編譯這個專案,確認無誤之後,就可以到命令列視窗執行建置指令了。

執行 build script

開啟命令列視窗,並將現行目錄切換至專案所在的 source 目錄,然後輸入以下指令來執行建置腳本:

flubu compile

其中的 "compile" 就是欲執行的目標工作(target),名稱對應到前面的 BuildScript.cs 裡面的第 41 行(傳入 CreateTarget 方法的字串)。

執行過程看起來會像這樣:


請注意前面幾行字,它們的意思是:「你沒有指明建置腳本檔案的所在路徑,所以我會開始到幾個預設的目錄底下尋找建置腳本檔案。」

接著下一行又說:「找到了,會使用這個腳本檔案:'build/BuildScript.cs'.」

這也就呼應了稍早提過的,建立 build script 專案時,專案名稱和建置腳本的檔案名稱最好都按照慣例,便可避免一些麻煩。

官方文件有列出預設的(會自動搜尋的)建置腳本目錄和檔案名稱,如下所示(醒目標示的項目是我偏好的命名組合):
  • Build.cs
  • BuildScript.cs
  • DeployScript.cs
  • DeploymentScript.cs
  • _Build/Build.cs
  • _Build/BuildScript.cs
  • Build/Build.cs
  • Build/BuildScript.cs
  • _BuildScript/BuildScript.cs
  • _BuildScripts/BuildScript.cs
  • BuildScript/BuildScript.cs
  • buildscript/deployscript.cs
  • buildscripts/buildscript.cs
  • buildscripts/deployscript.cs
  • BuildScript/DeploymentScript.cs
  • BuildScripts/DeploymentScript.cs

使用 .flubu 檔案

如果你的建置腳本專案放在比較特殊的路徑,或者使用了比較特別的檔案名稱,你還可以使用 flubu setup 指令來建立一個組態檔。這個指令會以問答的方式要你輸入建置腳本的 .cs 檔案名稱以及建置腳本專案的 .csproj 檔案名稱(二者皆使用相對路徑)。參考下圖:


此指令執行完畢後,便會在你執行該指令的所在目錄下產生一個名為 ".flubu" 的純文字檔案,裡面的內容就是你在上圖中回答的兩個檔案名稱,而且檔案路徑是採用相對路徑名,就像這樣:

build/BuildScript.cs
build/build.csproj

結語

初次使用 FlubuCore,目前覺得挺好。同時,儘管 FlubuCore 也支援 GitVersion,但我開始覺得,使用 GitVersion 來自動設定組件的版本編號對我來說是弊多於利。本文範例腳本使用一個純文字檔案來控制組件版本編號,優點是簡單、明確。如果使用 GitVersion,每一次建置專案時,我還得去注意 GitVersion 這次使用的版本編號是否跟我所想的一樣,徒增煩惱。

另外,本文也有提到 Flubu 命令列工具能夠產生 .flubu 檔案,以便紀錄建置腳本檔案的所在路徑。這個 .flubu 檔案的內容雖然簡單(內容只有兩行文字),但是卻扮演了相當重要的角色,因為它解決了建置腳本的一個重要問題:如何決定工作目錄,以便在編寫建置腳本時能夠使用相對路徑名。有關這個部分,我會在下一篇文章裡進一步說明。

Happy building!

參考資料
技術提供:Blogger.