Producing Packages with Source Link
In our last post, we showed you how you can debug into the framework and dependencies that was produced with Source Link. In this post, we’ll show you how to add Source Link to your projects. This is beneficial both for public and internal projects.
How Source Link Works
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.
Using Source Link
Source Link is distributed as a set of NuGet packages, 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).
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:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net5.0</TargetFramework> <!-- Publish the repository URL in the built .nupkg (in the NuSpec <Repository> element) --> <PublishRepositoryUrl>true</PublishRepositoryUrl> <!-- Embed source files that are not tracked by the source control manager in the PDB --> <EmbedUntrackedSources>true</EmbedUntrackedSources> <!-- Recommended: Embed symbols containing Source Link in the main file (exe/dll) --> <DebugType>embedded</DebugType> </PropertyGroup> <ItemGroup> <!-- Add PackageReference specific for your source control provider (see below) --> </ItemGroup> </Project>
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,
ContinuousIntegrationBuild, to set on the build server to normalize stored file paths. These should not be enabled during local dev or the debugger won’t be able to find the local source files.
Therefore, you should use your CI system’s variable to set them conditionally. For Azure Pipelines, it looks like this
<PropertyGroup Condition="'$(TF_BUILD)' == 'true'"> <ContinuousIntegrationBuild>true</ContinuousIntegrationBuild> </PropertyGroup>
For GitHub Actions, the variable is
GITHUB_ACTIONS, so the result would be:
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'"> <ContinuousIntegrationBuild>true</ContinuousIntegrationBuild> </PropertyGroup>
Don’t Repeat Yourself
If you have a solution that has multiple projects in it, you can extract the common properties into a Directory.Build.props file at the solution directory. That way all projects have them added automatically.
If you distribute the library via a package published to NuGet.org, you should use embedded PDB’s so the debug information is always available with your library. Alternatively, you can build a symbol package and publish it to NuGet.org as well. This will make the symbols available on NuGet.org symbol server, where the debugger can download it when needed.
Source Control Providers
Source Link packages are currently available for the following source control providers.
Source Link package is a development dependency, which means it is only used during build. It is therefore recommended to set
allon the package reference. This prevents consuming projects of your NuGet package from attempting to install Source Link.
github.com and GitHub Enterprise
For projects hosted by GitHub or GitHub Enterprise reference Microsoft.SourceLink.GitHub like so:
<ItemGroup> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/> </ItemGroup>
Azure Repos (former Visual Studio Team Services)
For projects hosted by Azure Repos in git repositories reference Microsoft.SourceLink.AzureRepos.Git:
<ItemGroup> <PackageReference Include="Microsoft.SourceLink.AzureRepos.Git" Version="1.0.0" PrivateAssets="All"/> </ItemGroup>
Azure DevOps Server (former Team Foundation Server)
For projects hosted by on-prem Azure DevOps Server in git repositories referenceMicrosoft.SourceLink.AzureDevOpsServer.Git and add host configuration like so:
<ItemGroup> <PackageReference Include="Microsoft.SourceLink.AzureDevOpsServer.Git" Version="1.0.0" PrivateAssets="All"/> </ItemGroup>
If your server is configured with non-empty IIS Virtual Directory, specify this directory in
SourceLinkAzureDevOpsServerGitHost item like so:
<ItemGroup> <SourceLinkAzureDevOpsServerGitHost Include="server-name" VirtualDirectory="tfs"/> </ItemGroup>
Include attribute specifies the domain and optionally the port of the server (e.g.
For projects hosted by GitLab reference Microsoft.SourceLink.GitLab package:
<ItemGroup> <PackageReference Include="Microsoft.SourceLink.GitLab" Version="1.0.0" PrivateAssets="All"/> </ItemGroup>
For projects in git repositories hosted on Bitbucket.org or hosted on an on-prem Bitbucket server reference Microsoft.SourceLink.Bitbucket.Git package:
<ItemGroup> <PackageReference Include="Microsoft.SourceLink.Bitbucket.Git" Version="1.0.0" PrivateAssets="All"/> </ItemGroup>
If your project is hosted by Bitbucket Server or Bitbucket Data Center older than version 4.7 you must specify
SourceLinkBitbucketGitHost item group in addition to the package reference:
<ItemGroup> <SourceLinkBitbucketGitHost Include="bitbucket.yourdomain.com" Version="4.5"/> </ItemGroup>
The item group
SourceLinkBitbucketGitHost specifies the domain of the Bitbucket host and the version of Bitbucket.The version is important since URL format for accessing files changes with version 4.7. By default Source Link assumes new format (version 4.7+).
For projects hosted on-prem via gitweb reference Microsoft.SourceLink.GitWeb package:
<ItemGroup> <PackageReference Include="Microsoft.SourceLink.GitWeb" Version="1.1.0-beta-20204-02" PrivateAssets="All"/> </ItemGroup>
Source Link is easy to add to your projects and we highly recommend that all projects configure it by default.
When will you add at least basic source link support to C++ projects?
I mean it’s nice to see that someone is working on that essential feature at all, but it’s also blatant obvious that you folks don’t even try to maintain a common feature set between the different language frameworks.
I own several packages that have been using Source Link. The advice here seems a bit different to that found in https://github.com/dotnet/sourcelink. So here are a few questions:
is needed only if you are not building and publishing NuGet symbol packages. That way you ensure that pdb-s are distirbuted along with dlls.
Thank you. I already push .snupkg packages to the NuGet symbol server, so it’s worth calling out that this is not needed.
There is a good explanation of ContinuousIntegrationBuild in https://github.com/JamesNK/Newtonsoft.Json/pull/1746
Is it planned to include configurable source link “adapters” for internal Git repository servers? We have Bitbucket Server running, it would be nice to configure some kind of BaseUrl in the csproj and get the full support as well.
At the moment localy hosted instances are not supported. There is a bug-Ticket and they are working on it. But it’s an old Ticket and we are still hoping for a fix.
Thanks for the article, it’s very helpful!
Do you know, by any chance, if there is a plan for VisualStudio to support different authentication protocols (other than basic auth) for fetching the files?
It’s kind of a blocker for us to use Source Links with private GitLab repositories (hosted on gitlab.com, we can’t add proxy), since GitLab doesn’t support basic auth. Unfortunately, it seems it won’t implement that support any time soon, or at all.
Any info would be helpful, thanks!
Thanks for the article, it’s very helpful 🙂
تبلیغ در گوگل
Any chance for TFS-style source control, but still stored in Azure DevOps? I know it’s not in vogue, but it still works fine for us.
I asked the same question in the first post in this series, with a me-too from Gioacchino Piazzolla. There are at least three people in the world that would be interested in such a thing. I was really hoping we could get some comment from Microsoft here.
I have a solution (ApNetCore3.1) with 2 projects. My Azure DevOps builds were working fine until I integrated this post’s solution. Now I get this:
A lot of our older code is in the old / original csproj format, and SourceLink will only work with the new (SDK) project format, so the first job is to convert the projects.
Convert the csproj file. The new project format is very simple, so you can often just copy and paste an existing csproj file.
@Delete the files that are no longer required (packages.config, Properties\AssemblyInfo.cs)
@Add the SourceLink.Create.CommandLine and Microsoft.SourceLink.GitHub nuget packages.
@Update the version numbers of the nuget packages
Hasilkan Uang Dari Google News, Mudah Banget !.