Nuget的最佳做法:调试还是发布?


89

目前,我将发布版本与Nuget打包在一起,以将正式版本打包到nuget.org,但我将调试版本与Nuget打包在一起,以将符号源推送到symbolsource.org。

编辑:(乔恩·斯基特,从野田时间发展的一些偏见)

NuGet现在支持同时推送到NuGet gallery symbolsource.org(或类似的服务器),如记录所示。不幸的是,这里有两个矛盾的要求:

  • 当只使用一个库而无需调试时,您确实需要发行版。毕竟,这就是发行版的目的。
  • 当出于诊断目的而调试到库中时,您确实想要禁用所有适当优化的调试版本。毕竟,这就是调试版本的目的。

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

因此,选择是:

  • 将调试版本分发给每个人(如文档中的示例所示),并在不影响大小和性能的情况下生存。
  • 向所有人分发发行版,并在调试体验稍有下降的情况下进行。
  • 选择一个非常复杂的分发策略,可能会提供单独的发行和调试包。

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

我的诱惑是只保留与发行版本,与预期相对很少有人会需要调试,和谁做的人不会受到影响太大由发布版本的优化。(无论如何,JIT编译器都会进行大多数优化。)

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


2
我将要问同样的问题-尽管目前我也将Release配置也推送到symbolsource,因为我只是在使用nuget pack ... -Symbol和推送生成的软件包...
Jon Skeet

1
我觉得我应该向NuGet背后的人们提交此问答环节,看看他们是否可以参与其中。
gzak

烘烤登录到您的程序包,然后仅发布发行版本。您可以允许记录器注入,这将使使用者可以根据自己的喜好设置记录。
CShark

Answers:


29

对于SymbolSource,我认为最佳实践是:

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

虽然我们很容易理解,但是人们普遍误以为.NET中的发行版和调试版本确实有很大的不同,但是我认为这种区别是在这里,因为调试中可能包含或可能不包含各种代码,例如Debug。断言。

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

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


“将两个版本发布到NuGet”部分比较棘手。我一直发布Noda Time的Release版本,因为我必须在两者之间进行选择。(我有一个nuspec文件,而不是仅从C#项目来完成。)您提到调试生产代码,似乎仅使用发行版版本要困难得多-尽管先前的“它们差别不大”。我知道调试版本中的NOP,显然还有其他信息Debug.Assert-但是您能否在调试时扩展(答案)?使用发布版本有多糟糕?
乔恩·斯基特

我的意思是,您希望所有正在使用的二进制文件都具有符号:如果在野外同时存在调试和发布版本,则需要为两者提供符号。它们不需要在代码方面有很大的不同,但是它们在校验和方面会有所不同,这使得无需进行黑客操作就无法加载符号。
TripleEmcoder

1
对。我可能的解决方案是发布Release二进制文件,但我担心在调试方面会遭受多少损失。例如,缺少NOP是否意味着您无法添加断点?
乔恩·斯基特

与构建时优化相比,JIT优化的问题更多。因此,如果您推送发布模式程序包并建议在需要调试时使用COMPLUS_ZapDisable = 1,这对我来说已经足够了。NuGet仍应允许以某种方式一起调试和发布。
TripleEmcoder

我不知道symbolsource.org存在。作为痒,我很多时候都需要抓挠,我对此表示欢迎。
Remus Rusanu

4

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

如果确实存在问题,我认为理想的解决方案是让NuGet支持它。例如,假设在调试时是否可以用SymbolSource软件包中包含的DLL代替发行版DLL。

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

但是,我只是没有看到足够多的人对此事抱怨,这是值得的。

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


我不确定我是否理解您的第二句话-我怀疑OP(在我编辑之前)正在手动推送到SymbolSource进行调试。如果发行版本的PDB最终出现在SymbolSource中而不是调试版本中,您是否设想了重大问题?还是您所提倡的,我只是被误解了?
乔恩·斯基特

3
“但是,我只是没有看到足够多的人对此事抱怨,这是值得的。” 也许他们不是在抱怨,但是如果您向用户样本询问他们对此的看法,我敢打赌,您会发现大多数人在这一特定步骤中会感到有些困惑(发布到NuGet.org和SymbolSource的内容) .org)。如果您问他们最终选择什么,您可能会发现没有一个一致同意的做法,每个人都在做自己的事情。
gzak

7
我要为此投诉,该在哪里注册?
Alex

一旦有了内部NuGet并开始将它们部署到符号服务器上……您将不可避免地要调试它们。局部变量或参数...已被优化”。正如Phil所提到的...如果nuget有一种方法可以以调试模式加载调试dll,并以发布模式(从nuget包中)释放dll,那么这将是最终的选择。在那之前,我们被卡住NuGet包切换
felickz

1
我同意,这将是一个不错的产品增强功能。
htm11h

1

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

指定符号包内容

可以通过约定从前一部分中所述的结构化文件夹中构建符号包,也可以使用文件部分指定其内容。如果要构建前面描述的示例程序包,可以将其放入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>

由于发布符号的目的是允许其他人在调试时逐步浏览您的代码,因此最明智的做法是发布用于调试的代码版本,而不进行可能影响代码逐步调试的优化。


是的,这就是该示例所做的工作-但我宁愿不以调试能力取代大多数开发人员只运行发行版的愿望。问题是,据我所知,NuGet没有发布发布和调试版本的方法。(同时发布这两个文件对我来说也有点痛苦,因为这意味着要为已签名的调试版本创建另一套配置...)
Jon Skeet

在这里,我们进入一点主观性。通常,我对“最佳做法”的选择是作者建议的明示或暗含的建议,因为我认为他们比我有更多的见识(或者在假设中最终假设的情况下是疏忽)。我个人而言,我认为这些符号应与我使用的版本匹配。我通常不会使用我认为可能必须进行调试的软件包,除非该源是公开的,并且可以根据需要从头开始进行编译,因此缺少打包的调试版本并不是特别重要。
tvanfosson

在我的情况下,如果有人因为相信Noda Time中的一个错误而需要调试Noda Time,那么最好下载源代码(当然,他们可以这样做)。但是,能够进入Noda Time源代码只是为了看看发生了什么仍然很有用。基本上,我认为(至少)有两种不同的调试方案,具有不同的解决方案...
Jon Skeet

我想考虑的一件事是.NET本身:我可以肯定地说Microsoft发布.NET而不是调试版本。发布版本意味着一定程度的质量和稳定性,因此,您的想法是,您几乎不需要介入代码来诊断问题。
gzak

2
但是,这也是一种“封闭源”的心态。我发现在开源世界中,人们更希望能够进入各种库的“稳定版本”的代码中,而不是因为事情已经坏了,而是因为有时最好的文档只是看一下库是什么在做。
gzak
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.