.NET Core 3.0では、デフォルトのビルド出力がexeファイルになった。
もろもろの依存関係をまとめた単一実行可能ファイルも出力できるようになった。(前からできたかは知らない)
手順
以下実行する。
dotnet publish -r win-x64 /p:PublishSingleFile=true
または、*.csproj のPropertyGroup
に以下を追記。
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<PublishSingleFile>true</PublishSingleFile>
win-x64
の部分をlinux-x64
やosx-x64
に置き換えるとそれぞれの環境向け単一実行ファイルが出力される。
ファイルサイズについて
RuntimeIdentifier
を指定すると、ランタイムこみこみのいわゆる自己完結型(配布先に.NET Coreがインストールされていなくても動く形式)が出来上がるので、ファイルサイズが大きくなりがち。
これを削減する方法がいくつかある。
- ランタイムを含めない
- PublishTrimmedする
- サードパーティツールを使う
ランタイムを含めない
--self-contained=false
を追加してdotnet publish
すればOK
PublishTrimmed
/p:PublishTrimmed=true
を追加してdotnet publish
する。
または、*.csproj のPropertyGroup
に以下を追記。
<PublishTrimmed>true</PublishTrimmed>
サードパーティツールを使う
warp
というのがあって、PublishTrimmed
するより小さくなるらしい
ReadyToRun
.NET Core アプリケーションの起動時間を向上させる施策らしい。ファイルサイズは少し増える。
やり方は/p:PublishReadyToRun=true
を追加してdotnet publish
するか、*.csproj のPropertyGroup
に以下を追記。
<PublishReadyToRun>true</PublishReadyToRun>
ただし、基本的にはビルドプラットフォームとターゲットプラットフォームが異なる場合には使えない(今のところWindows上でLinuxのReadyToRunはできない)。
現状の単一実行可能ファイルは初回実行時にtempディレクトリにファイルを展開してから実行されるので、一回目の実行は割と起動が遅くて二回目以降から速くなる。
ReadyToRunは二回目以降の起動に効いてくると思えばよいのだろうか。
実行ファイルパス問題
上に書いたように、単一実行可能ファイルはtempディレクトリに展開され実行されるので実行パスがおかしなことになる。
例えば、実行ファイルのパスが欲しくてプログラム中でAppContext.BaseDirectory
とかしても、ファイルが展開されているtempディレクトリのパスを取得してしまう。
実行ファイルのパスは以下で取得できる。
var ExePath = Process.GetCurrentProcess().MainModule.FileName;
これはdotnet xxx.dll
で実行していた場合にはdotnet
コマンドのパスが取得できるアレですね。
参考リンク
以上