歡迎光臨
每天分享高質量文章

記錄使用 Cake 進行構建並製作 nuget 包

前段時間折騰了一下,總算是把我自己的圖片快取控制元件(https://github.com/h82258652/HN.Controls.ImageEx)發佈到了 nuget 上,目前已經進入一個比較穩定的版本了,基本沒有很嚴重的 bug 了。其實核心代碼早就寫完了,後期主要都在折騰持續集成以及自動構建(包含製作 nuget 包)。持續集成使用了 appveyor,園子里也有不少相關的資料,這裡我就不說了。

在製作 nuget 包的過程中,我折騰了很久,最開始打算直接用 appveyor 的自動打包功能,但是在打包 UWP 的包時,打包出來的版本號一直都是 1.0.0,而 WPF 的就沒這問題(這個已確認是 appveyor 的 bug,然而好久都還沒有修複(lll¬ω¬))。另外包里的 dll 的版本號也不好統一控制,我發一次版本需要發 3 個 nuget 包,每個 nuget 包都有一個 dll,手動折騰版本號那不切實際的。

在經過一番調研之後,我終於發現了一個能滿足我需求的工具,Cake,也叫 C# Make,是一個專門用來進行 .net 專案構建的工具。官方網站在此:https://cakebuild.net/

接下來就按著教程開始吧。

這個是我專案的根目錄。接下來我們在此目錄運行 Powershell(可以通過左上角的檔案 –> 打開 Windows Powershell 來打開)。然後輸入以下命令。

Invoke-WebRequest https://cakebuild.net/download/bootstrapper/windows -OutFile build.ps1

然後敲下回車,稍微等待之後,我們的目錄下就會出現一個叫 build.ps1 的檔案。

接下來我們在該目錄創建一個叫 build.cake 的空白檔案,這個檔案主要就是執行構建的邏輯。

然後在宇宙最強的 IDE,Visual Studio 中進行編寫腳本吧,在這裡,建議各位看官先安裝一個插件:

安裝之後,Visual Studio 就具備對 .cake 腳本的語法高亮能力(可惜還是沒法有語法提示功能/(ㄒoㄒ)/~~)。

使用 Visual Studio 打開 build.cake 之後,先編寫個 Hello world 熱熱身:

var target = Argument("target", "Default");

Task("Default")
  .Does(() =>
{
  Information("Hello World!");
});

RunTarget(target);

然後儲存並運行剛纔的 build.ps1。(Powershell 里輸入 .\build.ps1

如果運氣好的話,那麼你應該和我一樣碰到了這樣的情況:

這是由於執行 Powershell 腳本是一直比較危險的操作,所以需要更改權限。

輸入如下的腳本:

或者可以參考微軟的官方文件來修改權限:https://docs.microsoft.com/zh-cn/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-6

接著再次執行腳本,應該就可以看見如下信息。

我們的 Hello world 終於跑起來了,熱身完畢,接下來開始編寫構建腳本。

Cake 腳本是由一個個 Task 串聯起來的,我們先定義一些變數和一個叫 Build 的 Task,用於執行構建。

var target = Argument("target", "Default");
var configuration = Argument("configuration", "Release");
var verbosity = Argument("verbosity", Verbosity.Minimal);

var solution = "./HN.Controls.ImageEx.sln";

Task("Build")
    .Does(() =>
{
    if(IsRunningOnWindows())
    {
        // Use MSBuild
        MSBuild(solution, configurator =>
            configurator.SetConfiguration(configuration)
                .SetVerbosity(verbosity));
    }
    else
    {
        // Use XBuild
        XBuild(solution, configurator =>
            configurator.SetConfiguration(configuration)
                .SetVerbosity(verbosity));
    }
});


Task("Default")
    .IsDependentOn("Build");

RunTarget(target);

這裡定義了一些變數,configuration 定義為 Release,在 Build Task 里用到,設置為使用 Release 樣式。verbosity 表示編譯時的信息輸入,這裡設置為 Minimal,以免輸出過多的信息。solution 表示解決方案的路徑。然後運行:

這樣一執行就把這個解決方案構建了一遍。

然後我們開始編寫打包的 Task,命名為 Package。修改腳本如下:

var target = Argument("target", "Default");
var configuration = Argument("configuration", "Release");
var verbosity = Argument("verbosity", Verbosity.Minimal);
var version = Argument("version", "1.0.0");

var solution = "./HN.Controls.ImageEx.sln";

Task("Build")
    .Does(() =>
{
    if(IsRunningOnWindows())
    {
        // Use MSBuild
        MSBuild(solution, configurator =>
            configurator.SetConfiguration(configuration)
                .SetVerbosity(verbosity));
    }
    else
    {
        // Use XBuild
        XBuild(solution, configurator =>
            configurator.SetConfiguration(configuration)
                .SetVerbosity(verbosity));
    }
});

Task("Package")
    .IsDependentOn("Build")
    .Does(() =>
{
    var nuGetPackSettings = new NuGetPackSettings
    {
        Version = version
    };

    var nuspecFiles = GetFiles("./src/*/*.nuspec");
    NuGetPack(nuspecFiles, nuGetPackSettings);
});

Task("Default")
    .IsDependentOn("Package");

RunTarget(target);

在這裡我加了一個 version 的變數,在下麵打包 nuget 包的時候會用到,統一每個 nuget 包的版本號。GetFiles(“./src/*/*.nuspec”) 這個則獲取了源檔案夾下麵的專案下的 nuspec 檔案(我這裡一個 nuspec 對應一個 csproj,就放到同一個檔案夾下了),這個檔案的作用是用於描述 nuget 包如何進行打包,具體可以參考本文開頭指向的上一篇文章。

執行之後,我們會得到些 nuget 包(當然對於看官你們的專案需要有 nuspec 才行啦):

編譯、打包都說完了。最後就是版本號的問題。nuget 包的版本在上面已經解決了,現在就是 dll 的版本號比較棘手。在我這三個專案中,WPF 和 UWP 都是傳統的專案,都是有一個 AssemblyInfo.cs 的檔案,然后里面通過 AssemblyVersionAttribute 來設置 dll 的版本號的。但是我這個 Core 的專案是新型別的專案,並沒有 AssemblyInfo.cs 檔案,版本號是在 csproj 里設置的。這難道沒辦法了麽,最後通過萬能的 Google 和 StackOverflow,我還是找到了辦法。編輯 csproj 檔案,並添加下麵一節。

這樣,這個專案的版本號等信息就不會從 csproj 裡面讀取。我們可以添加自己的 AssemblyInfo.cs 檔案進行版本號管理。

現在情況就是每個專案都有自己的 AssemblyInfo.cs 了,如何統一使用一個 AssemblyInfo.cs 檔案來管理這幾個專案呢?還記得 Visual Studio 有一個添加取用檔案的功能麽?

這樣幾個專案都通過這種方式取用同一個 AssemblyInfo.cs 檔案就行了。

最後的問題就是如何將 AssemblyInfo.cs 里的版本號跟 build.cake 腳本里的版本號保持一致。在查閱 Cake 的官方文件後,我發現有一個能生成 AssemblyInfo 的功能。修改我們的 build.cake 腳本:

var target = Argument(target, Default);

var configuration = Argument("configuration", "Release");
var verbosity = Argument("verbosity", Verbosity.Minimal);
var version = Argument("version", "1.0.0");

var solution = "./HN.Controls.ImageEx.sln";

Task("Version")
    .Does(() =>
{
    var file = "./src/SolutionInfo.cs";
    CreateAssemblyInfo(file, new AssemblyInfoSettings
    {
        Version = version,
        FileVersion = version,
        InformationalVersion = version
    });
});

Task("Build")
    .IsDependentOn("Version")
    .Does(() =>
{
    if(IsRunningOnWindows())
    {
        // Use MSBuild
        MSBuild(solution, configurator =>
            configurator.SetConfiguration(configuration)
                .SetVerbosity(verbosity));
    }
    else
    {
        // Use XBuild
        XBuild(solution, configurator =>
            configurator.SetConfiguration(configuration)
                .SetVerbosity(verbosity));
    }
});

Task("Package")
    .IsDependentOn("Build")
    .Does(() =>
{
    var nuGetPackSettings = new NuGetPackSettings
    {
        Version = version
    };

    var nuspecFiles = GetFiles("./src/*/*.nuspec");
    NuGetPack(nuspecFiles, nuGetPackSettings);
});

Task("Default")
    .IsDependentOn("Package");

RunTarget(target);

 

在 Version Task 中,會生成一個 SolutionInfo.cs 的檔案,也就相當於前面的 AssemblyInfo.cs。那現在所有的專案都取用這個檔案來進行統一的版本管理就行了。

這樣就已經實現了統一版本、構建、打包的一件腳本化了。後續還可以添加上構建完之後執行單元測試以及打包後自動發佈到 nuget 的功能,但我自己比較習慣打包完之後本地也測試一下(畢竟 nuget 發了就不能刪),所以就暫時不折騰這功能了。

博主圖片快取控制元件專案的 build.cake 腳本可以參考這裡:https://github.com/h82258652/HN.Controls.ImageEx/blob/master/build.cake,雖然配置好了 xunit,但是沒有寫單元測試就是了,ε=ε=ε=┏(゜ロ゜;)┛

這篇博文主要記錄操作步驟,方便以後自己(我還有個微博的庫的坑想要填……)。但也希望看完這篇博文的各位,製作一個 nuget 包並不是一件難事,馬上行動把珍藏都弄一份 nuget 包,讓各位 .net 開發者也機會用上吧。

原文地址:https://www.cnblogs.com/h82258652/p/10625036.html

赞(0)

分享創造快樂