mcpField
D
dotnet-cli-distribution

dotnet-cli-distribution

github.com/wshaddix開発8674 回インストール35 週間前に更新
リポジトリ

dotnet-cli-distribution について

.NET CLI 開発者向けに、Native AOT、フレームワーク依存のデプロイ、dotnet tool の配布方式を選ぶためのガイドです。クロスプラットフォームの RID 計画、単一ファイル発行、バイナリサイズの最適化、リリース用チェックサムも扱います。

主な機能

  1. 01CLI の配布方式を比較
  2. 02クロスプラットフォームの RID を計画
  3. 03単一ファイル発行を設定
  4. 04発行バイナリのサイズを削減
  5. 05リリース用チェックサムを生成

活用シーン

  1. 01CLI のデプロイ方式を選択
  2. 02クロスプラットフォームのビルド対象を決定
  3. 03自己完結型リリースのサイズを削減
  4. 04検証可能なリリース成果物を準備

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/wshaddix/dotnet-skills --skill dotnet-cli-distribution

インストール後、Claude Code で/dotnet-cli-distributionを入力して読み込まれたか確認します。

詳細

dotnet-cli-distribution

.NET ツールの CLI 配布戦略:Native AOT の単一ファイル発行、フレームワーク依存のデプロイ、dotnet tool パッケージングから選択します。クロスプラットフォームのターゲット(linux-x64、osx-arm64、win-x64、linux-arm64)に向けたランタイム識別子(RID)マトリックスの計画、単一ファイル発行の構成、CLI アプリケーションのバイナリサイズ最適化手法について説明します。

バージョンの前提条件: .NET 8.0 以降を基準とします。コンソールアプリの Native AOT は、.NET 8 以降で完全にサポートされています。単一ファイル発行は .NET 6 以降で成熟しています。

対象外: Native AOT の MSBuild 構成(PublishAot、ILLink 記述子、EnableAotAnalyzer、トリミング)については、[skill:dotnet-native-aot] を参照してください。AOT を優先するアプリケーション設計パターン(リフレクションよりソースジェネレーターを優先する方法、DI の選択)については、[skill:dotnet-aot-architecture] を参照してください。マルチプラットフォームのパッケージ形式(Homebrew、apt/deb、winget、Scoop)については、[skill:dotnet-cli-packaging] を参照してください。リリース CI/CD パイプラインについては、[skill:dotnet-cli-release-pipeline] を参照してください。コンテナーを使った配布については、[skill:dotnet-containers] を参照してください。一般的な CI/CD パターンについては、[skill:dotnet-gha-patterns] および [skill:dotnet-ado-patterns] を参照してください。

相互参照:[skill:dotnet-native-aot] では AOT コンパイルパイプライン、[skill:dotnet-aot-architecture] では AOT 対応の設計パターン、[skill:dotnet-cli-architecture] では CLI のレイヤードアーキテクチャ、[skill:dotnet-cli-packaging] ではプラットフォーム固有のパッケージ形式、[skill:dotnet-cli-release-pipeline] では自動リリースのワークフロー、[skill:dotnet-containers] ではコンテナーを使った配布、[skill:dotnet-tool-management] では利用者側でのツールのインストールとマニフェスト管理について説明しています。


配布戦略の判断マトリックス

対象ユーザーとデプロイの制約に基づいて、配布モデルを選択します。

戦略起動時間バイナリサイズランタイムの要否最適な用途
Native AOT 単一ファイル~10ms10-30 MB不要パフォーマンスが重要な CLI ツール、幅広い配布
フレームワーク依存の単一ファイル~100ms1-5 MB.NET ランタイムランタイムが確実に用意される内部ツール
自己完結型の単一ファイル~100ms60-80 MB不要AOT の複雑さを避けたシンプルな配布
dotnet tool(グローバル/ローカル)~200ms< 1 MB(NuGet).NET SDK開発者向けツール、.NET エコシステムのユーザー
各戦略を選択する場合

Native AOT 単一ファイル -- CLI 配布の最高水準:

  • ターゲットマシン上の依存関係がゼロ(.NET ランタイムは不要)
  • 最速の起動時間(JIT の ~100ms 以上に対して ~10ms)
  • トリミングと組み合わせることで最小のバイナリサイズ
  • トレードオフ:ビルド時間が長くなり、保持しない限りリフレクションを使用できません
  • PublishAot の MSBuild 構成については、[skill:dotnet-native-aot] を参照してください

フレームワーク依存のデプロイ:

  • 成果物のサイズが最小(アプリのコードのみで、ランタイムは含まれません)
  • ユーザーは .NET ランタイムをインストールする必要があります
  • ランタイムが管理されている内部/エンタープライズツールに最適です
  • 利便性のために単一ファイル発行を利用することもできます

自己完結型(非 AOT):

  • 成果物に .NET ランタイムを含みます
  • AOT よりバイナリサイズは大きくなりますが、ビルドプロセスはシンプルです
  • リフレクションと動的コードを完全にサポートします
  • AOT への互換対応が難しい場合に適した妥協案です

dotnet tool パッケージング:

  • NuGet 経由で配布でき、公開ワークフローが最もシンプルです
  • ユーザーは dotnet tool install -g mytool でインストールします
  • ターゲットには .NET SDK(ランタイムだけでは不可)が必要です
  • .NET エコシステムの開発者向けツールに最適です
  • NuGet による配布の詳細については、[skill:dotnet-cli-packaging] を参照してください

ランタイム識別子(RID)マトリックス

標準的な CLI の RID ターゲット

幅広くカバーするには、主要な 4 つの RID をターゲットにします。

RIDプラットフォーム備考
linux-x64Linux x86_64ほとんどの Linux サーバー、CI ランナー、WSL
linux-arm64Linux ARM64AWS Graviton、Raspberry Pi 4 以降、Apple Silicon VM
osx-arm64macOS Apple SiliconM1/M2/M3 以降の Mac(macOS の主要ターゲット)
win-x64Windows x86_64Windows 10 以降、Windows Server
オプションの拡張ターゲット
RID含める場合
osx-x64旧型の Intel Mac をサポートする場合(市場シェアは減少傾向)
linux-musl-x64Alpine Linux/Docker の scratch イメージを使用する場合
linux-musl-arm64ARM64 上の Alpine を使用する場合
win-arm64ARM 搭載の Windows(Surface Pro X、Snapdragon 搭載ノート PC)をサポートする場合
.csproj での RID 設定




<PropertyGroup Condition="'$(RuntimeIdentifier)' == ''">
  <RuntimeIdentifier>osx-arm64</RuntimeIdentifier>
</PropertyGroup>

コマンドラインから RID ごとに発行します。

# Publish for each target RID
dotnet publish -c Release -r linux-x64
dotnet publish -c Release -r linux-arm64
dotnet publish -c Release -r osx-arm64
dotnet publish -c Release -r win-x64

単一ファイルの発行

単一ファイルの発行では、アプリケーションとその依存関係を 1 つの実行可能ファイルにまとめます。

設定
<PropertyGroup>
  <PublishSingleFile>true</PublishSingleFile>
  
  <SelfContained>true</SelfContained>
  
  <DebugType>embedded</DebugType>
  
  <IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
</PropertyGroup>
Native AOT での単一ファイル発行

Native AOT と組み合わせると、単一ファイルは暗黙的に有効になります。AOT では常に単一のネイティブバイナリが生成されます。

<PropertyGroup>
  <PublishAot>true</PublishAot>
  
  
</PropertyGroup>

ILLink、型の保持、アナライザーの設定を含む AOT 発行設定の全容については、[skill:dotnet-native-aot] を参照してください。

発行コマンド
# Framework-dependent single-file (requires .NET runtime on target)
dotnet publish -c Release -r linux-x64 /p:PublishSingleFile=true --self-contained false

# Self-contained single-file (includes runtime, no AOT)
dotnet publish -c Release -r linux-x64 /p:PublishSingleFile=true --self-contained true

# Native AOT (inherently single-file, smallest and fastest)
dotnet publish -c Release -r linux-x64
# (when PublishAot=true is in csproj)

CLI バイナリのサイズ最適化

トリミング(AOT なし)

トリミングすると、発行された出力から未使用のコードが削除されます。自己完結型の非 AOT ビルドの場合:

<PropertyGroup>
  <PublishTrimmed>true</PublishTrimmed>
  <TrimMode>link</TrimMode>
  
  <SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
</PropertyGroup>
AOT のサイズ最適化

Native AOT ビルドでは、サイズは AOT 固有の MSBuild プロパティで制御します。設定の全容については、[skill:dotnet-native-aot] を参照してください。CLI に関係する主なプロパティには、StripSymbols、OptimizationPreference、InvariantGlobalization、StackTraceSupport があります。

サイズ比較(一般的な CLI ツール)
設定おおよそのサイズ
自己完結型(トリミングなし)60~80 MB
自己完結型+トリミング15~30 MB
Native AOT(デフォルト)15~25 MB
Native AOT+サイズ最適化8~15 MB
Native AOT+不変のグローバリゼーション+シンボル削除5~10 MB
フレームワーク依存型1~5 MB
実用的なサイズ削減チェックリスト
  1. ツールでロケール固有の書式設定が不要な場合は、不変のグローバリゼーションを有効にします(InvariantGlobalization=true)
  2. Linux/macOS ではシンボルを削除します(StripSymbols=true)。クラッシュ解析用にシンボルファイルは別途保持してください
  3. サイズを優先して最適化します(OptimizationPreference=Size)。I/O 待ちが中心の CLI ツールでは、ランタイムのパフォーマンスへの影響は最小限です
  4. 可能な場合はリフレクションを無効にします。JSON シリアル化にはソースジェネレーターを使用してください([skill:dotnet-aot-architecture])
  5. NuGet 依存関係を監査します。依存関係ごとにバイナリサイズが増えるため、未使用のパッケージは削除してください

フレームワーク依存型と自己完結型のトレードオフ

フレームワーク依存型
dotnet publish -c Release -r linux-x64 --self-contained false

メリット:

  • 成果物のサイズが最小(1~5 MB)
  • ランタイムの更新で保守されます(セキュリティパッチはアプリの再ビルドではなく、ランタイムに適用されます)
  • 発行時間が短い

デメリット:

  • ターゲット環境に一致する .NET ランタイムが必要です
  • ランタイムのバージョン不一致により、起動に失敗します
  • ユーザーがランタイムのインストールを管理する必要があります
自己完結型
dotnet publish -c Release -r linux-x64 --self-contained true

メリット:

  • ターゲット環境にランタイム依存関係がありません
  • アプリで使用するランタイムのバージョンを正確に管理できます
  • サイドバイサイドでデプロイできます(複数のアプリで異なるランタイムを使用できます)

デメリット:

  • 成果物のサイズが大きくなります(トリミングなしで 60~80 MB)
  • ランタイムのセキュリティパッチ適用時には、再ビルドして再配布する必要があります
  • ターゲット RID ごとに成果物が 1 つ必要です

発行ワークフロー

ローカル開発
# Quick local publish for testing
dotnet publish -c Release -r osx-arm64

# Verify the binary
./bin/Release/net8.0/osx-arm64/publish/mytool --version
リリース成果物の作成
#!/bin/bash
# build-all.sh -- Produce artifacts for all target RIDs
set -euo pipefail

VERSION="${1:?Usage: build-all.sh <version>}"
PROJECT="src/MyCli/MyCli.csproj"
OUTPUT_DIR="artifacts"

RIDS=("linux-x64" "linux-arm64" "osx-arm64" "win-x64")
# Note: Native AOT cross-compilation for ARM64 on x64 requires platform toolchain
# See [skill:dotnet-cli-release-pipeline] for CI-based cross-compilation setup

for rid in "${RIDS[@]}"; do
  echo "Publishing for $rid..."
  dotnet publish "$PROJECT" \
    -c Release \
    -r "$rid" \
    -o "$OUTPUT_DIR/$rid" \
    /p:Version="$VERSION"
done

# Create archives
for rid in "${RIDS[@]}"; do
  if [[ "$rid" == win-* ]]; then
    (cd "$OUTPUT_DIR/$rid" && zip -q "../mytool-$VERSION-$rid.zip" *)
  else
    tar -czf "$OUTPUT_DIR/mytool-$VERSION-$rid.tar.gz" -C "$OUTPUT_DIR/$rid" .
  fi
done

echo "Artifacts in $OUTPUT_DIR/"
チェックサムの生成

リリース成果物のチェックサムは必ず生成してください。

# Generate SHA-256 checksums
cd artifacts
shasum -a 256 *.tar.gz *.zip > checksums-sha256.txt

GitHub Actions でこれを自動化する方法については、[skill:dotnet-cli-release-pipeline] を参照してください。


エージェントに関する注意点

  1. マルチプラットフォーム対応の CLI ツールでは、.csproj に RuntimeIdentifier を設定しないでください。 プロジェクトファイルで RID をハードコードすると、他のプラットフォーム向けにビルドできなくなります。代わりに、発行時に -r <rid> を渡してください。
  2. PublishAot と PublishSingleFile を併用しないでください。 Native AOT の出力は本質的に単一ファイルです。両方を設定しても冗長であり、ビルド時にわかりにくい警告が発生することがあります。
  3. サイズが重要な CLI ツールでは、InvariantGlobalization を省略しないでください。 グローバリゼーションデータによって、AOT バイナリのサイズは約 25 MB 増加します。ロケール固有の日付や通貨をフォーマットしない CLI ツールの多くでは、InvariantGlobalization=true を有効にしてください。
  4. トリミングされていない自己完結型バイナリを配布しないでください。 60~80 MB の CLI ツールは、エンドユーザーにとって許容できません。トリミング(PublishTrimmed)するか、AOT を使用するか、フレームワーク依存型として配布してください。
  5. リリース成果物のチェックサムを忘れずに生成してください。 ユーザーやパッケージマネージャーがダウンロードの整合性を検証できるよう、SHA-256 チェックサムが必要です。チェックサムを自動生成する方法については、[skill:dotnet-cli-release-pipeline] を参照してください。
  6. 発行スクリプトにシークレットをハードコードしないでください。 署名やアップロードの認証情報には、環境変数のプレースホルダー(${SIGNING_KEY})を使用し、CI でのシークレットの保存場所についてコメントを添えてください。

参考資料

コメント