.NET Core 3.0 からビルド時に Tier 0 のネイティブコードを生成する ReadyToRun が利用可能になっています。実行時に Tier 0 のコード生成を行わない分、スタートアップの高速化が期待できる機能です。
.NET 6.0 は Windows x64 環境なら全てのクロスコンパイルも出来るので、使い勝手がよくなっています。
起動速度が重要となるデスクトップアプリケーションでは基本的に ReadyToRun は有効化するようにしているのですが、WPF を使って MSIX でパッケージングしているアプリケーションを .NET 6.0 に移行すると GitHub Actions で行っているビルドが通らなくなりました。
使用しているのは Windows Server 2022 環境なので x64 の .NET SDK が使われているのですが、何故か R2R ビルドがサポートされないプラットフォームと言われてしまいます。
error NETSDK1095: Optimizing assemblies for performance is not supported for the selected target platform or architecture. Please verify you are using a supported runtime identifier, or set the PublishReadyToRun property to false.
エラーメッセージにあるように PublishReadyToRun
を false
にすればビルドが通るようになりますが、出来る限り有効化した状態で WPF アプリケーションはリリースしたいです。
最初は GitHub Actions 固有の問題かと思っていましたが、調べていると以下の Issue が見つかりました。どうやら .NET 6.0 から ReadyToRun ビルドを行うときの挙動が変更になっていたようです。
少し前に Breaking change としてドキュメントも公開されていました。.NET 6.0 からは ReadyToRun ビルドを行う際には復元時にも PublishReadyToRun
プロパティを指定して、必要となる NuGet パッケージ*1をインストールする必要があるようです。
従って GitHub Actions や MSIX に関係なく、シンプルな WPF アプリケーションでもビルド・発行時に --no-restore
を指定していると発生します。回避方法は dotnet restore
時に PublishReadyToRun
を指定するか、dotnet publish
で暗黙的に NuGet パッケージの復元を実行する必要があります。
.NET CLI で ReadyToRun ビルドを行う場合は以下のどちらかになることを覚えておけば良さそうです。
# --no-restore を指定する場合は restore 時に R2R を使う宣言をしないと crossgen2 がインストールされない dotnet restore -p:PublishReadyToRun=true dotnet publish -c Release --no-restore # --no-restore を付けなければ自動で restore が行われるので問題なく動作する dotnet publish -c Release -p:PublishReadyToRun=true
大きなソリューションでは最初に一回だけ dotnet restore
を実行するようにして、暗黙的な復元を無効化した方がビルド時間が短縮できるので、--no-restore
を使っているケースもあると思います。その場合は R2R との組み合わせに注意が必要です。
.NET CLI を使ったビルドの場合はここまでの方法で問題ないのですが、MSIX を使ったデスクトップアプリケーションのパッケージングには Visual Studio とインストールされた MSBuild が必要になります。具体的には wapproj
は dotnet msbuild
を使ってもビルドは行えません。
最初に .NET CLI を使って dotnet restore
だけ実行すれば良さそうではありますが、それもエラーになって上手く動きませんでした。なので MSBuild で NuGet パッケージの復元を行うことで対応します。
MSBuild は .NET CLI のように自動的に復元は実行してくれないですが -restore
オプションを指定すると、ビルド前に NuGet パッケージの復元を行ってくれるようになります。その際に PublishReadyToRun
を指定することで、必要なパッケージのインストールが行われるようになります。
# -restore を付けると dotnet build/publish のように自動で restore が行われる msbuild -restore -p:Configuration=Release -p:PublishReadyToRun=true
Windows App SDK を使ったプロジェクトなど、最近の新しいプロジェクトでは各 RID 向けの Publish Profile が作成されて、それを wapproj
から参照するようになっていますが、復元時にはその設定が考慮されないので個別に R2R の設定を指定しています。
実際にプロジェクトで使っている GitHub Actions のワークフローを修正した PR が以下になります。
GitHub 上で新しく Release を作成して MSIX のビルドを行わせると、ReadyToRun が有効な状態でも問題なくビルドが完了するようになりました。ARM64 向けの R2R ビルドも問題なく実行されています。
原因が分からなかったので、一旦はローカル開発環境でビルドしたものをストアに申請していて非常に面倒でしたが、これで .NET 6.0 でも GitHub Actions を使った MSIX の自動化が利用出来るようになりました。
*1:crossgen2 が含まれているパッケージ