Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NuGet Docs: Revise Source Link documentation with modern guidance #13597

Open
Mikejo5000 opened this issue Jun 28, 2024 · 0 comments
Open

NuGet Docs: Revise Source Link documentation with modern guidance #13597

Mikejo5000 opened this issue Jun 28, 2024 · 0 comments

Comments

@Mikejo5000
Copy link

Mikejo5000 commented Jun 28, 2024

NuGet Product Used

Other/NA

Product Version

N/A

Worked before?

No response

Impact

None

Repro Steps & Context

Ported from NuGet Docs, where we are closing issues.
Opener: JonDouglas

Revise the https://docs.microsoft.com/en-us/nuget/create-packages/symbol-packages-snupkg

Most current blog might be

https://devblogs.microsoft.com/dotnet/producing-packages-with-source-link/
https://docs.microsoft.com/en-us/dotnet/standard/library-guidance/sourcelink
https://aaronstannard.com/visual-studio-sourcelink-setup/

COMMENTS
from @PureKrome
The topic of this issue is about refreshing the Docs on Source Link. Awesome! 🚀

This thread was created by @JonDouglas after this twitter thread convo.

I still have a few questions which I think can be viewed as "The current documentation is a bit confusing or not worded clearly enough .. so lets see if we can clear things up".

Firstly: the current docs are pretty awesome with respect to getting a simple OSS package up to Nuget.org and where the code resides on GitHub. This is like the common OSS happy path.

Most of my questions (where I think the docs are a bit hazy/missing info) is about:

Private packages (think: working at a company)
Not Nuget.org as the package repository because we've got private code. (In our example, it's MyGet.org)
Happy path includes GitHub as the code repo ... but SL already supports 99% of the other major players, so i think this part is solved and doesn't need further docs/clarification.

Questions:
Q1. There are .nupkgs and .snupkgs. What's the relationship between these? Do we need -both- of these?
The docs suggest that we create symbol packages seperate from our nuget packages (our main reusable library "code").

The idea of symbol packages is they're hosted on a symbol server and are only downloaded by a tool like Visual Studio on demand.

So from my understanding, this is what I thought the docs are saying (simplified version):

Create come code. dotnet build it. when ready, dotnet pack it. We now have your dll packaged inside a nice zip folder 📦 ready for easy re-use. Throw this package up to a special place called a NuGet server so people can find/use it really easy. ⭐
Create some symbols (`.pdb's) of your library as a separate package. Again, stick it in a 📦 and throw that up somewhere else to a special location called a Symbol Server.
What's important about both of those two different steps is this:

main dll library/package only contains the code. Nothing else. If you get stuck and want to debug into the code, bad luck.
the symbol package contains all this extra magic to help you debug/step into the code -IF- you need to. Most people don't do this (e.g. all of the MS libraries).
Most people don't want to step into the other people's code. Like all the MS libraries we're leveraging/using in our .NET apps. As such (for performance reasons) those symbol/pdb's are NOT provided by default and if you want to, you manually request those files from a symbol server on a ad-hoc basis. Great! Separation of concerns.

But now the guidance is to have the pdb's embedded into the main dll ... so this means we don't need separate snupkg's?

This is all starting to get confusing 😕

Q2. What's the relationship with Source Link and .snupkgs
If the pdb's are inside an snupkg then the Source Link info is also inside the pdb's (which are in the snupkg's?) Source Link is (To quote @clairernovotny)

that maps raw source code locations to the source files in the build.

So we can connect readable code to the compiled code .. making it super easy to step-into-debug stuff.

So regardless how we store/handle pdb's (separate package? embedded into the dll?), Source Link will work. It just needs those pdb's.

Q3. Symbol Servers.
If we do use the guidance of putting our pdb's into a separate package (called an .snupkg) and send those symbols up to a symbol server, then these symbol servers need to do other special stuff? From this tweet:

image

Does this mean even though we use other NuGet providers that are not nuget.org (e.g. MyGet.org, etc) then those 3rd parties also need to do something magical ✨ to enable Source Link to work nicely with pdb's/symbols?

I hope my questions haven't confused people because I feel very confused. damn me!

Acceptance Criteria
For the MSDN docs to be 'updated', I would consider the following scenario all passing:

Create a nuget package
Symbols are generated and 'live' somewhere
Nuget is published to MyGet.org (or equivalent, not-nuget.org server)
Symbols are also published somewhere (or embedded, so nothing to publish)
I can create a new dotnet new blah, reference the nuget and then step through it.

COMMENTS
from @clairernovotny
Most people don't want to step into the other people's code. Like all the MS libraries we're leveraging/using in our .NET apps. As such (for performance reasons) those symbol/pdb's are NOT provided by default and if you want to, you manually request those files from a symbol server on a ad-hoc basis. Great! Separation of concerns.

Performance has nothing to do with this. There is no perf impact to having symbols in the execution of the app. The potential issues are that the nupkg is slightly larger, which may cause slower restore times for those on slower links. That said, portable pdb's and embedded pdb's are significantly smaller than the old Windows PDB's and aren't as much of an issue.

Symbols are required for reproducible builds and for debugging associated code. It is almost always easier to step into the third party code, if required, than to not have the symbols. For most OSS libraries, which is the majority of the ecosystem, at the very least it enables better bug reports and better call stacks (line numbers, etc).

Does this mean even though we use other NuGet providers that are not nuget.org (e.g. MyGet.org, etc) then those 3rd parties also need to do something magical ✨ to enable Source Link to work nicely with pdb's/symbols?

This is for the reproducible build logic as it needs to locate the symbols for the binaries. It has nothing to do with Source Link itself. I.e., you can use source link long as you get the PDB (and you can configure VS to get the symbols from the MyGet symbol server feeds you need already).

COMMENTS
from @PureKrome
Thanks so much @clairernovotny for jumping in here 🍰

That said, portable pdb's and embedded pdb's

Hmm - I just want to make sure we all understand the terminology better (maybe something we can update the MSDN docs with?) Can you confirm/clarify

Embedded pdb's: these are the symbols/debug-magic, which is INSIDE the dll? Or are these still a separate .pdb file that is packaged into the .nupkg file? so if I inspect the .nupkg, I will see the dll and the pdb, side by side (just like when I dotnet build and see these two files side-by-side in the output folder.
Portable pdb's: is this what an .snupkg is? where the pdb is packaged into a separate packaged file.
If i'm guessing the above is correct, then why do we have the option (suggestion?) to split the pdb into a separate .snupkg?

The potential issues are that the nupkg is slightly larger, which may cause slower restore times for those on slower links.

Is that the reason for choosing Embedded (in the .nupkg) vs Portable (in a separate .snupkg) - restore speed?

Which means we have 2 options:

Embedded: Slightly slower restore BUT you can debug-step-into 💯
Portable: Small nupkg size BUT the symbols are elsewhere and it's a real pain to access them if it's not-nuget.org
then wouldn't the guidance be something like this: To keep life easy for you developers...

If on NuGet.org -> make .snupkg's. (go portable)
If not on NuGet.org, embed and don't make snupkg's. It's too hard (go embedded)
Always add Source Link.
?

COMMENTS
from xtOrted
I'm sure @PureKrome is working up to this question, but the use of .snupkg packages is also important when using GitHub Packages since they don't support them and have a firm stance of not supporting them. I've typically bundled PDBs in my .nupkgs so tools like Application Insights, Raygun, and Sentry have more detailed stack traces but now that I'm using Source Link and GitHub Packages I'm not really sure what the right setup is.

COMMENTS
from @poke
As mentioned on Twitter, in the past, I repeatedly have seen guidance to use either symbol packages or embedded PDBs without any actual arguments to back these recommendations.

For that reason, I would like to see actual explanations on a revised documentation page that compares the two options and actually explains the differences and individual benefits. While there may be good reasons to favor one over the other, I think we should allow people to make up their own mind and enable them to make educated decisions on their own.

Claire already started with some reasons but I think we can find more. This would be what I would start with:

Embedded PDBs

Symbols packaged within single nupkg
Larger package size due to included symbols
Works with all NuGet feeds (local folders, GitHub packages, AzDO artifacts)
Generally a very simple model because everything is just bundled into a single package during a single process
Symbol packages

Symbols are packaged inside a separate symbol package (usually snupkg)
Original nupkg smaller due to left out symbols
Symbols and debuggability are opt-in
Kind of a pay-what-you-need model in terms of package contents
Does not work with feeds that do not support symbol packages, or requires separate symbol server
Need to be published separately, resulting in a slightly more complicated publishing process
May need additional configuration by the end user in order for them to use them for debugging

COMMENTS
from @clairernovotny
When I say embedded vs portable, I am referring to the type of PDB, not about whether they're in a snupkg or nupkg.

There are two PDB formats:

Windows PDB
Portable PDB
Windows PDB's are only supported on Windows. Portable PDB's are supported cross platform. There's more information here: https://github.com/dotnet/core/blob/main/Documentation/diagnostics/portable_pdb.md. Note that at this time, Portable PDB's are supported virtually everywhere. Portable PDB's are the default in the .NET SDK.

Portable PDB's are much smaller than Windows PDB's.

Both Windows and Portable PDB's are stored in a .pdb file by default. Portable PDB's may be embedded in a PE file (dll/exe) in a section, but otherwise it's the same data.

So when I say "Embedded PDB", that's where the PDB data is in the exe/dll itself. When that file is packed into a .nupkg, there's nothing extra needed as the pdb data is inside the dll/exe file. A portable PDB can be either alongside the dll in the nupkg or in a snupkg. snupkg does not support Windows PDBs.

BTW, the full format of Portable PDB is documented here: https://github.com/dotnet/runtime/blob/main/docs/design/specs/PortablePdb-Metadata.md

The format is controlled by the DebugType property:

full: Windows PDB, a .pdb file
portable / missing: Portable PDB, a .pdb file
embedded: Portable PDB, but stored inside the main .dll/.exe file
Extending this out to NuGet packages, .snupkg only supports Portable PDBs. There was an older .symbols.nupkg format that supported Windows PDBs and pushed the symbols to Symbol Soruce. That's mostly been deprecated as those Windows PDB's only work on Windows.

If you generate Portable PDB's, you need to decide where to put them; you have two choices: the main .nupkg, or the .snupkg. If you use Emedded PDBs, there's nothing to do since they're inside the main .dll/.exe, which is already in the .nupkg.

Our recommendation is to use Embedded PDB's largely for the simplicity and compatibility aspects. There's no additional package required (the .snupkg), no symbol server required (client config or server), and you'll always have it for diagnostics since you're far less likely to lose your running binary than some other artifact.

COMMENTS
from @PureKrome
@clairernovotny Wowz. this is awesome.

So this is sorta how I'm thinking the decision process goes ... in this exact order:

Which PDB format do I want? Portable or Windows?
How do I wish to share my PDB? Embedded or via an snupkg with a symbol server?
Finally, do I wish to Source Link my PDB?
Now it looks like you're saying that the suggested recommendation is 🥁 🥁🥁 :

Portable PDB's are supported cross platform
Portable PDB's are the default in the .NET SDK.
Our recommendation is to use Embedded PDB's

✔️ Portable PDB's
✔️ Embedded the PDB's.
🚀 Source Link those hawt PDB's.
So with this info, I'll start to do things like this.

It's also really helpful to see WHY people would want to choose snupkg's also. So all those questions @poke asked - that would be great to be documented also.

✔️ These are our (Microsoft) recommendations ...
⭐ But these the the other options ... which might suit these other scenarios
In the famous words of Carl Cox:
image

COMMENTS
from @slang25
Great writeup @clairernovotny! I've been advocating embedded PDBs for a couple of years now and will continue to do so.

@jnm2 recently made me aware of another interesting scenario where you might not want embedded PDBs, if you consider your library to be something not typically debugged by consumers:
shouldly/shouldly#772
I don't know if the underlying problem is really a tooling thing though.

COMMENTS
from @jnm2
It's a big problem for assertion or validation/check/throw helper libraries. It jars the inner loop test debugging experience for the IDE to stop in the innards of the assertion library when Just My Code is enabled, rather than stopping on your failing assertion.

COMMENTS
from @JonDouglas
Thank you all so much for the scenarios & modern guidance. We'll work on improving the existing documentation & writing some new conceptual docs during our next doc days(Once a month typically).

In the meantime, if anyone would like to contribute, I've marked this good first issue & help wanted. Here's how you can learn to contribute docs to NuGet:

https://github.com/NuGet/docs.microsoft.com-nuget#contribution-workflow

Otherwise, I'm mentally preparing myself to type up some new docs & recommendations on debug symbols. Till then!

image

COMMENTS
from @jnm2
The reason I'm not super excited about libraries ever embedding PDBs is that the larger file size doesn't feel appropriate in a mobile or desktop app distribution scenario.

For me, the sweet spot is a separate .pdb file for every library that could conceivably end up being distributed in an app, and snupkg is the current way of getting a library's separate .pdb file loaded with the least overall consumption friction.

COMMENTS
from @slang25
That's a job for the mono linker though, right?

COMMENTS
from @jnm2
If tooling existed to fix this in a way that didn't lose important attributes of the libraries, such as being able to still use the PDB data when debugging crash dumps (or for some, things like Authenticode?), and the tooling could be turned on with a single csproj property, that would be different.

COMMENTS
from @PureKrome
@JonDouglas also, maybe the Creating Symbol Packages doc can also be reviewed, as it is tied to this entire discussion, IMO

COMMENTS
from @JonDouglas
@PureKrome It's in the issue description when I first posted 😉. Is there something else?

COMMENTS
from @PureKrome
eeks. soz. I kept seeing the TITLE of the issue .. which is about Source Link (and thinking that might only get some updates .. not all the surrounding stuff, also) .. my bad.

sowwy

/me goes and hides :)

Verbose Logs

No response

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants