Nuget 的最佳实践: 调试还是发布?

目前,我把官方版本的版本和 Nuget 一起打包到 Nuget.org,但是我把符号源推送到 symbolsource.org 的调试版本和 Nuget 一起打包。

编辑: (Jon Skeet,带有一些来自 Noda Time 开发的偏见)

NuGet 现在支持向两个 NuGet 画廊推送 symbolsource.org (或类似的服务器) ,即 记录在案。不幸的是,这里有两个相互矛盾的要求:

  • 当只有 使用库而不需要任何调试时,您确实需要一个发布版本。毕竟,这就是释放版本的用途。
  • 在为诊断目的调试库时,您确实需要禁用所有适当优化的调试版本。毕竟,这就是构建调试的目的。

这很好,但是 NuGet (据我所知)不允许以有用的方式在同一个包中发布发布版本和调试版本。

所以,选择是:

  • 将调试版本分发给每个人(如文档中的示例所示) ,并使用任何大小和性能的命中。
  • 将发布版本分发给每个人,并带着轻微受损的调试体验生活。
  • 执行一个非常复杂的发布策略,可能会提供单独的发布和调试包。

前两个实际上归结为调试版本和发布版本之间的差异所造成的影响... ... 尽管值得注意的是,因为想要检查某些行为而想要进入库的代码和因为相信自己发现了 bug 而想要调试库的代码之间也有很大的差异。在第二种情况下,获取库 作为 VisualStudio 解决方案的代码并以这种方式进行调试可能更好,因此我不会过多关注这种情况。

我的想法是继续使用这个版本构建,期望很少有人需要调试 相对而言,而那些需要调试的人不会受到这个版本构建中的优化的影响。(不管怎样,大部分优化工作还是由 JIT 编译器完成的。)

还有其他我们没考虑过的选择吗?是否还有其他考虑因素打破了平衡?将 NuGet 软件包推向 SymbolSource 是否足够新,以至于“最佳实践”真的还没有建立起来?

22968 次浏览

The example in the Creating and Publishing A Symbol Package references files in the Debug directories as sources for the dll and pdb files.

Specifying Symbol Package Contents

A symbol package can be built by conventions, from a folder structured in the way described in the previous section, or its contents can be specified using the files section. If you wanted to build the example package described previously, you could put this into your nuspec file:

<files>
<file src="Full\bin\Debug\*.dll" target="lib\net40" />
<file src="Full\bin\Debug\*.pdb" target="lib\net40" />
<file src="Silverlight\bin\Debug\*.dll" target="lib\sl40" />
<file src="Silverlight\bin\Debug\*.pdb" target="lib\sl40" />
<file src="**\*.cs" target="src" />
</files>

Since the purpose of publishing the symbols is to allow others to step through your code when debugging, it seems most prudent to publish a version of the code intended for debugging without optimizations that might affect the code step through.

Speaking for SymbolSource, I believe that the best practice is to:

  1. Push release binary+content packages to nuget.org only (or any other production feed)
  2. Push debug binary+content packages to a development feed:
    • on-premise
    • on myget.org
    • on nuget.org as pre-release packages.
  3. Push both release and debug binary+symbols packages to symbolsource.org or any other symbol store.

While we're at it, it is a common misconception that release and debug builds in .NET really differ much, but I am assuming that the differentiation is here because of various code that might or might not be included in either build, like Debug.Asserts.

That said, it is really worth pushing both configurations to SymbolSource, because you just never know when you're going to need to debug production code. Remotely in production to make it harder. You're going to need the help you can get from your tooling when that happens. Which I obviously do not wish upon anyone.

There is still a matter to consider regarding versioning: is it correct to have 2 different packages (build in debug and in release) sharing 1 version number? SymbolSource would accept that, because it extracts packages and stores binaries in separate build mode branches, IF ONLY NuGet allowed to tag packages accordingly. There is no way at present to determine if a package is debug or release-mode.

I completely agree with your conclusion. NuGet packages with RELEASE and SymbolSource with debug. It seems pretty rare to step directly into packages and the occasional debug misstep with optimizations enabled might be acceptable.

If there were really a problem, I think the ideal solution would be to have NuGet support it. For example, imagine if when debugging, it could replace the release DLL with the one included in the SymbolSource package.

Ideally, what would happen then is that nuget pack SomePackage -Symbols against a release version would create a release nuget package, but a debug symbols package. And the VS plugin would be updated to be smart enough to see the association and pull in the Debug assemblies when running in a debugger and load those instead. Kind of crazy, but would be interesting.

However, I just don't see enough people complaining about this that it'd be worth it at the moment.

NuGet team accepts pull requests. :)

It's been 8 years since OP's post (with previous answer still top-voted below), so I'll give it a crack with what's used nowadays.

There are 2 ways of "stepping into" a NuGet package:

1. Distribution of PDBs

.symbols.nupkg symbol packages are considered as legacy and have been replaced with .snupkg packages that get published to Symbol Server. It’s supported by most vendors with Azure DevOps being the biggest outsider where the feature request is still "under review" (thank you @alv for the link).

Here are the official instructions. Simply add these two lines to the csproj file:

<PropertyGroup>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>

On the consumer side, make sure that your IDE is configured for the NuGet.org (or Azure, etc.) Symbol Server to allow stepping into package code when debugging.

2. Source Link.Linking the actual code

In some cases, the PDBs may hide some specifics of the source code due to MSIL/JIT optimisation. So there is a way of ”Stepping Into” the actual source of your NuGet while debugging. It’s called Source Link from the .NET Foundation – ”a language- and source-control agnostic system for providing source debugging experiences for binaries“.

It’s supported by Visual Studio 15.3+ and all the major vendors (also supports private repos).

It’s trivial to setup (official docs) – just add a development dependency to the project file (depends on the type of your repo) along with some flags:

<PropertyGroup>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>

Check out more on this subject in "5 steps to better NuGet package".