.NET for iOS / AndroidのSDKバージョンを固定する
.NET for iOS / Android、およびMAUI SDKのバージョンを制御する方法というテーマで調べた事をつらつら書いていきます。
問題
特に.NET for iOS SDKのバージョンが上がると、Xcodeのバージョンを上げないとビルドすらできなくなる場合もあり大変困ります。
主な動機
- ビルドパイプラインのために毎回同じ環境を一から構築できるようにする。
- セットアップ時期の違うマシンで開発環境を揃える。
- バグのあるバージョンを避けてSDKをダウングレードする。
SDK? Workload?
さて、今回扱うSDKは、XamarinでいうとXamarin.iOS / Android SDKに当たるものです。 つまり、C#のコードをiOS/Androidアプリにするためのビルドツールや、ネイティブAPIのC#ラッパーの事です。 ネイティブのAndroid SDKやXcodeは含みません。(簡単のためC#前提で進めます)
.NET 6以降でこれらのSDKは Workload
という仕組みでインストールされます。
Visual StudioとSDKの更新サイクルを分離して、個別にアップデート出来るようにするのが大きな目的です。
dotnet workload
コマンドが用意されており、例えばMAUI SDKをインストールする場合は dotnet workload install maui
を実行します。
dpotnet install
では常に最新のWorkloadがインストールされ、 dpotnet update
でインストール済みのWorkloadを全て最新に更新します。バージョン指定するオプションはありません。
いくら何でも強気すぎますね!?
ついでに、Xamarin.FormsはただのライブラリだったのでNuGetで任意のバージョンをインストールできましたが、後継の.NET MAUIは.NET SDKの一部になってしまい開発環境で特定のバージョンを使うことになりました。 (複数のプロジェクトで違うバージョンで開発したい場合に困りますね)
アンドキュメントな方法でバージョンを指定する
実は workload install
と workload update
には --from-rollback-file
という隠しパラメータが存在していて、所定のフォーマットのjsonファイルを与えるとバージョン指定が出来ます。
ロールバックファイルの中身はこんな感じ。
{ "microsoft.net.sdk.maui": "7.0.52", }
コマンド実行する時はこんな感じになります。
workload install maui --from-rollback-file rollback.json
先行事例に倣って"microsoft.net.sdk.maui"と指定しましたが、実験したところ代わりにWorkload IDの"maui"を使っても大丈夫でした。
参考
ドキュメント化しないと明言されているissue
Add
workload install --from-rollback-file
documentation · Issue #28226 · dotnet/docs
MAUIのバージョンを固定したいと相談しているissue
How do I Pin a Maui App to a specific version? · Issue #8985 · dotnet/maui
ロールバックファイルで指定する内容
ロールバックファイルで指定するバージョンをいくつにしたら良いか?
大抵の場合は安定環境にインストールされているメモして、それを利用するのが良さそうです。
WindowsでVisual Studioをインストールした環境で dotnet workload list
を実行すると以下のような結果となりました。
インストール済みワークロードの ID マニフェストのバージョン インストール ソース ---------------------------------------------------------------- maui-android 7.0.52/7.0.100 VS 17.4.33213.308 android 33.0.4/7.0.100 VS 17.4.33213.308 maui-windows 7.0.52/7.0.100 VS 17.4.33213.308 maui-maccatalyst 7.0.52/7.0.100 VS 17.4.33213.308 maccatalyst 16.1.1477/7.0.100 VS 17.4.33213.308 maui-ios 7.0.52/7.0.100 VS 17.4.33213.308 ios 16.1.1477/7.0.100 VS 17.4.33213.308
消せないWorkload
WindowsでVisual Studioをインストールしている環境では関連するWorkloadをアンインストールできなくなるようです。
「インストールソース」で頭に"VS"が付いてるものをアンインストールしようとすると、見つからない(実際にはインストールされている)扱いとなるので特別扱いされます。
"ロールバックファイルで指定する内容"の状態からmaui
とios
のWorkloadをインストールするとこのようになります。
インストール済みワークロードの ID マニフェストのバージョン インストール ソース ----------------------------------------------------------------------------- ios 16.2.1024/7.0.100 SDK 7.0.100, VS 17.4.33213.308 maui 7.0.59/7.0.100 SDK 7.0.100
この後、maui
とios
のWorkloadをアンインストールできますが、maui
のそのままリストから消えるのに対し、ios
の方は「インストールソース」の"SDK 7.0.100"部分だけ消えてWorkload自体は残ります。
CIなどを考える場合、WindowsではVisual Studioをインストールせずに.NET SDK、Workloadだけを直接インストールしたビルド専用マシンにするのが良さそうです。
Workload Manifest
WorkloadのIDやバージョンはWorkload Manifestに定義されています。 ManifestファイルはNuGetで配布されていて、dotnetコマンドをこれを自動的に取得して有効なIDか、新しいバージョンがあるかなどを判別しているようです。
nuget.orgで"Microsoft.NET.Sdk"と検索するとそれらしいのが沢山ヒットします。
命名規則は次のようになっているようで……
Microsoft.NET.Sdk.<プラットフォーム>.Manifest-<.NET SDKバージョン>
.NET 7.0.1xx系で利用可能なiOS開発用SDKの場合は Microsoft.NET.Sdk.iOS.Manifest-7.0.100
という具合ですね。
中身には WorkloadManifest.json
という名前でマニフェストファイルの実体が入っています。