출처: https://devadjust.exblog.jp/27784413/

.NET Core 3.0 단일 실행 파일 생성

.NET Core 3.0의 새로운 기능인 "단일 실행 파일 생성"을 이용하면 발급 대상 폴더에 단 하나 뿐인 실행 파일이 생성되어, 배포 등의 취급이 쉬워진다 .

(또한 본 기능의 작동 원리는 비유하자면 tar와 비슷한 류의 "아카이브"으로 필요한 .dll 파일들을 단일 실행 파일에 수록하고 있는 것 같다)

지금도 ILMerge와 ILRepack 등, .NET 플랫폼의 바이너리를 단일 파일에 정리하는 방법과 도구는 존재하고 있었다.

하지만 .NET Core SDK 본체에 유사한 기능이 기본으로 탑재되어 있어 바로 사용할 수 있는 점은 매우 편리하다.

Windows OS에서 Visual Studio 2019을 사용한 개발 체제에서 "단일 실행 파일 생성"을 실제로 시험해 보았다.

우선 작동을 확인

Visual Studio 2019 프로젝트 템플릿에서 .NET Core 콘솔 응용 프로그램을 생성한다.

"Hello World"를 표시만 하는 C# 프로그램이다.

그리고 아래 기사를 참고로 .csproj 파일에 두 줄 추가해 본다.

https://docs.microsoft.com/ko-kr/dotnet/core/whats-new/dotnet-core-3-0#single-file-executables

<Project Sdk="Microsoft.NET.Sdk">
 <PropertyGroup>
   <OutputType>Exe</OutputType>
   <TargetFramework>netcoreapp3
.0</TargetFramework>
   
<PublishSingleFile>true</PublishSingleFile>
   <RuntimeIdentifier>win10-x64</RuntimeIdentifier>

 </PropertyGroup>
</Project>

빌드하고 실행 해 본다.

계속해서, 드디어 발행이다.

Visual Studio 2019에서 개발 작업한 것으로, Visual Studio 상에서 폴더로의 발행 프로파일을 작성(아래) 발행을 실행.

무사히 발행되고 대상은 .exe 파일이 하나만 생성되었다.(실행 환경에 64bit Windows10 OS를 지정하고 있기 때문에 생성된 실행 파일은 확장명이 .exe 인 PE 파일이다.)

또한, 겨우 "Hello World"만 표시하는 콘솔 응용 프로그램이지만, 실행 파일의 크기는 65.8MB나 되어 버렸다.

아무튼, 대상 런타임이 휴대용이 아닌, 또한, 배치 모드가 자기 완결(Self-Contained)의 발행 결과물을, 압축하지 않고 보관하고 있기 때문이다.

다른 OS 용으로도 발행 할 수 있다

.NET Core 라고하면 크로스 플랫폼이다.

위 프로젝트, 예를 들면 64bit Linux 용 단일 실행 파일을 실행하려면 어떻게해야 할까?

이것은 어렵지 않다.

그저 단순히 대상 런타임으로 "linux-64"을 지정한 발행 프로필을 작성하고, 이 발행 프로필에서 발행하면 될 뿐이다

발행 프로필에 지정

"단일 실행 파일 생성의 지정은 프로젝트 파일(.csproj)을 쓰지 않는다. 대신 발행 프로필 (.pubxml)에 쓴다."

Visual Studio에서 개발하고 있는 발행 프로파일은 이 실태는 Properties 폴더 아래에 배치된 확장자 .pubxml 파일이며 (아래 그림) 프로젝트 파일 (.csproj)에 대한 차분이다.

우선 .csproj 파일에서 방금 추가한 단일 실행 파일 생성 및 대상 런타임 지정 두 줄을 삭제하고 원래대로 되돌린다.

<Project Sdk="Microsoft.NET.Sdk">
 <PropertyGroup>
   <OutputType>Exe</OutputType>
   <TargetFramework>netcoreapp3
.0</TargetFramework>
 </PropertyGroup>
</Project>

그럼 먼저 작성했던 발행 프로필(Visual Studio의 발행 프로필 편집 GUI를 통하지 않고) 에디터로 열어 직접 편집하고 "<PublishSingleFile> true </ PublishSingleFile>" 줄을 추가한다.

(※ 대상 런타임 지정 ( "<RuntimeIdentifier> ~ </ RuntimeIdentifier>")은 이미 포함되어 있어야한다.)

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion=
"4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <PropertyGroup>
   ...
   <RuntimeIdentifier>win10-x64</RuntimeIdentifier>
   
<PublishSingleFile>true</PublishSingleFile> <!-- ← 이것을 추가 -->
 </PropertyGroup>
</Project>

이상으로 OK이다.

이제 이 프로젝트는 어떤 OS에서도 대상 런타임 = 포터블용으로 빌드 디버그 실행된다.

이 위에, 상기 발행 프로필을 사용하여 발행하면, 64bit Windows 10에서 직접 실행 가능한 (.NET Core Runtime의 사전 설치도 불필요) 단일 파일의 실행 파일을 얻을 수 있다.

물론 다른 OS에 발행 프로필을 변경하거나 발행 프로필을 추가 ​​할 수 있다.

보충 1 - dotnet CLI에서 개발 시

처음에 나타낸 공식 문서를 보면 dotnet CLI를 사용하는 경우 dotnet CLI 실행 시 명령 줄 인수에,  대상 런타임 지정 및 단일 실행 파일 생성 지정을하는 방법이 설명되어 있다(아래 예 ).

> dotnet publish -r win10-x64 /p:PublishSingleFile=true

이와 같이, 역시 프로젝트 파일에서 단일 실행 파일 생성 지정하지 않고, 발급 시 개별적으로 단일 실행 파일 생성의 지정을 행하는(이 예에서 말하면, dotnet CLI 명령 줄 인수로 지정 하는) 것이 좋을 듯하다.

또한 dotnet CLI를 사용한 경우에도 다음 요령으로 이번에 설명한 것처럼 발행 프로파일을 이용한 발행을 할 수 있다.

dotnet publish /p:PublishProfile=<여기에.pubxml 파일의 path>

보충 2 - Visual Studio 2019의 발행 프로필 편집 GUI가 좀 이상하다

Visual Studio 2019의 발행 프로필 편집 GUI 디스플레이에서는 배치 모드가 "프레임 워크 의존"이라고 표시되고 있다.

그러나 실제로 발행되는 내용은 배치 모드 = "독립적"(Self-Contained) 내용으로 되어 있다.

사실 이것은 대상 런타임 지정(RuntimeIdentifier)가 지정 되어 있는 경우, 배치 모드가 명시 적으로 설정 되어 있지 않으면 아무래도 빌드 스크립트에서는 배치 모드의 기본값은 "프레임 워크 의존 '에서 '자기 완결 "로 전환하고 있는 것 같다.

다만, 이 빌드 스크립트의 사양이 Visual Studio 2019의 발행 프로필 편집 GUI에 반영되지 않은 것, 즉 Visual Studio 2019의 발행 프로필 편집 GUI는 배치 모드 지정이 명시적으로 설정되어 있지 않은 경우는 "프레임 워크 의존"이라고 표시되는 것 같다.

이러한 혼란을 방지하려면 배치 모드 지정을 발행 프로필에 명시해 버리면 된다.

    ...
   <SelfContained>
true</SelfContained> <!-- ← 여기를 명시적으로 -->
 </PropertyGroup>
</Project>

또는 Visual Studio 2019의 발행 프로필 편집 GUI에서 배치 모드를 명시적으로 '자기완결'로 다시 선택 두어도 OK 다.

이렇게 항상 배치 모드 지정을 명시적으로 설정 두도록 하면 불필요한 혼란을 피할 수 있다.

또한 반대로 배치 모드를 "프레임 워크 의존"로 명시적으로 설정하여 단일 실행 파일 생성 지정에 발행하면 어떻게 될까?

그러면 OS에 별도 .NET Core 런타임을 사전 설치해야 되지만, 크기가 아주 작게 되는, 단일 실행 파일이 발급 대상으로 생성된다.

정리

단일 실행 파일 생성은 이 기능의 특성상 대상 런타임의 지정이 필수이다.

따라서 단일 실행 파일 생성 지정은 프로젝트 파일에 기입하는 것이 아니라 발행 프로필을 작성하여 두는 것을 나는 추천한다.