Práticas recomendadas com Nuget: Depurar ou liberar?

89

Atualmente, empacoto as compilações de lançamento com Nuget para as compilações oficiais em nuget.org, mas empacoto as compilações de depuração com Nuget para os envios de fonte de símbolo para symbolsource.org.

EDITAR: (Jon Skeet, com algum viés do desenvolvimento da Noda Time)

O NuGet agora oferece suporte para envio à galeria do NuGet e aos symbolsource.org (ou servidores semelhantes), conforme documentado . Infelizmente, existem dois requisitos contraditórios aqui:

  • Ao usar uma biblioteca sem qualquer necessidade de depuração, você realmente deseja uma versão de lançamento. Afinal, é para isso que servem as versões de lançamento.
  • Ao depurar em uma biblioteca para fins de diagnóstico, você realmente deseja uma compilação de depuração com todas as otimizações apropriadas desabilitadas. Afinal, é para isso que servem as compilações de depuração.

Isso seria ótimo, mas o NuGet não permite (até onde eu sei) permite que as compilações de lançamento e depuração sejam publicadas de uma maneira útil, no mesmo pacote.

Então, as opções são:

  • Distribua as compilações de depuração para todos (conforme mostrado no exemplo nos documentos) e viva com qualquer tamanho e desempenho.
  • Distribua as compilações de lançamento para todos e viva com uma experiência de depuração ligeiramente prejudicada.
  • Escolha uma política de distribuição realmente complicada, potencialmente fornecendo pacotes separados de lançamento e depuração.

Os dois primeiros realmente se resumem ao efeito das diferenças entre as compilações de depuração e de lançamento ... embora seja importante notar que também há uma grande diferença entre querer entrar no código de uma biblioteca porque você deseja verificar algum comportamento e querer para depurar o código de uma biblioteca porque você acredita que encontrou um bug. No segundo caso, provavelmente é melhor pegar o código da biblioteca como uma solução do Visual Studio e depurar dessa forma, então não estou prestando muita atenção nessa situação.

Minha tentação é apenas continuar com os builds de lançamento, com a expectativa de que relativamente poucas pessoas precisarão depurar, e aqueles que precisam não serão muito afetados pelas otimizações no build de lançamento. (O compilador JIT faz a maior parte da otimização de qualquer maneira.)

Então, há outras opções que não consideramos? Existem outras considerações que fazem pender a balança? O envio de pacotes NuGet para a SymbolSource é suficientemente novo para que as "melhores práticas" não tenham sido estabelecidas?

gzak
fonte
2
Eu estava prestes a fazer a mesma pergunta - embora atualmente esteja empurrando a configuração do Release para a fonte de símbolos também, visto que estou apenas usando nuget pack ... -Symbole empurrando os pacotes gerados ...
Jon Skeet
1
Sinto que devo enviar esta sessão de perguntas e respostas para o pessoal por trás do NuGet e ver se eles podem opinar sobre isso.
gzak
Faça o login no seu pacote e publique apenas a versão de lançamento. Você pode permitir a injeção de logger, que permitirá ao consumidor configurar o log de acordo com suas preferências.
CShark de

Respostas:

29

Falando pela SymbolSource, acredito que a prática recomendada é:

  1. Envie pacotes binários de lançamento + conteúdo apenas para nuget.org (ou qualquer outro feed de produção)
  2. Envie pacotes binários de depuração + conteúdo para um feed de desenvolvimento:
    • na premissa
    • em myget.org
    • em nuget.org como pacotes de pré-lançamento.
  3. Envie os pacotes de símbolos binários de liberação e depuração para symbolsource.org ou qualquer outro armazenamento de símbolos.

Enquanto estamos nisso, é um equívoco comum que as compilações de lançamento e depuração no .NET realmente diferem muito, mas estou assumindo que a diferenciação está aqui por causa de vários códigos que podem ou não estar incluídos em qualquer uma das compilações, como Debug .Avaliações.

Dito isso, realmente vale a pena enviar ambas as configurações para o SymbolSource, porque você nunca sabe quando precisará depurar o código de produção. Remotamente em produção para torná-lo mais difícil. Você precisará da ajuda que poderá obter com seu ferramental quando isso acontecer. O que obviamente não desejo a ninguém.

Ainda há uma questão a considerar em relação ao controle de versão: é correto ter 2 pacotes diferentes (compilados na depuração e na versão) compartilhando 1 número de versão? SymbolSource aceitaria isso, porque extrai pacotes e armazena binários em ramos de modo de compilação separados, SE SÓ o NuGet tiver permissão para marcar os pacotes de acordo. No momento, não há como determinar se um pacote está em modo de depuração ou de lançamento.

TripleEmcoder
fonte
A parte "publicar duas compilações no NuGet" é a parte complicada. Eu sempre publiquei a versão de lançamento do Noda Time, alegando que eu tinha que escolher entre os dois. (Eu tenho um arquivo nuspec, em vez de fazer apenas do projeto C #.) Você menciona a depuração do código de produção como se isso fosse significativamente mais difícil com apenas uma versão de lançamento - apesar da parte anterior "eles não diferem muito". Estou ciente dos NOPs em compilações de depuração e, obviamente, Debug.Assertetc - mas você poderia expandir (em sua resposta) as implicações durante a depuração? Quão ruim é usar uma versão Release?
Jon Skeet
O que eu quis dizer é apenas que você deseja ter símbolos disponíveis para todos os binários em uso: se houver compilações de depuração e de lançamento no wild, você desejará fornecer símbolos para ambos. Eles não precisam ser muito diferentes em termos de código, mas serão diferentes em somas de verificação, o que torna o carregamento de símbolos impossível sem algum hacking.
TripleEmcoder 01 de
1
Certo. Minha solução possível é lançar apenas os binários do Release, mas estou preocupado com o quanto isso vai prejudicar em termos de depuração. Por exemplo, a falta de NOPs significa que você não pode adicionar pontos de interrupção?
Jon Skeet
O problema está mais nas otimizações JIT do que nas otimizações de tempo de construção. Portanto, se você enviar pacotes de modo de lançamento e recomendar o uso de COMPLUS_ZapDisable = 1 quando a depuração for necessária, isso seria bom o suficiente para mim. Ainda assim, o NuGet deve permitir depurar e liberar juntos de alguma forma.
TripleEmcoder
Eu não fazia ideia da existência de symbolssource.org. Como uma coceira que muitas vezes tive necessidade de coçar, eu acolho isso.
Remus Rusanu
4

Eu concordo totalmente com sua conclusão. Pacotes NuGet com RELEASE e SymbolSource com depuração. Parece muito raro entrar diretamente em pacotes e o erro ocasional de depuração com otimizações habilitadas pode ser aceitável.

Se realmente houvesse um problema, acho que a solução ideal seria ter o suporte do NuGet. Por exemplo, imagine se, durante a depuração, ele pudesse substituir a DLL de lançamento pela incluída no pacote SymbolSource.

Idealmente, o que aconteceria então é que nuget pack SomePackage -Symbolscontra uma versão de lançamento criaria um pacote nuget de lançamento, mas um pacote de símbolos de depuração. E o plug-in VS seria atualizado para ser inteligente o suficiente para ver a associação e extrair os assemblies de depuração ao ser executado em um depurador e carregá-los. Meio louco, mas seria interessante.

No entanto, eu simplesmente não vejo pessoas reclamando sobre isso para que valha a pena no momento.

A equipe do NuGet aceita solicitações pull. :)

Haacked
fonte
Não tenho certeza se entendi sua segunda frase - suspeito que o OP (antes de eu editar) estava fazendo push manuais para SymbolSource para as compilações de depuração. Você prevê problemas significativos se o PDB da versão de lançamento acabar no SymbolSource em vez da versão de depuração? Ou é isso que você estava defendendo e eu simplesmente não entendi?
Jon Skeet
3
"No entanto, não vejo gente suficiente reclamando sobre isso para que valha a pena no momento." Talvez eles não estejam reclamando, mas se você perguntasse a uma amostra de usuários o que eles achavam disso, aposto que descobriria que a maioria das pessoas admitiria um pouco de confusão nesta etapa específica (o que publicar no NuGet.org e SymbolSource .org). Se você perguntasse o que eles acabaram escolhendo, provavelmente descobrirá que não há uma prática única acordada, cada um apenas faz suas próprias coisas.
gzak
7
Quero reclamar disso, onde me inscrevo?
Alex,
Depois de ter NuGets internos e começar a implantá-los em um servidor de símbolo ... inevitavelmente, você vai querer depurá-los ... e mesmo que possa percorrer o código, acabará com "Não é possível obter o valor do variável local ou argumento ... foi otimizado ". Como Phil menciona ... SE o nuget tivesse uma maneira de carregar dlls de depuração no modo de depuração e liberar dlls no modo de liberação (de pacotes nuget), isso seria o máximo. Até então, estamos presos com switcher de pacotes Nuget
felickz
1
Eu concordo, isso seria um bom aprimoramento do produto.
htm11h
1

O exemplo em Criando e publicando um pacote de símbolos faz referência a arquivos nos diretórios de depuração como fontes para os arquivos dll e pdb.

Especificando o conteúdo do pacote de símbolos

Um pacote de símbolos pode ser construído por convenções, a partir de uma pasta estruturada da maneira descrita na seção anterior, ou seu conteúdo pode ser especificado usando a seção de arquivos. Se você quiser construir o pacote de exemplo descrito anteriormente, pode colocá-lo em seu arquivo 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>

Visto que o propósito de publicar os símbolos é permitir que outros percorram seu código durante a depuração, parece mais prudente publicar uma versão do código destinada à depuração sem otimizações que possam afetar a etapa de código.

Tvanfosson
fonte
Sim, é isso que o exemplo faz - mas prefiro não acabar com a capacidade de depurar substituindo o desejo da maioria dos desenvolvedores de apenas executar a versão de lançamento. O problema é que o NuGet não tem uma maneira de publicar compilações de lançamento e depuração, pelo que eu posso dizer. (Também seria uma pequena dor para mim publicar ambos, pois isso significa criar mais um conjunto de configurações, para compilações de depuração assinadas ...)
Jon Skeet
Aqui entramos em um pouco de subjetividade. Normalmente, minha escolha de "melhor prática" seria aquela que o autor recomenda, explícita ou implicitamente, porque presumo que eles têm mais insight (ou supervisão, no caso de suposições que terminam em exemplos) do que eu. Acho que os símbolos devem corresponder à versão que estou usando. Eu normalmente não usaria um pacote que achasse que teria que depurar, a menos que o código-fonte fosse público e eu pudesse compilar do zero se necessário, então a falta de um pacote de compilação de depuração não é particularmente importante.
tvanfosson
No meu caso, se alguém precisar depurar o Noda Time porque acredita que há um bug no Noda Time, seria melhor baixar o código-fonte (o que eles podem fazer, é claro). No entanto, ainda é útil ser capaz de entrar no código-fonte do Noda Time apenas para ver o que está acontecendo. Basicamente, eu acho que existem (pelo menos) dois cenários diferentes para depuração, com soluções diferentes ...
Jon Skeet
Uma coisa que gosto de pensar é o próprio .NET: acho que é seguro dizer que a Microsoft publica compilações de lançamento e não compilações de depuração do .NET. Uma versão de versão implica um certo nível de qualidade e estabilidade, portanto, a ideia é que raramente você precisará entrar no código para diagnosticar coisas.
gzak
2
No entanto, essa também é uma mentalidade de "fonte fechada". Eu descobri que no mundo do código aberto, é mais esperado ser capaz de entrar no código de "versões estáveis" de várias bibliotecas, não porque as coisas estão quebradas, mas porque às vezes a melhor documentação é apenas ver o que a biblioteca é fazendo.
gzak