Nuget의 모범 사례 : 디버그 또는 릴리스?


92

현재, 공식 빌드 용 Nuget을 사용하여 릴리스 빌드를 nuget.org로 패키징하지만 기호 소스 푸시를 위해 Nuget을 사용하여 디버그 빌드를 symbolsource.org로 패키징합니다.

편집 : (Jon Skeet, Noda Time 개발의 편견)

NuGet은 이제 문서화 된대로 NuGet 갤러리 symbolsource.org (또는 유사한 서버)에 대한 푸시를 지원합니다 . 불행히도 여기에는 두 가지 모순되는 요구 사항이 있습니다.

  • 단지 때 사용하는 디버깅을위한 필요없이 도서관을, 당신은 정말 릴리스 빌드를 원한다. 그것이 릴리스 빌드의 목적입니다.
  • 진단 목적으로 라이브러리로 디버깅 할 때 모든 적절한 최적화가 비활성화 된 디버그 빌드를 원합니다. 이것이 바로 디버그 빌드의 목적입니다.

괜찮겠지 만 NuGet은 릴리스 및 디버그 빌드가 동일한 패키지에 유용한 방식으로 게시되도록 허용하지 않습니다.

따라서 선택 사항은 다음과 같습니다.

  • 모든 사람에게 디버그 빌드를 배포하고 (문서의 예에 표시된대로) 모든 크기 및 성능 적중률을 유지합니다.
  • 릴리스 빌드를 모든 사람에게 배포하고 약간 손상된 디버그 환경을 유지합니다.
  • 정말 복잡한 배포 정책을 따르십시오. 잠재적으로 별도의 릴리스 및 디버그 패키지를 제공합니다.

처음 두 가지는 디버그와 릴리스 빌드 간의 차이의 영향으로 요약됩니다 ... 일부 동작을 확인하고 싶어하기 때문에 라이브러리 코드에 들어가기를 원하는 것과 원하는 것 사이에 큰 차이가 있다는 점도 주목할 가치가 있습니다. 버그를 발견했다고 믿기 때문에 라이브러리의 코드를 디버깅합니다. 두 번째 경우에는 라이브러리 코드를 Visual Studio 솔루션으로 가져 와서 그런 방식으로 디버그하는 것이 더 낫기 때문에 그 상황에 너무 많은주의를 기울이지 않습니다.

내 유혹은 릴리스 빌드를 유지하는 것입니다. 상대적으로 적은 수의 사용자가 디버그해야하고, 그렇게하는 사용자는 릴리스 빌드의 최적화에 크게 영향을받지 않을 것이라는 기대를 가지고 있습니다 . (JIT 컴파일러는 어쨌든 대부분의 최적화를 수행합니다.)

그래서 우리가 고려하지 않은 다른 옵션이 있습니까? 균형을 맞추는 다른 고려 사항이 있습니까? NuGet 패키지를 SymbolSource에 푸시하여 "모범 사례"가 실제로 확립되지 않았습니까?


2
나는 약 같은 질문을했다 - 현재 내가 너무 symbolsource에 릴리스 구성을 추진하고있어 있지만, 난 그냥 사용하고 주어진 nuget pack ... -Symbol생성 된 패키지를하고 밀어 ...
존 소총

1
이 Q / A 세션을 NuGet 뒤에있는 사람들에게 제출하고 그들이 참여할 수 있는지 확인해야한다고 생각합니다.
gzak

패키지에 로그인을 굽고 릴리스 빌드 만 게시합니다. 소비자가 선호하는대로 로깅을 설정할 수 있도록 로거 주입을 허용 할 수 있습니다.
CShark

답변:


31

SymbolSource에 대해 말하면 모범 사례는 다음과 같습니다.

  1. 릴리스 바이너리 + 콘텐츠 패키지를 nuget.org에만 (또는 기타 프로덕션 피드) 푸시
  2. 디버그 바이너리 + 콘텐츠 패키지를 개발 피드로 푸시합니다.
    • 전제에
    • myget.org에서
    • nuget.org에서 시험판 패키지로.
  3. 릴리스 및 디버그 바이너리 + 심볼 패키지를 symbolsource.org 또는 다른 기호 저장소로 푸시합니다.

.NET의 릴리스 및 디버그 빌드가 실제로 많이 다르다는 것은 일반적인 오해이지만 Debug와 같이 두 빌드에 포함되거나 포함되지 않을 수있는 다양한 코드로 인해 차이점이 여기에 있다고 가정합니다. .Asserts.

즉, 프로덕션 코드를 디버깅해야 할 때를 알 수 없기 때문에 두 구성을 모두 SymbolSource에 푸시 할 가치가 있습니다. 더 어렵게 만들기 위해 프로덕션에서 원격으로. 그럴 때 툴링에서 얻을 수있는 도움이 필요할 것입니다. 나는 분명히 누구에게도 바라지 않습니다.

버전 관리와 관련하여 여전히 고려해야 할 사항이 있습니다. 2 개의 서로 다른 패키지 (디버그 및 릴리스에서 빌드)가 하나의 버전 번호를 공유하는 것이 맞습니까? SymbolSource는 패키지를 추출하고 바이너리를 별도의 빌드 모드 분기에 저장하므로 NuGet 만 그에 따라 패키지에 태그를 지정할 수있는 경우이를 허용합니다. 현재로서는 패키지가 디버그 모드인지 릴리스 모드인지 확인할 방법이 없습니다.


"NuGet에 두 빌드 게시"부분은 까다로운 부분입니다. 저는 둘 중 하나를 선택해야한다는 이유로 항상 Noda Time의 릴리스 빌드를 게시했습니다. (C # 프로젝트에서 수행하는 것이 아니라 nuspec 파일이 있습니다.) 이전의 "그들은 크게 다르지 않습니다"부분에도 불구하고 릴리스 빌드만으로는 프로덕션 코드 디버깅이 훨씬 더 어려운 것처럼 언급했습니다. 나는 디버그 빌드의 NOP를 알고 있으며 분명히 Debug.Assert등등-디버깅 할 때 의미를 확장 할 수 있습니까? 릴리스 빌드를 사용하는 것이 얼마나 나쁜가요?
Jon Skeet

내가 의미하는 바는 사용중인 모든 바이너리에 사용할 수있는 심볼을 원한다는 것입니다. 만약 디버그와 릴리스 빌드가 모두 존재한다면 둘 다에 대한 심볼을 제공하고 싶을 것입니다. 코드면에서 크게 다를 필요는 없지만 체크섬이 다르기 때문에 해킹 없이는 기호를로드 할 수 없습니다.
TripleEmcoder

1
권리. 내 가능한 해결책은 릴리스 바이너리 릴리스하는 것이지만 디버깅 측면에서 얼마나 피해를 줄지 걱정됩니다. 예를 들어, NOP가 없다는 것은 중단 점을 추가 할 수 없다는 것을 의미합니까?
Jon Skeet

문제는 빌드 시간 최적화보다 JIT 최적화에 더 있습니다. 따라서 릴리스 모드 패키지를 푸시하고 디버깅이 필요할 때 COMPLUS_ZapDisable = 1 사용을 권장한다면 저에게 충분할 것입니다. 여전히 NuGet은 어떤 방식 으로든 디버그 및 릴리스를 함께 허용해야합니다.
TripleEmcoder

나는 symbolssource.org가 존재하는지 전혀 몰랐다. 가렵기 때문에 긁을 필요가 여러 번 있었으므로 환영합니다.
Remus Rusanu 2013

4

귀하의 결론에 전적으로 동의합니다. 디버그가있는 RELEASE 및 SymbolSource가있는 NuGet 패키지. 패키지로 직접 들어가는 것은 매우 드물고 최적화가 활성화 된 상태에서 가끔 디버그 실수가 허용 될 수 있습니다.

정말 문제가 있었다면 NuGet이 지원하는 것이 이상적인 솔루션이라고 생각합니다. 예를 들어 디버깅 할 때 릴리스 DLL을 SymbolSource 패키지에 포함 된 DLL로 바꿀 수 있다고 상상해보십시오.

이상적으로 nuget pack SomePackage -Symbols는 릴리스 버전에 대해 릴리스 너겟 패키지가 생성되지만 디버그 기호 패키지는 생성됩니다. 그리고 VS 플러그인은 디버거에서 실행할 때 연결을 확인하고 디버그 어셈블리를 가져와 대신로드 할 수있을만큼 스마트하게 업데이트됩니다. 다소 미쳤지 만 흥미로울 것입니다.

하지만 지금 당장은 그럴만 한 가치가 있다고 불평하는 사람들이 많지 않습니다.

NuGet 팀은 풀 요청을 수락합니다. :)


두 번째 문장을 이해했는지 잘 모르겠습니다. OP (편집하기 전에)가 디버그 빌드를 위해 SymbolSource에 수동 푸시를 수행하고 있다고 생각합니다. 릴리스 버전의 PDB가 디버그 버전이 아닌 SymbolSource로 끝나는 경우 중요한 문제를 예상하십니까 ? 아니면 그게 당신이 옹호했던 것입니까?
Jon Skeet 2013

3
"하지만 지금 당장은 그럴만 한 가치가 있다고 불평하는 사람들이 많지 않습니다." 불평하지 않을 수도 있지만 샘플 사용자에게 이것에 대해 어떻게 생각하는지 물어 보면 대부분의 사람들이이 특정 단계 (NuGet.org 및 SymbolSource에 게시 할 내용)에서 약간의 혼란을 인정할 것입니다. .org). 그들이 무엇을 골랐는 지 물으면 합의 된 단 하나의 관행이 없다는 것을 알게 될 것입니다. 모두가 자신의 일을합니다.
gzak

7
이것에 대해 불평하고 싶습니다. 어디에서 등록해야합니까?
알렉스

내부 NuGet이 있고 기호 서버에 배포하기 시작하면 불가피하게 디버깅하고 싶을 것입니다. 코드를 단계별로 실행할 수 있지만 "University of the 지역 변수 또는 인수 ... 최적화되었습니다. " Phil이 언급했듯이 ... nuget이 디버그 모드에서 디버그 dll을로드하고 릴리스 모드에서 (nuget 패키지에서) dll을 릴리스하는 방법이 있다면 이것이 궁극적 인 방법입니다. 그때까지 우리는 Nuget 패키지 스위처를 사용합니다
felickz

1
동의합니다. 이것은 좋은 제품 향상이 될 것입니다.
htm11h

2

OP가 포스트 한 지 8 년이 되었으니 요즘 사용하는 걸로 크랙을 드리겠습니다.

NuGet 패키지 를 " 스테핑 "하는 방법에는 두 가지가 있습니다 .

1. PDB 배포

.symbols.nupkg심볼 패키지는 레거시간주되며 Symbol Server에.snupkg 게시되는 패키지 로 대체되었습니다 . NuGet.org, Azure DevOps ( 덜 부드럽 지만) 등과 같은 모든 주요 공급 업체에서 지원합니다 .

다음은 공식 지침 입니다. 다음 두 줄을 csproj 파일에 추가하기 만하면됩니다.

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

소비자 측에서는 디버깅 할 때 패키지 코드 를 실행할 수 있도록 IDE가 NuGet.org (또는 Azure 등) 기호 서버에 대해 구성되어 있는지 확인합니다 .

2. 소스 링크. 실제 코드 연결

경우에 따라 PDB는 MSIL / JIT 최적화로 인해 소스 코드의 일부 세부 사항을 숨길 수 있습니다. 따라서 디버깅하는 동안 NuGet의 실제 소스에 " 단계적 으로" 들어가는 방법이 있습니다. 그것은라고 원본 링크를 닷넷 재단 - " 소스 바이너리에 대한 경험을 디버깅을 제공하는 language- 및 소스 제어 불가지론 시스템 ".

Visual Studio 15.3 이상 및 모든 주요 공급 업체에서 지원합니다 (개인 리포지토리도 지원).

설정하는 것은 간단합니다 ( 공식 문서 ) – 일부 플래그와 함께 프로젝트 파일에 개발 종속성을 추가합니다 (repo 유형에 따라 다름).

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

" NuGet 패키지를 개선하기위한 5 단계 "에서이 주제에 대해 자세히 알아보십시오 .


1

심볼 패키지 생성 및 게시 의 예제 는 디버그 디렉토리의 파일을 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에 릴리스 및 디버그 빌드를 모두 게시 할 수있는 방법이 없다는 것입니다. (이 구성의 또 다른 세트를 생성 의미로 서명 디버그 빌드하는 것도 ..., 나 모두를 게시 할 수있는 약간의 고통이 될 것입니다)
존 소총

여기서 우리는 약간의 주관성에 대해 알아 봅니다. 일반적으로 "모범 사례"에 대한 나의 선택은 저자가 명시 적으로 또는 묵시적으로 권장하는 것입니다. 왜냐하면 나는 그들이 I보다 더 많은 통찰력 (또는 예에서 끝나는 가정의 경우 감독)을 가지고 있다고 가정하기 때문입니다. 기호가 사용중인 버전과 일치해야한다고 생각합니다. 일반적으로 소스가 공개되어 있고 필요한 경우 처음부터 컴파일 할 수있는 경우가 아니면 디버그해야 할 것으로 생각되는 패키지를 사용하지 않으므로 패키지화 된 디버그 빌드의 부족은 특별히 중요하지 않습니다.
tvanfosson

제 경우에는 누군가가 Noda Time에 버그가 있다고 믿기 때문에 Noda Time을 디버깅해야한다면 소스를 다운로드하는 것이 좋습니다 (물론 할 수 있습니다). 그러나 Noda Time 소스 코드로 들어가서 무슨 일이 일어나고 있는지 확인하는 것은 여전히 ​​유용합니다. 기본적으로 생각이 서로 다른 솔루션과 디버깅을위한 두 개의 서로 다른 시나리오, (적어도) ...
존 소총

제가 생각하고 싶은 한 가지는 .NET 자체입니다. Microsoft가 .NET의 디버그 빌드가 아니라 릴리스 빌드를 게시한다고 말하는 것이 안전하다고 생각합니다. 릴리스 빌드는 특정 수준의 품질과 안정성을 의미하므로 문제를 진단하기 위해 코드를 입력 할 필요가 거의 없다는 아이디어가 있습니다.
gzak

2
그러나 그것은 또한 다소 "닫힌 소스"사고 방식입니다. 나는 오픈 소스 세계에서 다양한 라이브러리의 "안정된 릴리스"코드에 들어갈 수있을 것으로 더 기대되는 것을 발견했습니다. 하기.
gzak
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.