Najlepsze rozwiązania dotyczące Nuget: debugowanie czy wydanie?

92

Obecnie pakuję kompilacje wydania z Nuget dla oficjalnych kompilacji do nuget.org, ale pakuję kompilacje debugowania z Nuget, aby źródło symboli wypychało do symbolsource.org.

EDYCJA: (Jon Skeet, z pewnym odchyleniem od rozwoju Noda Time)

NuGet obsługuje teraz wypychanie zarówno do galerii NuGet, jak i do symbolsource.org (lub podobnych serwerów), zgodnie z dokumentacją . Niestety istnieją tutaj dwa sprzeczne wymagania:

  • Kiedy po prostu używasz biblioteki bez potrzeby debugowania, naprawdę potrzebujesz kompilacji wydania. W końcu do tego służą kompilacje wydań.
  • Podczas debugowania w bibliotece w celach diagnostycznych naprawdę potrzebujesz kompilacji debugowania z wyłączonymi wszystkimi odpowiednimi optymalizacjami. W końcu do tego służą kompilacje debugowania.

Byłoby dobrze, ale NuGet nie (o ile wiem) nie pozwala na publikowanie zarówno wersji wydania, jak i kompilacji debugowania w użyteczny sposób, w tym samym pakiecie.

Mamy więc do wyboru:

  • Roześlij wszystkim kompilacje debugowania (jak pokazano na przykładzie w dokumentacji) i żyj z dowolnymi rozmiarami i wynikami wydajności.
  • Rozpowszechnij kompilacje wydania wszystkim i korzystaj z nieco ograniczonego środowiska debugowania.
  • Wybierz naprawdę skomplikowaną politykę dystrybucji, potencjalnie zapewniającą oddzielne wydania i pakiety do debugowania.

Pierwsze dwie naprawdę sprowadzają się do efektu różnic między kompilacjami debugowania i wydania ... chociaż warto zauważyć, że istnieje również duża różnica między chęcią wejścia do kodu biblioteki, ponieważ chcesz sprawdzić pewne zachowanie, a chęcią aby debugować kod biblioteki, ponieważ uważasz, że znalazłeś błąd. W drugim przypadku prawdopodobnie lepiej jest pobrać kod biblioteki jako rozwiązanie Visual Studio i debugować w ten sposób, więc nie zwracam zbytniej uwagi na tę sytuację.

Moją pokusą jest pozostanie przy kompilacjach wydania, oczekując, że stosunkowo niewiele osób będzie musiało debugować, a optymalizacje w kompilacji wydania nie będą miały większego wpływu na tych, którzy to robią . (Kompilator JIT i tak wykonuje większość optymalizacji).

Czy są więc inne opcje, których nie rozważaliśmy? Czy są inne względy, które przechylają szalę? Czy wypychanie pakietów NuGet do SymbolSource jest na tyle nowe, że „najlepsze rozwiązanie” naprawdę nie zostało ustanowione?

gzak
źródło
2
Miałem właśnie zadać to samo pytanie - chociaż obecnie przekazuję konfigurację wydania również do źródła symboli, biorąc pod uwagę, że po prostu używam nuget pack ... -Symboli wysyłam wygenerowane pakiety ...
Jon Skeet,
1
Czuję, że powinienem przesłać tę sesję pytań i odpowiedzi do osób stojących za NuGet i sprawdzić, czy mogą to rozważyć.
gzak
Zaloguj się do swojego pakietu, a następnie opublikuj tylko kompilację wydania. Możesz zezwolić na wstrzykiwanie rejestratora, który umożliwi konsumentowi skonfigurowanie logowania zgodnie z jego / jej preferencjami.
CShark

Odpowiedzi:

31

W imieniu SymbolSource uważam, że najlepszą praktyką jest:

  1. Wypychanie pakietów zawartości binarnej + wersji do witryny nuget.org (lub dowolnego innego źródła produkcyjnego)
  2. Wypchnij pakiety debugowania binarnego + zawartości do źródła rozwoju:
    • lokalnie
    • na myget.org
    • na nuget.org jako pakiety w wersji wstępnej.
  3. Wypchnij pakiety do wydania i debugowania binarnych + symboli do symbolsource.org lub dowolnego innego magazynu symboli.

Skoro już o tym mowa, powszechnym błędem jest przekonanie, że kompilacje do wydania i debugowania w .NET naprawdę bardzo się różnią, ale zakładam, że różnica jest tutaj z powodu różnych kodów, które mogą, ale nie muszą być zawarte w obu kompilacjach, takich jak Debug .Asserts.

To powiedziawszy, naprawdę warto wypchnąć obie konfiguracje do SymbolSource, ponieważ nigdy nie wiesz, kiedy będziesz musiał debugować kod produkcyjny. Zdalnie w produkcji, aby było trudniej. Będziesz potrzebować pomocy, jaką możesz uzyskać od narzędzi, gdy to się stanie. Czego oczywiście nikomu nie życzę.

Nadal jest kwestia do rozważenia w odniesieniu do wersjonowania: czy to poprawne, aby 2 różne pakiety (wbudowane w debugowanie i wydanie) miały jeden numer wersji? SymbolSource zaakceptuje to, ponieważ wyodrębnia pakiety i przechowuje pliki binarne w oddzielnych gałęziach trybu kompilacji, JEŚLI TYLKO NuGet może odpowiednio oznaczać pakiety. Obecnie nie ma możliwości określenia, czy pakiet jest w trybie debugowania, czy w trybie wydania.

TripleEmcoder
źródło
Część „publikowanie dwóch kompilacji w NuGet” jest najtrudniejsza. Zawsze publikowałem wersję Release of Noda Time, opierając się na tym, że musiałem wybierać między nimi. (Mam plik nuspec, zamiast robić to tylko z projektu C #.) Wspomniałeś o debugowaniu kodu produkcyjnego, jakby to było znacznie trudniejsze przy tylko kompilacji wydania - pomimo poprzedniej części „nie różnią się zbytnio”. Zdaję sobie sprawę z NOPów w kompilacjach debugowania i oczywiście Debug.Assertitp. - ale czy możesz rozszerzyć (w swojej odpowiedzi) na implikacje podczas debugowania? Jak źle wygląda korzystanie z kompilacji wydania?
Jon Skeet
Chodziło mi o to, że chcesz mieć symbole dostępne dla wszystkich używanych plików binarnych: jeśli w środowisku naturalnym istnieją zarówno kompilacje debugowania, jak i wydania, będziesz chciał zapewnić symbole dla obu. Nie muszą się zbytnio różnić pod względem kodu, ale będą się różnić sumami kontrolnymi, co uniemożliwia ładowanie symboli bez hakowania.
TripleEmcoder
1
Dobrze. Moim możliwym rozwiązaniem jest opublikowanie tylko plików binarnych wydania, ale martwię się, jak bardzo zaszkodzi to debugowaniu. Na przykład, czy brak NOP oznacza, że ​​nie można dodawać punktów przerwania?
Jon Skeet
Problem dotyczy bardziej optymalizacji JIT niż optymalizacji czasu kompilacji. Więc jeśli wypychasz pakiety w trybie wydania i zalecasz używanie COMPLUS_ZapDisable = 1, gdy potrzebne jest debugowanie, byłoby to dla mnie wystarczająco dobre. Nadal NuGet powinien w jakiś sposób zezwalać na debugowanie i wydawanie razem.
TripleEmcoder
Nie miałem pojęcia, że ​​symbolssource.org istnieje. Jako swędzenie nieraz miałem potrzebę drapania się, witam to z zadowoleniem.
Remus Rusanu
4

Całkowicie zgadzam się z twoim wnioskiem. Pakiety NuGet z RELEASE i SymbolSource z debugowaniem. Wydaje się dość rzadkie wchodzenie bezpośrednio do pakietów, a okazjonalne błędy w debugowaniu z włączoną optymalizacją mogą być dopuszczalne.

Gdyby naprawdę był problem, myślę, że idealnym rozwiązaniem byłoby wsparcie NuGet. Na przykład wyobraź sobie, że podczas debugowania może zastąpić bibliotekę DLL wydania wersją zawartą w pakiecie SymbolSource.

Idealnie byłoby wtedy, nuget pack SomePackage -Symbolsgdyby wersja wydana utworzyła pakiet nuget wydania, ale pakiet symboli debugowania. Wtyczka VS zostanie zaktualizowana, aby była wystarczająco inteligentna, aby zobaczyć skojarzenie i pobrać zestawy debugowania podczas uruchamiania w debugerze i zamiast tego załadować je. Trochę szalone, ale byłoby interesujące.

Jednak po prostu nie widzę wystarczającej liczby osób narzekających na to, że w tej chwili byłoby to tego warte.

Zespół NuGet akceptuje żądania ściągnięcia. :)

Haacked
źródło
Nie jestem pewien, czy rozumiem twoje drugie zdanie - podejrzewam, że OP (zanim zredagowałem) wykonywał ręczne wypychanie do SymbolSource dla kompilacji debugowania. Czy przewidujesz poważne problemy, jeśli PDB wersji wydania trafi do SymbolSource zamiast do wersji debugowanej? A może to jest to, za czym się opowiadałeś, a ja po prostu źle zrozumiałem?
Jon Skeet
3
„Jednak po prostu nie widzę wystarczającej liczby osób narzekających na to, że w tej chwili byłoby to tego warte”. Być może nie narzekają, ale jeśli zapytasz próbkę użytkowników, co o tym myślą, założę się, że większość ludzi przyznałaby się do pewnego zamieszania na tym konkretnym etapie (co opublikować w NuGet.org i SymbolSource .org). Jeśli zapytasz, co ostatecznie wybrali, prawdopodobnie okaże się, że nie ma jednej uzgodnionej praktyki, każdy po prostu robi swoje.
gzak
7
Chcę na to narzekać, gdzie mam się zarejestrować?
Alex
Gdy masz już wewnętrzne NuGety i zaczniesz wdrażać je na serwerze symboli ... nieuchronnie będziesz chciał je debugować .... i nawet jeśli możesz przejść przez kod, otrzymasz komunikat „Nie można uzyskać wartości lokalna zmienna lub argument ... został zoptymalizowany ". Jak wspomina Phil ... JEŚLI nuget miał możliwość załadowania bibliotek dll debugowania w trybie debugowania i zwolnienia bibliotek dll w trybie wydania (z pakietów nuget), byłoby to ostateczne. Do tego czasu utknęliśmy w przełączniku pakietów
Nuget
1
Zgadzam się, byłoby to fajne ulepszenie produktu.
htm11h
2

Minęło 8 lat od postu OP, więc spróbuję tego, co jest używane obecnie.

Istnieją dwa sposoby „wkraczania do ” pakietu NuGet:

1. Dystrybucja PDB

.symbols.nupkgPakiety symboli są uważane za starsze i zostały zastąpione .snupkgpakietami publikowanymi na serwerze Symbol Server . Jest obsługiwany przez wszystkich głównych dostawców, takich jak NuGet.org, Azure DevOps ( choć mniej płynne ) itp.

Oto oficjalne instrukcje . Po prostu dodaj te dwie linie do pliku csproj:

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

Po stronie konsumenta upewnij się, że środowisko IDE jest skonfigurowane dla serwera symboli NuGet.org (lub platformy Azure itp.), Aby umożliwić przechodzenie do kodu pakietu podczas debugowania.

2. Link źródłowy. Łączenie z rzeczywistym kodem

W niektórych przypadkach PDB mogą ukrywać pewne szczegóły kodu źródłowego ze względu na optymalizację MSIL / JIT. Więc nie jest to sposób na” wchodzenie ” rzeczywistego źródła swojej Nuget podczas debugowania. Nazywa się Source Link z .NET Foundation - „ system niezależny od języka i kontroli źródła, zapewniający środowisko debugowania kodu źródłowego dla plików binarnych ”.

Jest obsługiwany przez Visual Studio 15.3+ i wszystkich głównych dostawców (obsługuje również prywatne repozytoria).

Konfiguracja jest banalna ( oficjalna dokumentacja ) - po prostu dodaj zależność programistyczną do pliku projektu (w zależności od typu repozytorium) wraz z kilkoma flagami:

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

Więcej informacji na ten temat można znaleźć w sekcji5 kroków do ulepszenia pakietu NuGet ”.

Alex Klaus
źródło
1

Przykład w Tworzenie i publikowanie pakietu symboli odwołuje się do plików w katalogach debugowania jako źródeł plików dll i pdb.

Określanie zawartości pakietu symboli

Pakiet symboli można zbudować według konwencji, z folderu zorganizowanego w sposób opisany w poprzedniej sekcji, lub jego zawartość można określić za pomocą sekcji plików. Jeśli chcesz zbudować przykładowy pakiet opisany wcześniej, możesz umieścić to w swoim pliku 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>

Ponieważ celem publikowania symboli jest umożliwienie innym przechodzenia przez kod podczas debugowania, wydaje się najrozsądniejsze opublikowanie wersji kodu przeznaczonej do debugowania bez optymalizacji, które mogą mieć wpływ na przechodzenie kodu.

tvanfosson
źródło
Tak, to właśnie robi przykład - ale wolałbym nie skończyć z możliwością debugowania, nadpisując pragnienie większości programistów, aby po prostu uruchomić wersję wydania. Problem polega na tym, że NuGet nie ma możliwości publikowania zarówno wersji wydania, jak i kompilacji debugowania, o ile mogę powiedzieć. (Byłoby również trochę uciążliwe dla mnie opublikowanie obu, ponieważ oznacza to stworzenie kolejnego zestawu konfiguracji dla podpisanych kompilacji debugowania ...)
Jon Skeet,
Tutaj dochodzimy do małej subiektywności. Zwykle moim wyborem „najlepszej praktyki” byłoby to, co autor zaleca, wprost lub pośrednio, ponieważ zakładam, że mają większy wgląd (lub przeoczenia, w przypadku założeń, które kończą się w przykładach) niż ja. Mówiąc osobiście, Myślę, że symbole powinny pasować do wersji, której używam. Zwykle nie użyłbym pakietu, o którym myślałem, że prawdopodobnie będę musiał debugować, chyba że źródła byłyby publiczne i mógłbym w razie potrzeby skompilować od zera, więc brak spakowanej kompilacji do debugowania nie jest szczególnie ważny.
tvanfosson
W moim przypadku, jeśli ktoś musi debugować Noda Time, ponieważ wierzy, że jest błąd w Noda Time, lepiej byłoby pobrać źródło (co oczywiście może zrobić). Jednak nadal przydatna jest możliwość wejścia do kodu źródłowego Noda Time tylko po to, aby zobaczyć, co się dzieje. Zasadniczo myślę, że istnieją (przynajmniej) dwa różne scenariusze debugowania, z różnymi rozwiązaniami ...
Jon Skeet,
Jedną rzeczą, o której lubię myśleć, jest sam .NET: myślę, że można bezpiecznie powiedzieć, że Microsoft publikuje wersje wydania, a nie debuguje kompilacje .NET. Kompilacja wydania implikuje pewien poziom jakości i stabilności, więc pomysł jest taki, że rzadko trzeba będzie wkraczać w kod w celu zdiagnozowania.
gzak
2
Jednak jest to również mentalność raczej „zamkniętego źródła”. Odkryłem, że w świecie open source bardziej oczekuje się, że będzie można wejść do kodu „stabilnych wydań” różnych bibliotek nie dlatego, że coś jest zepsute, ale dlatego, że czasami najlepszą dokumentacją jest po prostu sprawdzenie, czym jest biblioteka robić.
gzak