使用 Phantom 來自動建置 .NET 專案

先前嘗試用 IronRuby + Rake,好不容易把必要工具都裝好了,也學了點 Ruby 語法,卻發現它無法正確處理中文字元,於是改用原先 survey 的選項之一:Phantom

這篇筆記會說明 Phantom 的安裝步驟,並展示一個實際專案的建置腳本。

安裝 Phantom

Phantom 沒有安裝程式,只要到官網下載最新版本的壓縮檔,解開到本機的某個資料夾就行了,例如:C:\Tools\Phantom。

檔案下載的對話窗有提供 source code 和 package 的下載連結,參考下圖。


要注意的是,Package 的壓縮檔只包含可執行檔。如果你是下載 0.2 版的 package(Phantom-0.2.zip),它在執行 MSBuild.exe 時,預設是去執行 .NET Framework 3.5 版的 MSBuild.exe。也就是說,它可以建置 Visual Studio 2008 的專案,但如果碰到 Visual Studio 2010 的專案,就會建置失敗。此時,你必須在建置腳本中透過 msbuild 物件的 toolPath 屬性來指定 .NET Framework 4 的 MSBuild.exe 的完整路徑,參考這篇說明文件:MSBuild Integration

如果你下載的是包含完整 source code 的版本,此版本(v0.3)就是使用 Visual Studio 2010 來編譯,且預設使用 .NET Framework 4 的 MSBuild.exe,不過,你必須自行建置整個 Phantom 專案。由於 Phantom 本身就是用 Phantom 建置腳本 build 出來的,所以建置的過程非常簡單,只要執行原始碼套件中的 build.bat 就行了。

如果你希望在任何地方都能執行 Phantom.exe,可以將它的所在路徑加入環境變數 PATH。

安裝完成之後,我用一個簡單的建置腳本來確認它能夠正確處理中文字元,接著便開始為我目前的 .NET 專案動手編寫 Phantom 建置腳本。

編寫 Phantom 建置腳本

Phantom 建置腳本的檔案名稱是 build.boo,這個檔案必須使用 UTF-8 編碼,否則建置腳本中的中文字會變成亂碼。副檔名 .boo 已經告訴你,檔案內容是以 Boo 程式語言來撰寫。這部份的語法並不難,只要參考一下現有的建置腳本範例(例如 Phantom 專案本身的建置腳本),依樣畫葫蘆,動作快的人應該花個半小時就可以為自己的 .NET 專案寫好建置腳本。我算是動作慢的吧!(沒辦法,還得一邊寫筆記、抓圖、以及一堆有的沒的微調....)

我直接拿一個自己的類別庫專案來試,以下就是最後完成的建置腳本:

solution_file = "src/HuanlinLib.sln"
assembly_info_file = "src/AssemblyInfo_Global.cs"
configuration = "Release"

desc "預設的 target"
target default, (init, build, deploy, package):
  pass

desc "建置前的初始化動作"
target init:
  rmdir("build")

desc "清除編譯過程產生的檔案(讓原始碼保持乾淨)"  
target clean:
  rmdir("build")
  rmdir("src/Huanlin/bin")
  rmdir("src/Huanlin/obj")   
  rmdir("src/Huanlin.Braille/bin")
  rmdir("src/Huanlin.Braille/obj")   
  rmdir("src/Huanlin.TextServices/bin")
  rmdir("src/Huanlin.TextServices/obj") 
  // ....其餘省略

desc "建置專案"
target build:
  print "產生新的組件版本編號..."
  exec("UpdateVersion.exe", "-b Increment -r Automatic -i ${assembly_info_file} -o ${assembly_info_file}")
  
  print "建置專案..."
  msbuild(file: solution_file, configuration: configuration)

desc "將建置輸出結果複製到 'build' 資料夾"
target deploy:
  print "複製檔案到 build 資料夾..."
    
  with FileList(): 
    .Include("readme.txt")
    .ForEach def(file):
      file.CopyToDirectory("build/${configuration}")

  with FileList("src/Huanlin/bin/${configuration}"):
    .Include("*.{dll,exe}")
    .ForEach def(file):
      file.CopyToDirectory("build/${configuration}/HuanlinLib")

  with FileList("src/Huanlin.Braille/bin/${configuration}"):
    .Include("*.{dll,exe}")
    .Include("Braille.ini")
    .ForEach def(file):
      file.CopyToDirectory("build/${configuration}/HuanlinLib")

  // ....其餘省略

desc "建立 zip 壓縮檔"
target package:
  zip("build/${configuration}", 'build/HuanlinLib.zip')
(是不是比 XML 格式的建置腳本清爽、好讀多了呢?)

重點說明:
  • Line 2:定義一個變數:assembly_info_file,此變數稍後會用到。由於我的類別庫專案包含多個子專案,而且我想要讓每個子專案所 build 出來的組件都有相同的版本編號,因此我讓各專案共用一個 AssemblyInfo 檔案。在建置專案之前,只要先修改這個共用檔案裡面的版本編號即可。修改版本編號的動作也是自動的,稍後就會看到。
  • Line 6:定義預設的建置目標(target),名稱是 default。此 target 相依於另外四個 targets,依序是:init、build、deploy、package。也就是說,當我們用 Phantom 來執行建置腳本時,在執行 default target 之前,會先依序執行前述四個相依的 targets。
  • Line 7:只有一行 'pass',表示這裡沒有其他動作需要執行。
  • Line 10~11:建置前的初始化作業,這裡只有一個動作:刪除建置輸出的資料夾。
  • Line 25~30:build target,此區段包含建置專案的指令,主要有兩個動作:
    (1) 產生組件版本編號;
    (2) 執行 MSBuild.exe 來建置 solution 或 project。

    產生組件版本編號的工作,我是用 UpdateVersion 這個免費工具來幫我自動遞增版本編號。其實 Phantom 也有提供產生 AssemblyInfo 檔案的功能,需要的話可以參考這篇討論串:Assembly versioning

執行建置腳本

執行建置腳本的命令很簡單,只要執行 Phantom.exe,它就會在現行目錄下尋找建置腳本 build.boo,有找到的話就會自動執行預設的 target。你也可以加上命令列參數,明確指定要執行哪個 target,例如:

D:\Tools\Phantom\Phantom.exe  clean

官網的文件有完整的參數說明。

我是仿照 Phantom 專案的作法,在建置腳本 build.boo 的所在目錄下建立一個批次檔,檔名是 build.bat,內容如下:

@echo off
"..\..\3rd Party Tools\Phantom\v0.3\Phantom.exe" %*

因此,每次要建置專案時,我只要執行 build.bat 就行了。其中的參數 "%*" 代表 build.bat 命令後面帶的所有參數(如果有的話)。

小結

可能因為 Phantom 是用 C# 和  Boo 撰寫,加上我之前有用 IronRuby + Rake 寫過建置腳本的緣故,我覺得 Phantom 還蠻容易上手的,未來也有打算再為其他 .NET 專案編寫 Phantom 的建置腳本,並加上單元測試的 target。

在編寫建置腳本的過程中,我也重新檢視並調整了專案的目錄結構,讓整個目錄結構變得更乾淨、更清楚。比如說,增加一個 build 目錄,專用來存放自動建置的輸出檔案。此外,版本控制的設定也稍有變動,例如對整個專案原始碼的資料夾指定 svn:ignore 屬性,把 bin 和 obj 資料夾都加入忽略清單。

沒有留言:

技術提供:Blogger.
回頂端⬆️