建立與使用包含原始碼的 NuGet 符號套件

續上篇,這次要一併發布包含符號/原始碼的 NuGet 套件,並設定 Visual Studio 的除錯符號來源。

上一篇已經點出 NuGet 命令列工具的一些基本用法(如需完整的命令和參數,請參考官網文件),這次要說明如何發布包含符號與原始碼的 NuGet 套件,以及如何設定 Visual Studio 的符號來源。

文中提及的 YaLib 套件可從 NuGet.org 取得最新版本

為什麼要發布符號與原始碼?

有附原始碼的函式庫總是讓我比較放心一些。畢竟程式碼難免有一些臭蟲或不夠完善的地方,若真發生什麼狀況,有原始碼在手邊,至少我們還能透過單步追蹤來嘗試找出錯誤源頭,甚至加以修正。即便不為了除錯,閱讀別人的程式碼也是不錯的學習機會。

因此,當我們要公開發布自己寫的函式庫給別人使用時,也得設身處地:不提供原始碼,別人敢用我寫的東西嗎?

NuGet 在除錯方面的支援

開放原始碼的函式庫,我們可以下載完整的專案原始碼,然後加入自己的專案,方便隨時單步追蹤進入任何一個類別的程式碼。但如果原始碼數量龐大,這種做法其實挺累贅,因為那些常用的類別既然打包成方便重複使用的 DLL,可能只是某個地方偶爾出問題才需要除錯,平時大多不需要原始碼。

NuGet 除了能夠建立和發布 DLL 套件(library package),它也支援建立和發布包含符號與原始碼的套件(symbol/source package)。如此一來,在使用別人開發的函式庫時,引用的會是單純的 DLL(不包含 .pdb 和原始碼),而如果需要單步追蹤其原始碼,只要我們預先提供足夠的資訊給 Visual Studio(後面會說明如何設定),將來在除錯時只要按 F11(Step Into)就能往底層程式碼繼續追進去。這對類別庫的開發者和使用者來說都是好事。

話又多了,以下是打包和發布符號套件的步驟。

Step 1: 註冊 SymbolSource.org 帳號

我們需要藉助 SymbolSource.org 伺服器來讓 Visual Studio 取得套件的除錯資訊和原始碼,因此必須先到 SymbolSource.org 註冊一個帳號,並將該帳號跟你的 NuGet.org 帳號綁在一起。(本文不會說明如何建立自己專屬的符號來源伺服器

綁定的操作步驟如下圖:



Step 2:打包與發佈套件

在發布套件之前,保險起見還是先執行一下 SetApiKey。這個 NuGet 命令已在上一篇提過 ,就不解釋,只抓個圖,看一下命令的執行結果:


注意裡面的符號伺服器網址是 *.symbolsource.org/*。

底下是用來打包用的 .nuspec 檔案內容,檔名是 Yalib.symbols.nuspec。

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
  <metadata>
    <id>Yalib</id>
    <version>0.0.0</version>
    <title>Yet Another Library for .NET</title>
    <authors>Huanlin Tsai</authors>
    <owners>Huanlin Tsai</owners>
    <projectUrl>https://github.com/huanlin/YetAnotherLibrary</projectUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Some common utilities for .NET development.</description>
    <copyright>Copyright© 2014</copyright>
    <dependencies>    
    </dependencies>
  </metadata>
  <files>
    <file src="Debug\Yalib*.dll" target="lib\net40" />
    <file src="Debug\Yalib*.pdb" target="lib\net40" />
    <file src="..\Source\**\*.cs" target="src" />
  </files>
</package>

要特別注意的是 <files> 區段裡面的最後一行,它指定了要加入那些原始碼檔案,以及要打包至套件的目標資料夾。在 NuGet 套件中,原始碼檔案必須放在一個叫做「src」的資料夾。

接著使用以下命令來建立 .nupkg 檔案,也就是俗稱的打包:

NuGet.exe Pack Yalib.symbols.nuspec -OutputDirectory nupkg -Symbols -Version %1

其中 -Symbols 參數指定要同時建立包含符號的套件,-Version 指定套件的版本號碼,並由命令列參數 %1 傳入,假設是 1.0.6。於是,此命令會在 nupkg 子目錄下產生兩個檔案:Yalib.1.0.6.nupkg 和 Yalib.1.0.6.symbols.nupkg。我們可以用 NuGet Package Explorer 查看兩個套件的內容,比較其差異。參考下面兩張圖。

圖 (a):Yalib.1.0.6.nupkg (library package)

圖 (b):Yalib.1.0.6.symbol.nupkg (symbol package)
你可以從圖 (a) 發現 library package 裡面並沒有包含 .pdb 檔案,圖 (b) 的 symbol package 才有包含 .pdb + 原始碼(在 src\ 底下)。這是好事。如果你將 .pdb 檔案包在 library package 裡面,Visual Studio 反而會找不到原始碼,因為在載入符號資訊時,Visual Studio 總是會先在 .dll 檔案所在目錄下尋找同名的 .pdb 檔案,如果有找到,就不會去使用符號來源的設定了(稍後會說明如何設定符號來源)。

打包完成,接著將套件推送至 NuGet.org 伺服器:

NuGet.exe Push Yalib.1.0.6.nupkg

NuGet 在執行 Push 命令時,會自動檢查是否同時存在 Yalib.1.0.6.symbols.nupkg;若存在,就會一併推送。執行結果如下圖:

註:這圖是更早之前抓的,所以版本號碼與文字敘述不符。

OK,這樣就能讓別人透過 NuGet 搜尋並下載你發布的套件了。

設定 Visual Studio 以便在單步除錯時夠追進套件的原始碼

儘管一併發布了包含除錯符號與原始碼的套件,實際在專案中透過 NuGet 引用該套件時,使用的仍是未包含除錯符號的版本。也就是說,在 Visual Studio 中進行單步除錯時,按 F11 並沒有辦法讓我們追進外來套件的原始碼。

這問題很好解決,只要先確定專案所引用的 NuGet 套件有一併發布符號套件,剩下的工作就只是修改 Visual Studio 設定而已。

首先,從 Visual Studio 主選單點 TOOLS \ Options。在 Options 對話窗中,於左邊面板點 Debugging \ General,然後照下圖紅色框的部分來設定:


接著設定 Debugging \ Symbols:


圖中標示編號 3 的那串文字是 SymbolSource 主機的網址。這裡我只加入一個符號來源:http://srv.symbolsource.org/pdb/Public。你可以根據自己的需要添加其他符號來源,例如 SymbolSource.com 網站有一篇說明如何設定 Visual Studio 的文章就列出了好幾個網址(在「Configuring Visual Studio」小節裡)。
Tip: 如果你覺得設定符號來源伺服器之後,每次除錯專案時,Visual Studio 花太多時間在載入除錯資訊,可以把上面那張截圖中的底部的選項從 "All modules..." 改成 "Only specified modules",並且指定你想要載入的符號模組。

設定完成後,可以新建一個 Console Application 專案來測試看看能否順利單步追蹤進入套件的原始碼。

其他相關應用,像是如何為團隊建立自己專屬的 NuGet 伺服器和符號來源伺服器,可參考 Xian's 學習筆記的系列文章:

參考資料

Post Comments

技術提供:Blogger.