Best Practices mit Nuget: Debug oder Release?

89

Derzeit packe ich die Release-Builds mit Nuget für die offiziellen Builds auf nuget.org, aber ich packe die Debug-Builds mit Nuget für die Symbolquellen-Pushs auf symbellsource.org.

EDIT: (Jon Skeet, mit einigen Vorurteilen von Noda Time Entwicklung)

NuGet unterstützt jetzt das Pushen sowohl zur NuGet-Galerie als auch zu Symbolsource.org (oder ähnlichen Servern), wie dokumentiert . Leider gibt es hier zwei widersprüchliche Anforderungen:

  • Wenn nur mit einer Bibliothek , ohne dass für das Debuggen, wollen Sie wirklich ein Release - Build. Dafür sind schließlich Release-Builds gedacht.
  • Wenn Sie zu Diagnosezwecken in eine Bibliothek debuggen, möchten Sie wirklich einen Debug-Build, bei dem alle entsprechenden Optimierungen deaktiviert sind. Dafür sind Debug-Builds schließlich da.

Das wäre in Ordnung, aber NuGet erlaubt (soweit ich das beurteilen kann) nicht, dass sowohl die Release- als auch die Debug-Builds auf nützliche Weise im selben Paket veröffentlicht werden.

Die Auswahlmöglichkeiten sind also:

  • Verteilen Sie die Debug-Builds an alle (wie im Beispiel in den Dokumenten gezeigt) und leben Sie mit Treffern jeder Größe und Leistung.
  • Verteilen Sie die Release-Builds an alle und leben Sie mit einer leicht beeinträchtigten Debug-Erfahrung.
  • Entscheiden Sie sich für eine wirklich komplizierte Verteilungsrichtlinie, die möglicherweise separate Release- und Debug-Pakete bereitstellt.

Die ersten beiden beschränken sich wirklich auf die Unterschiede zwischen Debug- und Release-Builds ... obwohl es erwähnenswert ist, dass es auch einen großen Unterschied gibt, ob Sie in den Code einer Bibliothek eintreten möchten, weil Sie ein bestimmtes Verhalten überprüfen möchten oder nicht um den Code einer Bibliothek zu debuggen, weil Sie glauben, einen Fehler gefunden zu haben. Im zweiten Fall ist es wahrscheinlich besser, den Code der Bibliothek als Visual Studio-Lösung abzurufen und auf diese Weise zu debuggen, damit ich dieser Situation nicht zu viel Aufmerksamkeit schenke.

Meine Versuchung ist einfach zu halten mit der Release - Builds, mit der Erwartung , dass relativ wenige Menschen zu debuggen benötigen, und diejenigen , die tun nicht beeinträchtigt werden viel von den Optimierungen in dem Release - Build. (Der JIT-Compiler übernimmt sowieso den größten Teil der Optimierung.)

Gibt es andere Optionen, die wir nicht in Betracht gezogen hatten? Gibt es andere Überlegungen, die das Gleichgewicht beeinflussen? Ist die Weitergabe von NuGet-Paketen an SymbolSource so neu, dass "Best Practice" wirklich nicht etabliert wurde?

gzak
quelle
2
Ich wollte die gleiche Frage stellen - obwohl ich derzeit die Release-Konfiguration auch auf die Symbolquelle drücke, da ich nur nuget pack ... -Symboldie generierten Pakete verwende und pushe ...
Jon Skeet
1
Ich habe das Gefühl, ich sollte diese Q / A-Sitzung den Leuten hinter NuGet vorlegen und sehen, ob sie sich darüber Gedanken machen können.
Gzak
Backen Sie die Anmeldung in Ihrem Paket und veröffentlichen Sie dann nur den Release-Build. Sie können die Logger-Injektion zulassen, mit der der Verbraucher die Protokollierung gemäß seinen Präferenzen einrichten kann.
CShark

Antworten:

29

Wenn ich für SymbolSource spreche, glaube ich, dass die beste Vorgehensweise darin besteht:

  1. Push Release Binär + Content-Pakete nur an nuget.org (oder einen anderen Produktions-Feed)
  2. Übertragen Sie Debug-Binär- + Inhaltspakete in einen Entwicklungsfeed:
    • vor Ort
    • auf myget.org
    • auf nuget.org als Pre-Release-Pakete.
  3. Übertragen Sie sowohl Release- als auch Debug-Binärsymbol-Pakete an symbellsource.org oder einen anderen Symbolspeicher.

Während wir gerade dabei sind, ist es ein weit verbreitetes Missverständnis, dass Release- und Debug-Builds in .NET sehr unterschiedlich sind, aber ich gehe davon aus, dass die Unterscheidung hier auf verschiedenen Code zurückzuführen ist, der in beiden Builds enthalten sein kann oder nicht, wie z. B. Debug .Asserts.

Trotzdem lohnt es sich wirklich, beide Konfigurationen auf SymbolSource zu übertragen, da Sie nie wissen, wann Sie Produktionscode debuggen müssen. Remote in der Produktion, um es schwieriger zu machen. In diesem Fall benötigen Sie die Hilfe, die Sie von Ihren Werkzeugen erhalten können. Was ich natürlich niemandem wünsche.

Bei der Versionierung ist noch einiges zu beachten: Ist es richtig, zwei verschiedene Pakete (im Debug und in der Version eingebaut) mit einer Versionsnummer zu haben? SymbolSource würde dies akzeptieren, da es Pakete extrahiert und Binärdateien in separaten Zweigen im Erstellungsmodus speichert, WENN NUR NuGet Pakete entsprechend kennzeichnen darf. Derzeit gibt es keine Möglichkeit festzustellen, ob sich ein Paket im Debug- oder Release-Modus befindet.

TripleEmcoder
quelle
Der Teil "Veröffentlichen von zwei Builds in NuGet" ist das Knifflige. Ich habe immer den Release-Build von Noda Time veröffentlicht, weil ich mich zwischen beiden entscheiden musste. (Ich habe eine Nuspec-Datei, anstatt sie nur aus dem C # -Projekt zu erstellen.) Sie erwähnen das Debuggen von Produktionscode, als ob dies mit nur einem Release-Build erheblich schwieriger wäre - trotz des vorherigen Teils "Sie unterscheiden sich nicht sehr". Ich kenne die NOPs in Debug-Builds und natürlich Debug.Assertusw. - aber könnten Sie (in Ihrer Antwort) die Auswirkungen beim Debuggen erweitern? Wie schlecht ist es, einen Release-Build zu verwenden?
Jon Skeet
Ich meinte nur, dass Sie Symbole für alle verwendeten Binärdateien zur Verfügung haben möchten: Wenn sowohl Debug- als auch Release-Builds in freier Wildbahn vorhanden sind, möchten Sie Symbole für beide bereitstellen. Sie müssen sich in Bezug auf Code nicht sehr unterscheiden, aber sie unterscheiden sich in Prüfsummen, was das Laden von Symbolen ohne Hacking unmöglich macht.
TripleEmcoder
1
Richtig. Meine mögliche Lösung besteht darin, immer nur die Release-Binärdateien freizugeben, aber ich mache mir Sorgen darüber, wie sehr dies beim Debuggen schaden wird. Bedeutet das Fehlen von NOPs beispielsweise, dass Sie keine Haltepunkte hinzufügen können?
Jon Skeet
Das Problem liegt eher bei JIT-Optimierungen als bei Optimierungen zur Erstellungszeit. Wenn Sie also Pakete im Release-Modus pushen und die Verwendung von COMPLUS_ZapDisable = 1 empfehlen, wenn das Debuggen erforderlich ist, wäre das für mich gut genug. Trotzdem sollte NuGet das Debuggen und Freigeben auf irgendeine Weise ermöglichen.
TripleEmcoder
Ich hatte keine Ahnung, dass symbolssource.org existiert. Als Juckreiz musste ich oft kratzen, ich begrüße es.
Remus Rusanu
4

Ich stimme Ihrer Schlussfolgerung voll und ganz zu. NuGet-Pakete mit RELEASE und SymbolSource mit Debug. Es scheint ziemlich selten, direkt in Pakete einzusteigen, und gelegentliche Debug-Fehltritte mit aktivierten Optimierungen sind möglicherweise akzeptabel.

Wenn es wirklich ein Problem gäbe, wäre es meiner Meinung nach die ideale Lösung, wenn NuGet es unterstützt. Stellen Sie sich beispielsweise vor, Sie könnten beim Debuggen die Release-DLL durch die im SymbolSource-Paket enthaltene ersetzen.

Im Idealfall würde dann nuget pack SomePackage -Symbolsgegen eine Release-Version ein Release-Nuget-Paket, aber ein Debug-Symbol-Paket erstellt. Das VS-Plugin wird so aktualisiert, dass es intelligent genug ist, um die Zuordnung zu erkennen und die Debug-Assemblys abzurufen, wenn es in einem Debugger ausgeführt wird, und diese stattdessen zu laden. Ein bisschen verrückt, wäre aber interessant.

Ich sehe jedoch nicht genug Leute, die sich darüber beschweren, dass es sich im Moment lohnt.

Das NuGet-Team akzeptiert Pull-Anfragen. :) :)

Gehackt
quelle
Ich bin nicht sicher, ob ich Ihren zweiten Satz verstehe. Ich vermute, dass das OP (bevor ich es bearbeitet habe) manuelle Pushs für die Debug-Builds an SymbolSource durchgeführt hat. Stellen Sie sich erhebliche Probleme vor, wenn der PDB der Release- Version in SymbolSource anstelle der Debug-Version landet? Oder haben Sie das befürwortet, und ich habe es einfach falsch verstanden?
Jon Skeet
3
"Ich sehe jedoch nicht genug Leute, die sich darüber beschweren, dass es sich im Moment lohnt." Vielleicht beschweren sie sich nicht, aber wenn Sie eine Stichprobe von Benutzern fragen, was sie davon halten, würden Sie wahrscheinlich feststellen, dass die meisten Leute bei diesem bestimmten Schritt ein wenig Verwirrung eingestehen würden (was sie auf NuGet.org und SymbolSource veröffentlichen sollten) .org). Wenn Sie fragen, was sie letztendlich ausgewählt haben, werden Sie wahrscheinlich feststellen, dass es keine einzige vereinbarte Praxis gibt, jeder macht einfach sein eigenes Ding.
Gzak
7
Ich möchte mich darüber beschweren. Wo melde ich mich an?
Alex
Sobald Sie über interne NuGets verfügen und diese auf einem Symbolserver bereitstellen ... werden Sie sie unweigerlich debuggen wollen ... und obwohl Sie den Code schrittweise durchgehen können, wird am Ende "Kann den Wert von nicht erhalten lokale Variable oder Argument ... es wurde weg optimiert ". Wie Phil erwähnt ... WENN Nuget eine Möglichkeit hätte, Debug-DLLs im Debug-Modus zu laden und DLLs im Release-Modus (aus Nuget-Paketen) freizugeben, wäre dies die ultimative Lösung. Bis dahin stecken wir mit Nuget Paketumschalter fest
felickz
1
Ich stimme zu, dies wäre eine schöne Produktverbesserung.
htm11h
1

Das Beispiel im Erstellen und Veröffentlichen eines Symbolpakets verweist auf Dateien in den Debug-Verzeichnissen als Quellen für die DLL- und PDF-Dateien.

Angeben des Inhalts des Symbolpakets

Ein Symbolpaket kann durch Konventionen aus einem Ordner erstellt werden, der wie im vorherigen Abschnitt beschrieben strukturiert ist, oder sein Inhalt kann mithilfe des Abschnitts "Dateien" angegeben werden. Wenn Sie das zuvor beschriebene Beispielpaket erstellen möchten, können Sie dies in Ihre nuspec-Datei einfügen:

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

Da der Zweck des Publizierens der Symbole darin besteht, anderen zu ermöglichen, Ihren Code beim Debuggen zu durchlaufen, erscheint es am ratsamsten, eine Version des Codes zu veröffentlichen, die zum Debuggen vorgesehen ist, ohne Optimierungen vorzunehmen, die sich auf den Code auswirken könnten.

Tvanfosson
quelle
Ja, genau das macht das Beispiel - aber ich möchte lieber nicht die Möglichkeit zum Debuggen haben, die den Wunsch der meisten Entwickler überschreibt, nur die Release-Version auszuführen. Das Problem ist, dass NuGet, soweit ich das beurteilen kann, keine Möglichkeit hat, sowohl Release- als auch Debug-Builds zu veröffentlichen. (Es wäre auch ein kleines Problem für mich, beide zu veröffentlichen, da dies bedeutet, dass noch weitere Konfigurationen für signierte Debug-Builds erstellt werden ...)
Jon Skeet
Hier kommen wir zu einer kleinen Subjektivität. Normalerweise würde ich mich für "Best Practice" entscheiden, was der Autor entweder explizit oder implizit empfiehlt, da ich davon ausgehe, dass sie mehr Einsicht (oder Kontrolle bei Annahmen, die in Beispielen enden) haben als ich. Ich denke, die Symbole sollten mit der von mir verwendeten Version übereinstimmen. Normalerweise würde ich kein Paket verwenden, von dem ich dachte, dass ich es wahrscheinlich debuggen müsste, es sei denn, die Quelle wäre öffentlich und ich könnte bei Bedarf von Grund auf neu kompilieren. Daher ist das Fehlen eines gepackten Debug-Builds nicht besonders wichtig.
Tvanfosson
In meinem Fall, wenn jemand Noda Time debuggen muss, weil er glaubt, dass es einen Fehler in Noda Time gibt, ist es besser, die Quelle herunterzuladen (was er natürlich tun kann). Es ist jedoch immer noch nützlich, in den Noda Time-Quellcode einzusteigen, um zu sehen, was los ist. Grundsätzlich denke ich, dass es (mindestens) zwei verschiedene Szenarien für das Debuggen mit unterschiedlichen Lösungen gibt ...
Jon Skeet
Eine Sache, über die ich gerne nachdenke, ist .NET selbst: Ich kann mit Sicherheit sagen, dass Microsoft Release-Builds veröffentlicht und keine Builds von .NET debuggt. Ein Release-Build setzt ein gewisses Maß an Qualität und Stabilität voraus. Die Idee ist also, dass Sie selten in den Code eintreten müssen, um Dinge zu diagnostizieren.
Gzak
2
Das ist aber auch eine eher "Closed-Source" -Mentalität. Ich habe festgestellt, dass es in der Open-Source-Welt eher erwartet wird, in den Code "stabiler Releases" verschiedener Bibliotheken einzusteigen, nicht weil die Dinge kaputt sind, sondern weil es manchmal die beste Dokumentation ist, nur zu sehen, was die Bibliothek ist tun.
gzak