.NET for iOS / Android 、およびMAUI SDK のバージョンを制御する方法というテーマで調べた事をつらつら書いていきます。
問題
.NET 6以降のiOS /Android SDK 管理は、基本的に最新へ上げ続ける事を要求する。
ついでに、Xamarin.Formsが.NET MAUIになってバージョンを下げられなくなった。
特に.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
という名前でマニフェスト ファイルの実体が入っています。
おわり