讓你釋出的nuget包支援原始碼除錯

czd890發表於2021-07-07

前情概要

在不久的從前(也還是要以年為單位哈), 我們如果需要除錯第三方程式碼, 或者框架程式碼很麻煩. 需要配置symbols, 匹配原始程式碼路徑等.
為此, MS推出了 Source Link 功能, 詳細的介紹請檢視官方repo 的 readme.

Copy+google翻譯過來的介紹:

Source Link 是一個與語言和原始碼控制無關的系統,用於為二進位制檔案提供一流的原始碼除錯體驗。該專案的目標是讓任何構建NuGet 庫的人都能夠毫不費力地為其使用者提供原始碼除錯。Microsoft 庫(例如 .NET Core 和 Roslyn)已啟用 Source Link。Microsoft 支援源連結。

Source Link 是一組包和規範,用於描述可以嵌入到符號、二進位制檔案和包中的原始碼控制後設資料。

Visual Studio 15.3+ 支援在除錯時從符號讀取源連結資訊。它為使用者下載並顯示適當的特定於提交的源,例如來自raw.githubusercontent,啟用斷點和對任意 NuGet 依賴項的所有其他源除錯體驗。Visual Studio 15.7+ 支援從需要身份驗證的私有 GitHub 和 Azure DevOps(以前的 VSTS)儲存庫下載原始檔。

在最初的來源連結的實現是通過提供@ctaggart。謝謝!.NET 團隊和 Cameron 共同努力使此實現在 .NET Foundation 中可用。

如果您是從原始 Source Link 文件到達這裡的 - 您不需要使用SourceLink.Create.CommandLine. 您只需要安裝下面列出的軟體包。

到目前為止, 主流的nuget package 都已經支援了. 例如MS官方的包, protobuf-net, Newtonsoft.Json 等.

首先, 先介紹如何原始碼除錯支援Sourcelink的包.

我們僅需要修改vs的配置.

  • 首先, 禁用 Just My Code 功能
  • 然後, 啟用 Source Server SupportSource Link Support

我們就可以 F11 進入原始碼了

就是這麼簡單, 就是這麼順滑.

然後, 本文的重點來了, 讓我們自己的nuget包也支援這麼棒的功能!!!

為我們的專案新增SourceLink支援

<Project>
	<PropertyGroup>
		<DebugType>embedded</DebugType>
		<DebugSymbols>true</DebugSymbols>
		<PublishRepositoryUrl>true</PublishRepositoryUrl>
	</PropertyGroup>

	<!--<PropertyGroup Condition="'$(GITLAB_CI)' == 'true'">-->
	<PropertyGroup Condition="'$(Configuration)' == 'Release'">
		<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
		<Deterministic>true</Deterministic>
		<EmbedUntrackedSources>true</EmbedUntrackedSources>
	</PropertyGroup>
	<ItemGroup>
		<PackageReference Include="Microsoft.SourceLink.GitLab" Version="1.0.0" PrivateAssets="All"/>
	</ItemGroup>
</Project>

這些程式碼可以新增的專案的.csproj檔案中, 也可以為整個solution的所有project新增.
為整個solution新增, 我們可以在.sln檔案的同級目錄下增加檔案 Directory.Build.props, 然後把上面程式碼copy進行就可以了.

接下來簡單解釋一下這些改動都是啥意思, 其實在Source Link解釋的非常清楚了. 強烈建議看官方文件.

  • DebugType 為啥用 embedded呢? 首先它的意思是把pdb的資訊直接打包到dll檔案中.
    • 它的好處
      • 一個.dll檔案就夠了, 不在要生成 .dll.pdb 2個檔案.
      • 在目前階段, 不同的框架(nfx, netcore 2.x, 3.x, 5.x),不同的vs(msbuild)版本下, 對pdb檔案的處理各不相同. 比如vs 16.10 和netcore 2.x 它在build或者release的時候就不copy nuget packages 裡面的pdb檔案. 當然這個問題官方也在解決,但是比較緩慢, 反正我知道這個問題就已經好幾年了, 到目前位置github上的issue還在討論來討論去...
    • 壞處
      • 比較明顯的增加的檔案的體積.
  • DebugSymbols 我想應該不用解釋
  • PublishRepositoryUrl 將原始碼的git資訊編譯到dll和打包到nuget package 上.
  • ContinuousIntegrationBuild 和 Deterministic 表示確定性編譯. 具體解釋請檢視Here
  • EmbedUntrackedSources 跟蹤build生成的程式碼檔案. 比如我有模板程式碼在build時生成, 或者由PublishRepositoryUrl生成的比如assemble attribute檔案等.
    沒有設定的時候

    設定好了的時候
  • 新增Microsoft.SourceLink.[your git repo]包, 比如我DEMO這個專案用的是gitlab, 那我新增的就是Microsoft.SourceLink.GitLab. 目前SouceLink支援 github, gitlab, azure, bitbucket, gitweb, gitea.
    • PrivateAssets設定為All的意思是:這個包只有在編譯除錯的時候使用, 打包到nuget的時候它不會新增進去.

驗證我們的dll或者pdb已經支援SourceLink了

首先我們先安裝sourcelink工具.

dotnet tool install -g sourcelink

接著測試一下我們的dll是否已經支援了

sourcelink print-json .\protobuf-net.Core.dll
sourcelink print-urls .\protobuf-net.Core.dll


當然也可以用

sourcelink test .\protobuf-net.Core.dll

到這裡就基本完成了, 把包釋出到nuget package上就可以, 可以是nuget.org, 也可以是myget, 更可以你公司內部的私有nuget package 伺服器.

如果你和我一樣, 用的是gitlab的私有git repo, 那可以繼續看下去.

為gitlab的私有原始碼專案提供支援.

如果是gitlab的私有git repo. 在sourcelink test的時候會收到類似下面的錯誤

https://gitlab.com/myproject/mysourcecode.cs
error: url failed ServiceUnavailable: Service Temporarily Unavailable
sourcelink test failed

這是因為gitlab目前為止不支援基本身份驗證, 另外對於如果你是github的私有repo不用擔心. 只需要把Enable Source Link Support的下面的Fall back to GCM 選項勾起就可以了(參考我們僅需要修改vs的配置小節的截圖).
具體的issue可以參考:
Add support for Git Credential Manager on Windows
Support private GitLab repositories
如果要解決這個問題 可以參考 https://github.com/rgl/gitlab-source-link-proxy 的解決方案.

如果只是臨時的除錯一下原始碼可以有更簡單粗暴的方法, 在vs中用Web Browesr 登入一下gitlab就完事了.

哈!, 就是這麼簡單粗暴.

相關文章