100

目前,我使用 Nuget 将发布版本打包到 nuget.org 的官方版本,但我使用 Nuget 打包调试版本,以便将符号源推送到 symbolsource.org。

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

NuGet 现在支持推送到 NuGet 库symbolsource.org(或类似服务器),如文档所述。不幸的是,这里有两个相互矛盾的要求:

  • 当只使用库而不需要任何调试时,你真的想要一个发布版本。毕竟,这就是发布版本的用途。
  • 出于诊断目的调试库时,您确实需要禁用所有适当优化的调试版本。毕竟,这就是调试版本的用途。

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

所以,选择是:

  • 将调试版本分发给每个人(如文档中的示例所示),并接受任何规模和性能影响。
  • 将发布版本分发给每个人,并忍受稍微受损的调试体验。
  • 寻求一个非常复杂的分发策略,可能会提供单独的发布和调试包。

前两个确实归结为调试和发布版本之间差异的影响......尽管值得注意的是,因为想要检查某些行为而想要进入库的代码和想要调试库的代码,因为您认为自己发现了错误。在第二种情况下,最好将库的代码作为 Visual Studio 解决方案获取并以这种方式进行调试,因此我不会过多注意这种情况。

我的诱惑是只保留发布版本,期望相对较少的人需要调试,而那些这样做的人不会受到发布版本中的优化的太大影响。(无论如何,JIT 编译器都会进行大部分优化。)

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

4

4 回答 4

33

对于 SymbolSource,我认为最佳做法是:

  1. 仅将发布的二进制 + 内容包推送到 nuget.org(或任何其他生产源)
  2. 将调试二进制+内容包推送到开发提要:
    • 内部部署
    • 在 myget.org 上
    • 在 nuget.org 作为预发布包。
  3. 将发布和调试二进制+符号包推送到 symbolsource.org 或任何其他符号存储。

虽然我们在这里,一个常见的误解是 .NET 中的发布和调试版本确实有很大差异,但我假设差异就在这里,因为任何一个版本中可能包含或可能不包含的各种代码,如调试.断言。

也就是说,将这两种配置都推送到 SymbolSource 确实值得,因为您永远不知道何时需要调试生产代码。远程生产使其更难。发生这种情况时,您将需要从您的工具中获得的帮助。我显然不希望任何人。

关于版本控制还有一个问题需要考虑:让 2 个不同的包(在调试和发布中构建)共享 1 个版本号是否正确?SymbolSource 会接受这一点,因为它提取包并将二进制文件存储在单独的构建模式分支中,如果仅允许 NuGet 相应地标记包。目前没有办法确定一个包是调试模式还是发布模式。

于 2013-02-01T07:31:07.097 回答
4

我完全同意你的结论。带有 RELEASE 的 NuGet 包和带有调试功能的 SymbolSource。直接进入包似乎很少见,启用优化的偶尔调试失误可能是可以接受的。

如果真的有问题,我认为理想的解决方案是让 NuGet 支持它。例如,想象一下,如果在调试时,它可以将发布 DLL 替换为 SymbolSource 包中包含的那个。

理想情况下,随后会发生的情况是,nuget pack SomePackage -Symbols针对发布版本会创建一个发布 nuget 包,但会创建一个调试符号包。并且 VS 插件将更新为足够智能,以便在调试器中运行时查看关联并拉入调试程序集并加载它们。有点疯狂,但会很有趣。

但是,我只是没有看到足够多的人抱怨这一点,所以目前值得。

NuGet 团队接受拉取请求。:)

于 2013-02-04T21:41:11.443 回答
4

自 OP 的帖子发布以来已经 8 年了(之前的答案仍然在下面获得最高投票),所以我会用现在使用的东西来破解它。

“进入” NuGet 包有两种方式:

1. PDB 分布

.symbols.nupkg符号包被认为是旧的,并已被.snupkg发布到符号服务器的包所取代。大多数供应商都支持它,Azure DevOps是最大的局外人,功能请求仍在“审查中”(感谢@alv 提供链接)。

以下是官方说明。只需将这两行添加到 csproj 文件中:

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

在消费者方面,确保您的 IDE 已针对 NuGet.org(或 Azure 等)符号服务器进行配置,以允许在调试时单步执行包代码。

2.源码链接。链接实际代码

在某些情况下,由于 MSIL/JIT 优化,PDB 可能会隐藏源代码的某些细节。因此,有一种方法可以在调试时“<em>进入”NuGet 的实际源代码。它被称为.NET Foundation 的Source Link—— “一个与语言和源代码控制无关的系统,用于为二进制文件提供源代码调试体验”。

Visual Studio 15.3+ 和所有主要供应商都支持它(也支持私有存储库)。

设置(官方文档)很简单——只需在项目文件中添加一个开发依赖项(取决于你的 repo 的类型)以及一些标志:

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

在“改进 NuGet 包的 5 个步骤”中查看有关此主题的更多信息。

于 2020-09-21T00:51:59.890 回答
1

创建和发布符号包中的示例将 Debug 目录中的文件引用为 dll 和 pdb 文件的源。

指定符号包内容

符号包可以按照约定从按上一节中描述的方式构建的文件夹中构建,或者可以使用 files 部分指定其内容。如果你想构建前面描述的示例包,你可以把它放到你的 nuspec 文件中:

<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>

由于发布符号的目的是允许其他人在调试时单步执行您的代码,因此发布用于调试的代码版本似乎是最谨慎的做法,而无需进行可能影响代码单步执行的优化。

于 2013-02-01T07:28:22.993 回答