新建一個構建任務及任務依賴關係設定
上節我們通過新建一個HelloWorld示例講解了如何編寫build.cake以及如何下載build.ps1啟動檔案以及如何執行.實際專案中,我們使用最多的是對專案進行編譯.本節我們講解如何建立一個編譯任務.
新增一個編譯任務
我們仍然使用上節使用的build.cake檔案,我們複製一下Default任務,並把它改名為BuildProject
程式碼如下
Task("BuildProject")
.Does(() => {
Information("Hello World!");
});
通過上一節程式碼我們可以看到Information方法僅僅輸出了一行資訊,對我們構建可能並沒太大作用.Cake
提供了一個Msbuild
方法,我們可以使用該方法來編譯我們的專案,修改後的程式碼如下
Task("BuildProject")
.Does(() => {
MSBuild("buildDemo.sln");//我的專案名稱叫作buildDemo.sln,這裡改為你的實際專案名
});
新增完以上程式碼後我們執行,發現構建並沒有執行,這是因為這裡我們僅僅是定義了一個Task,並沒有執行它,我們需要顯式地執行這個任務
修改RunTarget方法
最下面的Runtarget預設接收的引數叫作target,我們 把它替換為BuildProject
修改後程式碼如下
RunTarget("BuildProject");
這時候我們再執行build.ps1
可以發現編譯任務執行的(我們可以進到專案目錄下,看到目錄下生成了bin目錄,bin目錄下面生成了debug目錄,裡面有編譯的檔案),如果bin目錄已經存在,我們可以把它刪除了,然後再執行任務,看看是否生成了bin目錄.
RunTarget是通過任務的名稱來確定要執行的任務的.
通過以上簡單的命令我們就實現了自動編譯一個.net專案,Cake的強大之處還有很多,遠不止於此,後面我們會有更多小節來講我解Cake的功能.
設定任務依賴關係
上面我們修改了RunTarget
的引數讓它不再執行預設任務,而是來執行BuildProject
,如果我們想要執行Default任務又需要修改程式碼來讓它執行預設任務,如果我們有很多個任務,這樣修改很明顯是很繁瑣的,也與自動化構建格格不入(頻繁修改指令碼嚴重背離了自動化初衷)
其實我們可能通過設定任務依賴,讓預設任務依賴於構建任務,這樣在執行default之前會先執行構建任務,達到了兩個任務都被執行的目的.程式碼如下
Task("BuildProject")
.Does(() => {
MSBuild("buildDemo.sln");
});
Task("Default")
.IsDependentOn("BuildProject")
.Does(() => {
Information("Hello World!");
});
RunTarget(target);
通過Task的IsDependentOn
方法,我們可以設定Default任務依賴於BuildProject
任務
通過以上我們僅僅是為了讓BuildProject
和Default
兩個任務同時執行,並不能看到任務依賴作用的具體體現,實際專案中,我們為了編譯一個專案,首先要還原Nuget包,為了執行單元測試,首先要編譯專案.如果步驟錯了,將會導致構失敗.
變數的設定及讀取
在一些複雜的構建任務中,往往不可能只執行一個固定指令碼就萬事大吉,還需要根據實際需要在構建時傳入各種構建引數.將一些可能需要經常修改的項通過引數暴露出來往往也是一種良好的設計,極大地增加了構建的靈活性.當然一切還需要以實際需求為準,不能為了設計而設計,暴露過多配置項同時會增加使用者的壓力
在第一節HelloWorld示例中我們的程式碼裡最前面是兩段這樣的程式碼
var target = Argument("target", "Default");
var configuration = Argument("configuration", "Release");
前面章節我們只講解了任務及簡單介紹了Setup和TearDown兩個特殊任務,並沒有講解上面這兩段程式碼的來龍去脈,這節我們把它們弄清楚.
我們一開始就說過Cake檔案裡的程式碼都是C#程式碼,也都必須符合C#語法規範.上面兩段程式碼都包含var
關鍵字,在C#裡 var
是用來宣告一個變數的,實際上這裡也確實是宣告瞭兩個變數,其中Argument
帶有括號,裡面接收兩個引數,在C#裡它是方法,其中第一個引數是變數的名,第二個引數為變數的預設值.
在RunTarget方法裡預設傳入的是target變數,它的預設值是
Default
,因此會去執行名字為Default
的任務,至此,我們應該明白為什麼任務Default
會執行了.
下面我們輸入下configuration看看它的值是什麼
程式碼如下
var target = Argument("target", "Default");
var configuration = Argument("configuration", "Release");
Information($"變數configuration的值是:{configuration}");
return;
//下面的程式碼省略
我們說過Cake程式碼實際上是C#程式碼,因此我們可以大但地使用C#語法,這裡使用return是為了除錯方便,程式執行到這裡就中止了,以防執行的任務過多執行的時間過長.
執行後我們可以看到輸入的是變數configuration的值是:Release
,target的值是Default,configuration的值是Release,這和直接定義變數沒有什麼太大區別比如直接定義var target=Default
這樣更為方便.
前面我們說過,Argument方法接收兩個引數,第一個是變數的名稱,其中變數是可以通過外部傳遞進來的,這樣就極大的增加了靈活性.
執行啟動指令碼時傳入引數
通過從外部傳入引數,這樣就極大增加了指令碼的靈活性,我們可以根據傳入的引數來決定要執行的邏輯從而不同的構建任務只需要修改引數而不需要修改指令碼就能達到適應不同構建的目的.
前面執行build.ps1指令碼的時候我們什麼引數也沒有傳入,這裡我們傳入configuration,程式碼如下
.\build.ps1 -ScriptArgs "--configuration=Debug"
在powershell裡執行以上指令碼,我們可以看到輸入的內容變數了變數configuration的值是:Debug
,可以看到Cake指令碼Argument方法已經接收到了名為configuration
的變數的值,這裡使用的是傳入的值,而不再是預設值
傳入其它型別的值
上面定義的兩個變數都是字串型別的值,很多時候我們需要傳入布林值,或者int型別的值,當然我們可以通過c#內建的轉換命令把字串轉換為目標型別,然而我們不需要這麼做,Argument是一個泛型方法,可以接收泛型引數.例如以下會得到一個Int的變數
var num=Argument<int>("num",0);
預設值不是必須的,但是強烈建議代上預設值,如果沒有預設值,則必須傳入相應的引數,否則執行的時候就會報錯.
獲取環境變數值
對於一些複雜的構建,我們可能需要獲取環境變數的值,當然我們可以通過.net內建的方法來獲取環境變數的值,實際上Cake提供的簡單的方法來獲取環境變數的值,舉例我們想要獲取javahome環境變數的值,可以通過以下程式碼獲取
var javaHome=EnvironmentVariable("JAVA_HOME");
我們都知道JAVA_HOME
為java_home環境變數的key,通過這個key來獲取環境變數的值.
以上獲取的都是簡單的鍵值對,如果是複雜的物件,則無法通過上述方法獲取,我們說過,這裡再強調一遍,cake實際上使用的就是C#語言,因此我們可以通過自己寫程式碼來解析xml,json或者文字文件等獲取複雜的配置,並轉成實體物件.