跟第一集相同,本文內容僅適用於 .NET Core 專案。
內容綱要:
工具使用:FlubuCore v5.0.3
(根目錄)
+ build
build.csproj
BuildScript.cs
+ source
- BuildAll.sln
+ MyApp
+ ClassLibrary1
+ output
此目錄配置方式意味著當你在使用命令列指令來建置專案時,現行工作目錄會是 (根目錄)。
另一種常見的安排是把建置腳本也放在 source 目錄底下:
(根目錄)
+ source
- BuildAll.sln
+ build
build.csproj
BuildScript.cs
+ MyApp
+ ClassLibrary1
+ output
這種目錄配置方式則意味著當你在使用命令列指令來建置專案時,現行工作目錄通常是(但不必然是)source。
這兩種目錄結構的安排方式,對你在撰寫建置腳本時多少會有一些影響,例如 solution 檔案的相對路徑名稱、建置輸出結果(即 output 目錄)的相對路徑等等。當然,你在寫建置腳本時,也可以使用完整的路徑名稱,但這不是好主意,因為它有個缺點:一旦把建置腳本放到其他電腦上執行,可能就因為檔案路徑不同而建置失敗。(稍後會進一步說明如何在建置腳本中避免使用絕對路徑)
目錄結構的重點是 build 和 source 這兩個子目錄;前者用來存放建置腳本,腳本的專案名稱也命名為 build.csproj,而用來寫腳本內容的 C# 檔案則是 BuildScript.cs。這兩個檔案名稱都有其內定的慣例命名,在上一篇文章已經整理了預設名稱列表,就不重複列出。只要知道,按慣例來命名腳本檔案就能讓 FlubuCore 找到它們,可減少一些麻煩。同樣的,它們彼此的相對位置以及它們與「根目錄」的相對位置也是挺重要的,因為你得在建置腳本中指定建置結果的輸出路徑,也就是前面目錄結構範例中的 output 資料夾。
如果你需要在 Visual Studio 中除錯你的建置腳本,那麼最簡單的方式就是採用 Console Application 了。相較於 Class Library,採用 Console App 類型的建置腳本只是在專案中多了一個 Program.cs,如下所示:
其中的
如果想要在除錯建置腳本時,也能夠追進(trace into)FlubuCore 的原始碼,這會稍微 tricky 一點。還好我們通常不需要除錯 FlubuCore 原始碼,所以相關的專案配置以及可能碰到的問題與解法,這裡就不特別說明。
乍聽之下,使用相對路徑應該很簡單,不會是令人頭疼的問題,然而事情也不是那麼單純。底下進一步說明原因。
在建立 Console Application 類型的建置腳本專案時,基本上有兩種運行建置腳本的方式:
然而,這兩種執行建置腳本的方式有個根本上的差異:執行時的工作目錄不一樣。
當你在 Visual Stduio 中按 F5 或 Ctrl+F5 來執行建置腳本專案時,其執行時的工作目錄是建置腳本專案的輸出目錄,例如 bin/debug/netcoreapp3.1/。另一方面,當你在命令列視窗透過
既然兩種運行建置腳本的工作目錄不一樣,那麼我們在建置腳本當中使用的相對路徑名稱,到底是相對於哪一個工作目錄呢?這裡就會有問題了。
你可以在命令列視窗使用
根據我的經驗,在命令列視窗底下使用 flubu 命令來執行建置腳本時的所在目錄,就是存放 .flubu 檔案的最佳位置(通常會是整個 repository 的根目錄,或者根目錄之下的 source 目錄)。按此作法,將能夠避免許多檔案路徑找不到的問題。
如果你實際用過
這裡有個關鍵:Flubu 會從建置腳本執行時的工作目錄開始尋找 .flubu 檔案,如果找不到,就會往上層目錄尋找,直到磁碟機的根目錄或者找到 .flubu 檔案為止;而 .flubu 檔案所在的資料夾,就會被 Flubu 設定為「運行建置腳本的工作目錄」。你在建置腳本中撰寫的相對路徑名,就是相對於這個工作目錄。
以上是本文最重要的部分。接著介紹一些常見的工作與 API 用法範例。
執行此工作的命令列指令為:
範例:
第 19 行程式碼改寫了第 7 行所設定的 "Release" 組態。
另外,你也可以透過命令列的指令來蓋過建置腳本中的參數,例如:
上列指令,Flubu 在實際執行 dotnet 建置工作時,會轉換成類似底下的指令:
也就是說,只要你知道某項工作在實際執行時的外部程式有哪些命令列參數,就可以在使用 flubu 命令列工具時一併傳入。
執行此工作的命令列指令為:
注意第 10 行的
當 targetC 執行時,實際執行的工作依序為 targetB, targetA, targetC。
內容綱要:
- 工作目錄結構與檔案名稱
- 使用 Console App 為建置腳本
- 工作目錄與相對路徑
- 編譯方案(專案)
- 改寫預設參數
- 清理輸出目錄
- 目標工作的相依關係
- 工作的事件
- 結語
工具使用:FlubuCore v5.0.3
工作目錄結構與檔案名稱
在上一篇文章裡提過,我偏好的目錄結構類似這樣:(根目錄)
+ build
build.csproj
BuildScript.cs
+ source
- BuildAll.sln
+ MyApp
+ ClassLibrary1
+ output
此目錄配置方式意味著當你在使用命令列指令來建置專案時,現行工作目錄會是 (根目錄)。
另一種常見的安排是把建置腳本也放在 source 目錄底下:
(根目錄)
+ source
- BuildAll.sln
+ build
build.csproj
BuildScript.cs
+ MyApp
+ ClassLibrary1
+ output
這種目錄配置方式則意味著當你在使用命令列指令來建置專案時,現行工作目錄通常是(但不必然是)source。
這兩種目錄結構的安排方式,對你在撰寫建置腳本時多少會有一些影響,例如 solution 檔案的相對路徑名稱、建置輸出結果(即 output 目錄)的相對路徑等等。當然,你在寫建置腳本時,也可以使用完整的路徑名稱,但這不是好主意,因為它有個缺點:一旦把建置腳本放到其他電腦上執行,可能就因為檔案路徑不同而建置失敗。(稍後會進一步說明如何在建置腳本中避免使用絕對路徑)
目錄結構的重點是 build 和 source 這兩個子目錄;前者用來存放建置腳本,腳本的專案名稱也命名為 build.csproj,而用來寫腳本內容的 C# 檔案則是 BuildScript.cs。這兩個檔案名稱都有其內定的慣例命名,在上一篇文章已經整理了預設名稱列表,就不重複列出。只要知道,按慣例來命名腳本檔案就能讓 FlubuCore 找到它們,可減少一些麻煩。同樣的,它們彼此的相對位置以及它們與「根目錄」的相對位置也是挺重要的,因為你得在建置腳本中指定建置結果的輸出路徑,也就是前面目錄結構範例中的 output 資料夾。
用來存放建置結果的 output 資料夾無需事先建立,也無須保存檔案的版本,所以通常會加入 .gitignore 檔案,以免存入 Git 儲存庫。
使用 Console App 為建置腳本
FlubuCore 的建置腳本可以是 Class Library 或 Console Application 類型的專案,前者編譯結果為 .dll,後者為 .exe。無論哪一種應用程式類型,在命令列視窗裡面下的指令都一樣是flubu [target]
。如果你需要在 Visual Studio 中除錯你的建置腳本,那麼最簡單的方式就是採用 Console Application 了。相較於 Class Library,採用 Console App 類型的建置腳本只是在專案中多了一個 Program.cs,如下所示:
其中的
BuildScript
類別就是你的建置腳本。如果你對這個部分覺得陌生,請先閱讀我的上一篇文章:〈FlubuCore 入門:建置 .NET Core 專案〉。如果想要在除錯建置腳本時,也能夠追進(trace into)FlubuCore 的原始碼,這會稍微 tricky 一點。還好我們通常不需要除錯 FlubuCore 原始碼,所以相關的專案配置以及可能碰到的問題與解法,這裡就不特別說明。
👉 如需除錯 FlubuCore 程式碼,可參考官方文件 Test and Debugging。我的作法比較像土法煉鋼,將來若有適當時機,再寫專文介紹。
工作目錄與相對路徑
前面提過,在編寫建置腳本時,檔案路徑名稱最好不要使用完整路徑,否則當你把建置腳本放在其他機器上面執行時,很可能會因為路徑找不到而發生錯誤。乍聽之下,使用相對路徑應該很簡單,不會是令人頭疼的問題,然而事情也不是那麼單純。底下進一步說明原因。
在建立 Console Application 類型的建置腳本專案時,基本上有兩種運行建置腳本的方式:
- 在命令列視窗中,以
flubu
指令來執行建置腳本。 - 在 Visual Studio 環境中,以 F5 或 Ctrl+F5 來執行建置腳本專案(以便除錯建置腳本)。
然而,這兩種執行建置腳本的方式有個根本上的差異:執行時的工作目錄不一樣。
當你在 Visual Stduio 中按 F5 或 Ctrl+F5 來執行建置腳本專案時,其執行時的工作目錄是建置腳本專案的輸出目錄,例如 bin/debug/netcoreapp3.1/。另一方面,當你在命令列視窗透過
flubu
指令來執行建置腳本時,其工作目錄則是下指令當時的所在目錄,而且通常是 solution 所在的目錄,或整個專案的最上層目錄。既然兩種運行建置腳本的工作目錄不一樣,那麼我們在建置腳本當中使用的相對路徑名稱,到底是相對於哪一個工作目錄呢?這裡就會有問題了。
解決方法:使用 .flubu 檔案
要達到前面說的目標(兩種運行建置腳本的結果必須一致),同時又要避免在建置腳本中使用完整路徑,目前看來最簡單、也可能是唯一的解決方法,就是使用 .flubu 檔案。你可以在命令列視窗使用
flubu setup
指令來產生 .flubu 檔案,具體作法可參考上一篇文章的說明。這裡的重點是 .flubu 檔案該放在哪個資料夾。根據我的經驗,在命令列視窗底下使用 flubu 命令來執行建置腳本時的所在目錄,就是存放 .flubu 檔案的最佳位置(通常會是整個 repository 的根目錄,或者根目錄之下的 source 目錄)。按此作法,將能夠避免許多檔案路徑找不到的問題。
如果你實際用過
flubu setup
指令來產生 .flubu 檔案,你會知道 .flubu 檔案裡面保存的是建置腳本檔案的相對路徑名。再細想一下,你可能會問:這樣一來,當你在 Visual Studio 中按 F5 來執行建置腳本時,其輸出目錄(也是執行時的工作目錄)是 bin/Debug 底下的資料夾,那麼建置腳本如何找到需要建置的 .sln 和其他相關檔案呢?這裡有個關鍵:Flubu 會從建置腳本執行時的工作目錄開始尋找 .flubu 檔案,如果找不到,就會往上層目錄尋找,直到磁碟機的根目錄或者找到 .flubu 檔案為止;而 .flubu 檔案所在的資料夾,就會被 Flubu 設定為「運行建置腳本的工作目錄」。你在建置腳本中撰寫的相對路徑名,就是相對於這個工作目錄。
💬 萬一 Flubu 找不到 .flubu 檔案呢?那麼它就會以「執行建置腳本時的所在目錄」作為工作目錄。
以上是本文最重要的部分。接著介紹一些常見的工作與 API 用法範例。
編譯方案(專案)
建置腳本的各項工作,或者說目標(target),都是寫在ConfigureTargets
方法裡面。底下範例的功能是用來編譯一個方案或專案:執行此工作的命令列指令為:
flubu compile
改寫預設參數
所有執行外部程序的工作,都可以加入其他參數,也可以改寫既有的參數。範例:
第 19 行程式碼改寫了第 7 行所設定的 "Release" 組態。
另外,你也可以透過命令列的指令來蓋過建置腳本中的參數,例如:
flubu compile --configuration=Debug
上列指令,Flubu 在實際執行 dotnet 建置工作時,會轉換成類似底下的指令:
flubu dotnet build MyApp.sln --configuration Debug
也就是說,只要你知道某項工作在實際執行時的外部程式有哪些命令列參數,就可以在使用 flubu 命令列工具時一併傳入。
相關文件:Override existing options or add additional options to tasks through console
清理輸出目錄
底下範例 target 的作用是清除輸出目錄:執行此工作的命令列指令為:
flubu clean
目標工作的相依關係
建置腳本通常包含多項工作,而有些工作可能彼此有執行上的先後順序關係。以下結合剛才兩個範例來示範多個相依 target 之間的執行順序:注意第 10 行的
DependsOn
方法,這行的作用是告訴 FluboCore:要執行 compile
工作之前,必須先執行 clean
。DependsOn
方法接受一個參數陣列,這表示你可以傳入多個相依工作。例如:當 targetC 執行時,實際執行的工作依序為 targetB, targetA, targetC。
工作的事件
你可以針對每一項工作出錯或結束的時候寫一些額外的程式碼。出錯的時候是呼叫工作的OnError
方法,工作結束時呼叫 Finally
方法。Finally
方法的運作方式如同 C# 的finally
關鍵字:無論執行過程是否發生錯誤,最終都會呼叫 Finally
方法。參考以下範例:結語
這是我的第二篇介紹 FlubuCore 的文章,其中最重要的部分,我認為是 FlubuCore 針對「如何決定工作目錄」所提出的解決辦法,也就是 .flubu 檔案以及自動搜尋 .flubu 檔案的機制。解決了這個問題,我們便能夠在建置腳本中使用相對路徑名,而無須擔心在哪個資料夾啟動建置腳本。
FlubuCore 還有許多功能是我在最近兩篇文章裡面沒還提到的,例如:以互動模式執行、為工作撰寫自訂方法、撰寫自訂工作(task plugin)等等。如果需要更多資訊,可以參考 Flubu 官方文件。
如果你也在使用 FlubuCore,記得到它的 GitHub 頁面上點個星星喔。
Happy building!
FlubuCore 還有許多功能是我在最近兩篇文章裡面沒還提到的,例如:以互動模式執行、為工作撰寫自訂方法、撰寫自訂工作(task plugin)等等。如果需要更多資訊,可以參考 Flubu 官方文件。
如果你也在使用 FlubuCore,記得到它的 GitHub 頁面上點個星星喔。
Happy building!