3
votes

Having private repositories on VSTS (Azure DevOps) I tried enabling SourceLink by adding the following to the .csproj file: https://github.com/dotnet/sourcelink#azure-devops-visual-studio-team-services

This does not seem to have any effect during debugging. There is an exception thrown in a local NuGet package and I can not navigate to it using the Call Stack windows since the pdb is not even loaded for that project.

I have "Enable Just My Code" disabled and SourceLink enabled inside Visual Studio.

What other changes do I need to make to enable SourceLink?

2
the new csproj format doesn't copy PDBs from the nuget package to output dir, do this on your ownmagicandre1981
@magicandre1981https://github.com/dotnet/sourcelink#using-sourcelink seems to imply that there is a way to specify PDB generationRăzvan Flavius Panda
you miss the point. I talk about consuming nuget packages. Here the new SDK has a bug where it doesn't copy the PDB to output, so no PDB + sourcelink info a present.magicandre1981

2 Answers

8
votes

Most of the tutorials on how to set up SourceLink seem to omit two key things.

Firstly:

  • As well as unchecking "Enable Just My Code" (non-default) and making sure "Enable Source Link support" is checked (default) under Options/Debugging/General,
  • If you want to work with SourceLink for public packages (say Newtonsoft.Json) you also have to check the listed symbol servers in VS Options/Debugging/Symbols.

Secondly:

  • If you want to publish symbols for your own package onto a public feed (e.g. nuget.org) then AFAIK the .snupkg format works fine
  • On a private NuGet feed (whether using a local file system NuGet feed, or the IIS NuGet.Server package) there is no symbol server, .snupkg is not supported, and this (which is widely listed as what to do instead) does not work (it includes the .pdb file in the NuGet package, but from my tests the consuming VS never uses them):
  <PropertyGroup>
    <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
  </PropertyGroup>
  • Using this instead, in the same place, does work (the pdb is embedded inside the dll itself, and the consuming VS sees it just fine):
  <PropertyGroup>
    <DebugType>Embedded</DebugType>
  </PropertyGroup>

You should definitely check out the VS Modules window found under Debug/Windows/Modules (shortcut CTRL+ALT+U) (only available while code is running), which shows which modules have loaded symbols and helps you figure out which haven't, and why not, if they haven't.

EDIT

It turns out that:

  <PropertyGroup>
    <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
  </PropertyGroup>

is working. It produces a NuGet file which is fine, or should be... but there is currently a bug in .NET SDK which causes it not to load .pdb files stored in NuGet files in this way, although it should.

There is another fix. In the consuming project, include:

    <PackageReference Include="SourceLink.Copy.PdbFiles" Version="2.8.3" PrivateAssets="All" />

after adding that, everything should work again as per the demos.

Alternatively, the fix which that package applies is:

<Project>
  <Target Name="_ResolveCopyLocalNuGetPackagePdbs" AfterTargets="ResolveReferences"
      Condition="$(CopyLocalLockFileAssemblies) == true">
    <ItemGroup>
      <ReferenceCopyLocalPaths Include="@(ReferenceCopyLocalPaths->'%(RootDir)%(Directory)%(Filename).pdb')" 
          Condition="'%(ReferenceCopyLocalPaths.NuGetPackageId)' != '' and Exists('%(RootDir)%(Directory)%(Filename).pdb')" />
    </ItemGroup>
  </Target>
</Project>

and (from here):

A good place to put it is in Directory.Build.targets so that your project files are not cluttered and so that you can apply it to multiple projects in a solution. https://docs.microsoft.com/en-us/visualstudio/msbuild/customize-your-build

1
votes

This may not be a direct answer, but it is well worth noting that you don't need SourceLink to get source level debugging. SourceLink is a clever way to put links in the PDB to source code in the cloud, in a git repo.

Another way to get portable source level debugging is to embed the source code directly in the PDB (EmbedAllSources=True), then embed the PDB in the DLL (DebugType=embedded). It's fairly efficient (20-30% larger .nupkg file) and doesn't suffer from the bug currently affecting separate PDBs.

Just add this to your project file:

  <PropertyGroup>
    <EmbedAllSources>True</EmbedAllSources>
    <DebugType>embedded</DebugType>
  </PropertyGroup>

and lo and behold you will be able to single step into the NuGet file generated from it. No other workarounds and no SourceLink packages are required.