by Eric Seng, on Nov 8, 2021 6:01:56 PM
Demystifying Symbols & Source Serving
While munging project files is great for writing & editing library code, symbols and source serving is more appropriate for debugging into library code. It can be difficult to wrap your head around all the various articles and documentation regarding symbols and source serving. The following sections aim to explain how everything fits together as clearly as possible.
What are Symbols?
Also known as PDB files, they essentially map compiled code (.dll and .exe files) to original source code files (.cs files). This is what visual studio uses behind the scenes for integrated debugging.
There are two types of symbol files: Microsoft PDB & Portable PDP.
- Microsoft PDB: These are an older format, and can optionally have instructions that point Visual Studio to download the mapped .cs files from a specialized Source Server. ProGet can act as a Source Server, and uses the .cs files you embed in the NuGet package to return the source code to visual studio.
- Portable PDB: These are a newer format, and work cross-platform (unlike Microsoft PDB). However, they do not support Source Server. Instead, you'll need to use SourceLink to embed source files URLs in the NuGet package during compiling.
What are Symbol packages?
A symbol package is really just a NuGet package that contains symbol files. They can sometimes have different file extensions, like .symbols.nupkg or .snupkg.
Legacy Format (.symbols.nupkg)
.symbols.nupkg packages are considered to be legacy symbol packages, and can be created using the pack command on the nuget.exe client:
nuget.exe pack MyPackage.nuspec -Symbols
nuget.exe pack MyProject.csproj -Symbols
When created in this manner, a .symbols.nupkg file is motly the same as the .nupukg file, but it includes .pdb files alongside the .dll files.
New Format (.snupkg)
.snupkg packages are the "new" format, and can be created using by specifying the SymbolPackageFormat on either the nuget.exe CLI or the dotnet CLI.
nuget pack MyPackage.nuspec -Symbols -SymbolPackageFormat snupkg
nuget pack MyPackage.csproj -Symbols -SymbolPackageFormat snupkg
dotnet pack MyPackage.csproj -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
When created in this manner, a .snupkg file will be just like the .nupukg file, but there will be .pdb files instead of the .dll files and the .nuspec manifest file will be slightly different.
Embedded Format (.nupkg)
Embedded Symbols packages are the most straightforward and recommended approach, especially with ProGet. They include the PDB and DLL inside a single NuGet Package instead of needing to use separate packages.
This involves setting the DebugType property on your project file to embedded.
By using the Embedded Format, this is the only change you need to make: you can simply push the package to ProGet, and you will be able to use ProGet's symbol server.
What is a Source Server?
A source server enables a client to retrieve the exact version of the source files that were used to build an application.
The source code for a module can change between versions and over times, so it's important to look at the source code as it existed when the version of the module in question was built. Source server retrieves the appropriate files from source control.
To use source server, the application must have been source indexed. A NuGet feed in ProGet may be configured as a Symbol/Source server compatible with debuggers such as Visual Studio and WinDbg. The following is supported by the ProGet symbol server:
- Microsoft PDB format (C/C++, .NET)
- Source server
- Portable PDB format (.NET)
ProGet will index and serve portable PDB files as well as the traditional Microsoft PDB files, but portable PDB files need to use a build tool like Sourcelink.
What is SourceLink?
Sourcelink was created to enable anyone building NuGet libraries to provide source debugging for their users with little effort. Instead of embedding information in the PDB, it uses the package’s repository metadata element to locate code files in your web-based Git repository.
Using ProGet as a Symbol & Source Server
You can use a NuGet feed that you've already created in ProGet to server Symbols and source files.
Configuring your NuGet Feed ProGet
In order for ProGet to serve symbols for a particular NuGet feed, it must be configured to do so. From the ProGet home screen navigate to Feeds>Feed Name>Manage Feed Name>Symbol Server>Configure.
Ensure that the options under Symbol Server are correctly checked, while noting the URL of the feed's symbol server to be used within Visual Studio.
Configuring Visual Studio to work with ProGet
Enable Symbol Server Support
In order to debug into NuGet package libraries, Visual Studio must be configured to use ProGet as a symbol server.
To do this select Debug > Options, from the menu bar, then browse to Debugging > Symbols in the tree menu. Add the symbol server URL found on the Manage Feed page earlier, and specify a Symbol Cache Directory. By default Visual Studio will use %LOCALAPPDATA%\Temp\SymbolCache, but you may specify any path.
Enable Source Server Support
To configure source server support, browse to Debugging > General in the debugging options tree menu, and make sure the following settings are checked/unchecked as follows:
☐ Enable Just My Code
☑ Enable source server support
Additionally, you may have to uncheck:
☐ Enable .NET Framework Source Stepping
The settings should look like the following:
If you want to use embedded symbol packages but prevent symbol files from being downloaded with your package, you can update the settings in ProGet. From the manage feed page, navigate to Symbol Server settings and select the “strip symbol files" option.
Debug NuGet Packages With ProGet
Debugging NuGet packages is anything but intuitive. Using the solutions outlined in this article will allow your developers to more easily integrate debugging with NuGet.
We recommend munging project files, but using embedded symbol packages is fine as well, especially if your debugging into library code. ProGet supports these solutions so your developers can debug NuGet packages as painless as possible.
Debugging is important, but there’s a lot more to learn about NuGet packages to successfully use them on the Enterprise level. Sign up for our mailing list to receive our upcoming guide that will guide you through everything NuGet!