{"id":31145,"date":"2020-12-09T09:05:44","date_gmt":"2020-12-09T16:05:44","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=31145"},"modified":"2020-12-09T10:04:33","modified_gmt":"2020-12-09T17:04:33","slug":"producing-packages-with-source-link","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/producing-packages-with-source-link\/","title":{"rendered":"Producing Packages with Source Link"},"content":{"rendered":"<p>In our last post, we showed you <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/improving-debug-time-productivity-with-source-link\/\">how you can debug into the framework and dependencies<\/a> that was produced with Source Link. In this post, we&#8217;ll show you how to add Source Link to your projects. This is beneficial both for public and internal projects.<\/p>\n<h2>How Source Link Works<\/h2>\n<p>At its most basic, Source Link generates a JSON file that maps raw source code locations to the source files in the build. This is most commonly an HTTPS URL to a file on GitHub, GitLab, Azure Repos, or Bitbucket. The JSON file gets embedded in the debug symbols, which the debugger uses to download the file on-demand. For non-public repos, this does not automatically grant anyone access to the source; the debugger would need to authenticate so existing permissions are maintained.<\/p>\n<h2>Using Source Link<\/h2>\n<p>Source Link is distributed as <a href=\"https:\/\/www.nuget.org\/packages?q=Microsoft.SourceLink\">a set of NuGet packages<\/a>, one per repository host. It is intended to be used as a private reference (it is used during the build, it does not require runtime consumers to have a dependency on it).<\/p>\n<p>You can enable Source Link experience in your own .NET project by setting a few properties and adding a PackageReference to a Source Link package:<\/p>\n<pre><code class=\"xml\">&lt;Project Sdk=\"Microsoft.NET.Sdk\"&gt;\r\n &lt;PropertyGroup&gt;\r\n    &lt;TargetFramework&gt;net5.0&lt;\/TargetFramework&gt;\r\n\r\n    &lt;!-- Publish the repository URL in the built .nupkg (in the NuSpec &lt;Repository&gt; element) --&gt;\r\n    &lt;PublishRepositoryUrl&gt;true&lt;\/PublishRepositoryUrl&gt;\r\n\r\n    &lt;!-- Embed source files that are not tracked by the source control manager in the PDB --&gt;\r\n    &lt;EmbedUntrackedSources&gt;true&lt;\/EmbedUntrackedSources&gt;\r\n\r\n    &lt;!-- Recommended: Embed symbols containing Source Link in the main file (exe\/dll) --&gt;\r\n    &lt;DebugType&gt;embedded&lt;\/DebugType&gt;\r\n  &lt;\/PropertyGroup&gt;\r\n  &lt;ItemGroup&gt;\r\n    &lt;!-- Add PackageReference specific for your source control provider (see below) --&gt;\r\n  &lt;\/ItemGroup&gt;\r\n&lt;\/Project&gt;\r\n<\/code><\/pre>\n<h3>Deterministic Builds<\/h3>\n<p>Deterministic builds ensure that the same binary is produced regardless of the machine building it, including paths to sources stored in the symbols. While deterministic builds are enabled by default in .NET SDK projects, there is an extra property, <code>ContinuousIntegrationBuild<\/code>, to set on the build server to normalize stored file paths. These should not be enabled during local dev or the debugger won&#8217;t be able to find the local source files.<\/p>\n<p>Therefore, you should use your CI system&#8217;s variable to set them conditionally. For Azure Pipelines, it looks like this<\/p>\n<pre><code class=\"xml\">&lt;PropertyGroup Condition=\"'$(TF_BUILD)' == 'true'\"&gt;\r\n  &lt;ContinuousIntegrationBuild&gt;true&lt;\/ContinuousIntegrationBuild&gt;\r\n&lt;\/PropertyGroup&gt;\r\n<\/code><\/pre>\n<p>For GitHub Actions, the variable is <code>GITHUB_ACTIONS<\/code>, so the result would be:<\/p>\n<pre><code class=\"xml\">&lt;PropertyGroup Condition=\"'$(GITHUB_ACTIONS)' == 'true'\"&gt;\r\n  &lt;ContinuousIntegrationBuild&gt;true&lt;\/ContinuousIntegrationBuild&gt;\r\n&lt;\/PropertyGroup&gt;\r\n<\/code><\/pre>\n<h3>Don&#8217;t Repeat Yourself<\/h3>\n<p>If you have a solution that has multiple projects in it, you can extract the common properties into a <a href=\"https:\/\/docs.microsoft.com\/visualstudio\/msbuild\/customize-your-build#directorybuildprops-and-directorybuildtargets\">Directory.Build.props<\/a> file at the solution directory. That way all projects have them added automatically.<\/p>\n<p>If you distribute the library via a package published to <a href=\"https:\/\/nuget.org\">NuGet.org<\/a>, you should use embedded PDB&#8217;s so the debug information is always available with your library. Alternatively, you can build a <a href=\"https:\/\/docs.microsoft.com\/nuget\/create-packages\/symbol-packages-snupkg\">symbol package<\/a> and publish it to <a href=\"https:\/\/nuget.org\">NuGet.org<\/a> as well. This will make the symbols available on <a href=\"https:\/\/docs.microsoft.com\/nuget\/create-packages\/symbol-packages-snupkg#nugetorg-symbol-server\">NuGet.org symbol server<\/a>, where the debugger can download it when needed.<\/p>\n<h2>Source Control Providers<\/h2>\n<p>Source Link packages are currently available for the following source control providers.<\/p>\n<blockquote><p>Source Link package is a development dependency, which means it is only used during build. It is therefore recommended to set <code>PrivateAssets<\/code> to <code>all<\/code> on the package reference. This prevents consuming projects of your NuGet package from attempting to install Source Link.<\/p><\/blockquote>\n<h3>github.com and GitHub Enterprise<\/h3>\n<p>For projects hosted by <a href=\"https:\/\/github.com\">GitHub<\/a> or <a href=\"https:\/\/enterprise.github.com\/home\">GitHub Enterprise<\/a> reference <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.SourceLink.GitHub\">Microsoft.SourceLink.GitHub<\/a> like so:<\/p>\n<pre><code class=\"xml\">&lt;ItemGroup&gt;\r\n  &lt;PackageReference Include=\"Microsoft.SourceLink.GitHub\" Version=\"1.0.0\" PrivateAssets=\"All\"\/&gt;\r\n&lt;\/ItemGroup&gt;\r\n<\/code><\/pre>\n<h3>Azure Repos (former Visual Studio Team Services)<\/h3>\n<p>For projects hosted by <a href=\"https:\/\/azure.microsoft.com\/services\/devops\/repos\">Azure Repos<\/a> in git repositories reference <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.SourceLink.AzureRepos.Git\">Microsoft.SourceLink.AzureRepos.Git<\/a>:<\/p>\n<pre><code class=\"xml\">&lt;ItemGroup&gt;\r\n  &lt;PackageReference Include=\"Microsoft.SourceLink.AzureRepos.Git\" Version=\"1.0.0\" PrivateAssets=\"All\"\/&gt;\r\n&lt;\/ItemGroup&gt;\r\n<\/code><\/pre>\n<h3>Azure DevOps Server (former Team Foundation Server)<\/h3>\n<p>For projects hosted by on-prem <a href=\"https:\/\/azure.microsoft.com\/services\/devops\/server\/\">Azure DevOps Server<\/a> in git repositories reference\n<a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.SourceLink.AzureDevOpsServer.Git\">Microsoft.SourceLink.AzureDevOpsServer.Git<\/a> and add host configuration like so:<\/p>\n<pre><code class=\"xml\">&lt;ItemGroup&gt;\r\n  &lt;PackageReference Include=\"Microsoft.SourceLink.AzureDevOpsServer.Git\" Version=\"1.0.0\" PrivateAssets=\"All\"\/&gt;\r\n&lt;\/ItemGroup&gt;\r\n<\/code><\/pre>\n<p>If your server is configured with non-empty IIS <a href=\"https:\/\/github.com\/dotnet\/sourcelink\/blob\/master\/docs\/TfsVirtualDirectory\/README.md\">Virtual Directory<\/a>, specify this directory in <code>SourceLinkAzureDevOpsServerGitHost<\/code> item like so:<\/p>\n<pre><code class=\"xml\">&lt;ItemGroup&gt;\r\n  &lt;SourceLinkAzureDevOpsServerGitHost Include=\"server-name\" VirtualDirectory=\"tfs\"\/&gt;\r\n&lt;\/ItemGroup&gt;\r\n<\/code><\/pre>\n<p>The <code>Include<\/code> attribute specifies the domain and optionally the port of the server (e.g. <code>server-name<\/code> or <code>server-name:8080<\/code>).<\/p>\n<h3>GitLab<\/h3>\n<p>For projects hosted by <a href=\"https:\/\/gitlab.com\">GitLab<\/a> reference <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.SourceLink.GitLab\">Microsoft.SourceLink.GitLab<\/a> package:<\/p>\n<pre><code class=\"xml\">&lt;ItemGroup&gt;\r\n  &lt;PackageReference Include=\"Microsoft.SourceLink.GitLab\" Version=\"1.0.0\" PrivateAssets=\"All\"\/&gt;\r\n&lt;\/ItemGroup&gt;\r\n<\/code><\/pre>\n<h3>Bitbucket<\/h3>\n<p>For projects in git repositories hosted on <a href=\"https:\/\/bitbucket.org\">Bitbucket.org<\/a> or hosted on an on-prem Bitbucket server reference <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.SourceLink.Bitbucket.Git\">Microsoft.SourceLink.Bitbucket.Git<\/a> package:<\/p>\n<pre><code class=\"xml\">&lt;ItemGroup&gt;\r\n  &lt;PackageReference Include=\"Microsoft.SourceLink.Bitbucket.Git\" Version=\"1.0.0\" PrivateAssets=\"All\"\/&gt;\r\n&lt;\/ItemGroup&gt;\r\n<\/code><\/pre>\n<p>If your project is hosted by Bitbucket Server or Bitbucket Data Center older than version 4.7 you must specify <code>SourceLinkBitbucketGitHost<\/code> item group in addition to the package reference:<\/p>\n<pre><code class=\"xml\">&lt;ItemGroup&gt;\r\n  &lt;SourceLinkBitbucketGitHost Include=\"bitbucket.yourdomain.com\" Version=\"4.5\"\/&gt;\r\n&lt;\/ItemGroup&gt;\r\n<\/code><\/pre>\n<p>The item group <code>SourceLinkBitbucketGitHost<\/code> specifies the domain of the Bitbucket host and the version of Bitbucket.\nThe version is important since URL format for accessing files changes with version 4.7. By default Source Link assumes new format (version 4.7+).<\/p>\n<h3>gitweb (pre-release)<\/h3>\n<p>For projects hosted on-prem via <a href=\"https:\/\/git-scm.com\/docs\/gitweb\">gitweb<\/a> reference <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.SourceLink.GitWeb\">Microsoft.SourceLink.GitWeb<\/a> package:<\/p>\n<pre><code class=\"xml\">&lt;ItemGroup&gt;\r\n  &lt;PackageReference Include=\"Microsoft.SourceLink.GitWeb\" Version=\"1.1.0-beta-20204-02\" PrivateAssets=\"All\"\/&gt;\r\n&lt;\/ItemGroup&gt;\r\n<\/code><\/pre>\n<h2>Summary<\/h2>\n<p>Source Link is easy to add to your projects and we highly recommend that all projects configure it by default.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to add Source Link to your packages, to make your users more productive while debugging.<\/p>\n","protected":false},"author":42867,"featured_media":31148,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685,196,7196],"tags":[4,9,322,7202],"class_list":["post-31145","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-dotnet-core","category-debugging","tag-net","tag-net-core","tag-debugging","tag-source-link"],"acf":[],"blog_post_summary":"<p>Learn how to add Source Link to your packages, to make your users more productive while debugging.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/31145","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/42867"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=31145"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/31145\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/31148"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=31145"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=31145"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=31145"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}