Лучшие практики с Nuget: отладка или выпуск?

92

В настоящее время я упаковываю сборки выпуска с помощью Nuget для официальных сборок на nuget.org, но я упаковываю сборки отладки с помощью Nuget для того, чтобы источник символов отправлял символы на symbolsource.org.

РЕДАКТИРОВАТЬ: (Джон Скит, с некоторым предубеждением от разработки Noda Time)

NuGet теперь поддерживает отправку как в галерею NuGet, так и в symbolsource.org (или аналогичные серверы), как описано в документации . К сожалению, здесь есть два противоречащих друг другу требования:

  • Когда вы просто используете библиотеку без необходимости отладки, вам действительно нужна сборка выпуска. В конце концов, для этого и нужны релизные сборки.
  • При отладке в библиотеку для диагностических целей вам действительно нужна отладочная сборка с отключенными всеми соответствующими оптимизациями. В конце концов, для этого и нужны отладочные сборки.

Это было бы хорошо, но NuGet не позволяет (насколько я могу судить) публиковать как релизную, так и отладочную сборки полезным способом в одном пакете.

Итак, варианты:

  • Распространяйте отладочные сборки для всех (как показано в примере в документации) и работайте с любым размером и падением производительности.
  • Распространите сборки релиза среди всех и живите с немного ослабленным опытом отладки.
  • Используйте действительно сложную политику распространения, потенциально предоставляя отдельные пакеты выпуска и отладки.

Первые два на самом деле сводятся к влиянию различий между отладочной и выпускной сборками ... хотя стоит отметить, что есть большая разница между желанием войти в код библиотеки, потому что вы хотите проверить какое-то поведение, и желанием для отладки кода библиотеки, потому что вы считаете, что нашли ошибку. Во втором случае, вероятно, лучше получить код библиотеки как решение Visual Studio и отладить таким образом, поэтому я не обращаю слишком много внимания на эту ситуацию.

У меня есть искушение просто придерживаться релизных сборок, ожидая, что отладку потребуется относительно небольшому количеству людей, а на тех, кто это сделает, оптимизация релизной сборки не сильно повлияет . (В любом случае компилятор JIT выполняет большую часть оптимизации.)

Итак, есть ли другие варианты, которые мы не рассматривали? Есть ли другие соображения, которые склоняют чашу весов? Является ли размещение пакетов NuGet в SymbolSource достаточно новым, чтобы действительно не было «лучших практик»?

гзак
источник
2
Я собирался задать тот же вопрос - хотя в настоящее время я также отправляю конфигурацию Release в источник символов, учитывая, что я просто использую nuget pack ... -Symbolи отправляю сгенерированные пакеты ...
Джон Скит
1
Я чувствую, что должен отправить этот сеанс вопросов / ответов людям, стоящим за NuGet, и посмотреть, смогут ли они высказать свое мнение.
gzak 02
Запеките вход в свой пакет, а затем опубликуйте только сборку выпуска. Вы можете разрешить внедрение регистратора, что позволит потребителю настроить ведение журнала в соответствии с его / ее предпочтениями.
CShark

Ответы:

31

Говоря о SymbolSource, я считаю, что лучше всего:

  1. Отправка бинарных пакетов выпуска и пакетов содержимого только на сайт nuget.org (или в любой другой рабочий канал)
  2. Отправьте отладочные двоичные пакеты + содержимое в канал разработки:
    • на месте
    • на myget.org
    • на nuget.org в виде предварительных пакетов.
  3. Отправьте пакеты двоичных символов + выпуска и отладки на сайт symbolsource.org или любое другое хранилище символов.

В то время как мы находимся на этом, распространено заблуждение, что сборки выпуска и отладки в .NET действительно сильно различаются, но я предполагаю, что различие здесь из-за различного кода, который может или не может быть включен в любую сборку, например Debug .Asserts.

Тем не менее, действительно стоит передать обе конфигурации в SymbolSource, потому что вы просто никогда не знаете, когда вам понадобится отлаживать производственный код. Удаленно в производстве, чтобы усложнить задачу. Когда это произойдет, вам понадобится помощь, которую вы можете получить от своих инструментов. Чего я, очевидно, никому не желаю.

Есть еще вопрос, который следует учитывать в отношении управления версиями: правильно ли иметь 2 разных пакета (сборка в отладке и в выпуске) с общим номером версии? SymbolSource согласится с этим, поскольку он извлекает пакеты и сохраняет двоичные файлы в отдельных ветвях режима сборки, ЕСЛИ ТОЛЬКО NuGet позволяет помечать пакеты соответствующим образом. В настоящее время нет способа определить, находится ли пакет в режиме отладки или в режиме выпуска.

TripleEmcoder
источник
Часть «Публикация двух сборок в NuGet» - это сложный момент. Я всегда публиковал релизную сборку Noda Time на том основании, что мне приходилось выбирать между ними. (У меня есть файл nuspec, а не только из проекта C #.) Вы упоминаете отладку производственного кода, как если бы это было значительно сложнее только с выпускной сборкой - несмотря на предыдущую часть «они не сильно отличаются». Я знаю о NOP в отладочных сборках и, очевидно, и Debug.Assertт.д., но не могли бы вы рассказать (в своем ответе) о последствиях при отладке? Насколько плохо использовать сборку Release?
Джон Скит,
Я имел в виду только то, что вы хотите, чтобы символы были доступны для всех используемых двоичных файлов: если в дикой природе есть как отладочная, так и выпускная сборки, вы захотите предоставить символы для обоих. Они не должны сильно различаться с точки зрения кода, но они будут отличаться контрольными суммами, что делает невозможной загрузку символов без некоторого взлома.
TripleEmcoder 01
1
Правильно. Мой возможным решением является только когда - либо выпустить двоичные файлы Release, но я беспокоился о том, сколько это будет больно с точки зрения отладки. Например, означает ли отсутствие NOP вы не можете добавлять точки останова?
Джон Скит,
Проблема больше связана с оптимизацией JIT, чем с оптимизацией времени сборки. Поэтому, если вы отправляете пакеты в режиме выпуска и рекомендуете использовать COMPLUS_ZapDisable = 1, когда требуется отладка, этого было бы достаточно для меня. Тем не менее, NuGet должен каким-то образом разрешать отладку и выпуск вместе.
TripleEmcoder 01
Я понятия не имел, что существует symbolssource.org. Как зуд у меня много раз было желание почесаться, я приветствую это.
Ремус Русану
4

Полностью согласен с вашим выводом. Пакеты NuGet с RELEASE и SymbolSource с отладкой. Кажется, довольно редко входить непосредственно в пакеты, и случайные ошибки отладки с включенной оптимизацией могут быть приемлемыми.

Если бы действительно была проблема, я думаю, что идеальным решением было бы, чтобы NuGet поддерживал ее. Например, представьте, если бы при отладке он мог заменить выпускаемую DLL библиотекой, включенной в пакет SymbolSource.

В идеале в таком nuget pack SomePackage -Symbolsслучае вместо версии выпуска должен быть создан пакет nuget выпуска, но пакет символов отладки. И плагин VS будет обновлен, чтобы быть достаточно умным, чтобы видеть ассоциацию и извлекать сборки отладки при запуске в отладчике и загружать их вместо этого. Вроде безумно, но было бы интересно.

Однако я просто не вижу достаточно людей, которые жалуются на это, чтобы это того стоило на данный момент.

Команда NuGet принимает запросы на вытягивание. :)

Haacked
источник
Я не уверен, что понимаю ваше второе предложение - я подозреваю, что OP (до того, как я отредактировал) вручную нажимал на SymbolSource для отладочных сборок. Предвидите ли вы существенные проблемы, если PDB версии релиза окажется в SymbolSource вместо отладочной версии? Или это то, за что вы выступали, а я просто неправильно понял?
Джон Скит,
3
«Однако я просто не вижу достаточно людей, которые жалуются на это, чтобы это того стоило на данный момент». Возможно, они не жалуются, но если вы спросите некоторых пользователей, что они думают об этом, держу пари, вы обнаружите, что большинство людей допускают небольшую путаницу на этом конкретном этапе (что публиковать на NuGet.org и SymbolSource .org). Если вы спросите, что они в итоге выбрали, вы, вероятно, обнаружите, что нет единой согласованной практики, каждый просто делает свое дело.
gzak
7
Я хочу пожаловаться на это, где мне зарегистрироваться?
Alex
Как только у вас есть внутренние NuGet и вы начнете развертывать их на сервере символов ... вам неизбежно захочется их отлаживать ... и даже если вы можете пройти через код, вы получите сообщение «Невозможно получить значение локальная переменная или аргумент ... он был оптимизирован ". Как упоминает Фил ... ЕСЛИ у nuget был способ загружать отладочные dll в режиме отладки и выпускать dll в режиме выпуска (из пакетов nuget), это было бы окончательным. А пока мы застряли на переключателе пакетов
Nuget
1
Я согласен, это было бы неплохим усовершенствованием продукта.
htm11h
2

Прошло 8 лет с момента публикации OP, поэтому я расскажу о том, что используется в настоящее время.

Есть 2 способа « войти » в пакет NuGet:

1. Распространение PDB

.symbols.nupkgПакеты символов считаются устаревшими и были заменены .snupkgпакетами, которые публикуются на сервере символов . Он поддерживается всеми основными поставщиками, такими как NuGet.org, Azure DevOps ( хотя и менее гладко ) и т. Д.

Вот официальные инструкции . Просто добавьте эти две строки в файл csproj:

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

На стороне потребителя убедитесь, что ваша IDE настроена для сервера символов NuGet.org (или Azure и т. Д.), Чтобы разрешить переход в код пакета при отладке.

2. Ссылка на исходный код. Ссылка на фактический код.

В некоторых случаях PDB могут скрывать некоторые особенности исходного кода из-за оптимизации MSIL / JIT. Таким образом, есть способ « зайти » в фактический источник вашего NuGet во время отладки. Это называется Source Link от .NET Foundation - « независимая от языка и управления исходным кодом система для обеспечения возможности отладки исходного кода для двоичных файлов ».

Он поддерживается Visual Studio 15.3+ и всеми основными поставщиками (также поддерживает частные репозитории).

Это тривиально для настройки ( официальная документация ) - просто добавьте зависимость разработки в файл проекта (зависит от типа вашего репо) вместе с некоторыми флагами:

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

Подробнее об этом читайте в статье « 5 шагов к лучшему пакету NuGet ».

Алекс Клаус
источник
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>

Поскольку цель публикации символов состоит в том, чтобы позволить другим пройти через ваш код при отладке, кажется наиболее разумным опубликовать версию кода, предназначенную для отладки, без оптимизаций, которые могут повлиять на выполнение кода.

tvanfosson
источник
Да, это то, что делает пример , но я бы предпочел не заканчивать с возможностью отладки, отменяя желание большинства разработчиков просто запустить выпускную версию. Проблема в том, что NuGet не может публиковать как выпускные, так и отладочные сборки, насколько я могу судить. (Мне также было бы немного сложно опубликовать оба, поскольку это означает создание еще одного набора конфигураций для подписанных отладочных сборок ...)
Джон Скит
Здесь мы немного поговорим о субъективности. Как правило, мой выбор в качестве «наилучшей практики» - это то, что автор рекомендует явно или неявно, потому что я предполагаю, что они обладают большей проницательностью (или надзором, в случае предположений, которые приводятся в примерах), чем я. Говоря лично, Я думаю, символы должны соответствовать той версии, которую я использую. Обычно я бы не стал использовать пакет, который, как я думал, мне, вероятно, придется отлаживать, если только исходный код не был общедоступным и я мог бы при необходимости скомпилировать с нуля, поэтому отсутствие упакованной отладочной сборки не особенно важно.
tvanfosson 01
В моем случае, если кому-то нужно отлаживать Noda Time, потому что они считают, что в Noda Time есть ошибка, им лучше загрузить исходный код (что они, конечно, могут сделать). Тем не менее, по-прежнему полезно иметь возможность войти в исходный код Noda Time, чтобы просто посмотреть, что происходит. По сути, я думаю, что есть (по крайней мере) два разных сценария отладки с разными решениями ...
Джон Скит,
Одна вещь, о которой мне нравится думать, - это сама .NET: я думаю, можно с уверенностью сказать, что Microsoft публикует сборки выпуска, а не отлаживает сборки .NET. Релизная сборка подразумевает определенный уровень качества и стабильности, поэтому идея заключается в том, что вам редко нужно вмешиваться в код для диагностики.
gzak 02
2
Однако это тоже скорее менталитет «закрытого кода». Я обнаружил, что в мире с открытым исходным кодом более ожидаемо иметь возможность войти в код «стабильных выпусков» различных библиотек не потому, что что-то сломано, а потому, что иногда лучшая документация - просто посмотреть, что это за библиотека делаю.
gzak 02