Appleシリコンプロセッサーは、デスクトップCPUの世界に革命を起こしました。Intelのx86_64アーキテクチャからAppleのarm64への移行は、パフォーマンスを大きく落とすことなくx86_64コマンドをarm64に変換する、ロゼッタ2エミュレータのおかげで、消費者にとってとてもスムーズでした。しかし、2020年末に新アーキテクチャがリリースされた当初は、開発者たちもエミュレーションに頼る必要がありました。というのも、開発者ツールやライブラリの大半は、arm64アーキテクチャをサポートしておらず、さらにそのために、パフォーマンスが不安定になったり、場合によってはクラッシュしたりすることもあったからです。
新しいAppleシリコンチップが登場して約2年が経過した今、状況は一変しています。arm64アーキテクチャへの移行がまだの方は、この機会にご検討ください。昨年や2020年末と比較すると、ほとんどの依存関係やツールが新しいアーキテクチャに対応しているので、移行作業中に大きなハードルに直面することはないでしょう。
さらに、皆様にご愛用いただいているCI/CDプロバイダーであるCodemagicが、初のMac mini M1ビルドマシンを一般公開したことにも触れないわけにはいきません! すでに一部のお客様には、新しい効率的なチップを搭載した強力なビルドマシンをお試しいただき、ビルドタイムの大幅な短縮に成功されております。そこで、IntelからM1への移行、つまり、プロジェクトのCI/CDパイプラインを、古き良きx86_64からピカピカの新しいarm64へ移行することについてご説明させていただきます。
本記事では、以下のトピックについてご紹介いたします:
- 必要条件
- 新アーキテクチャでの作業
- サードパーティの依存関係を更新
- Mac mini M1とMac Proのビルド時間
それでは、さっそく始めましょう!
M1への移行に必要な条件
本稿執筆時点では、ワークフローをCodemagic上の新しいApple M1仮想マシンに移行するには、**Xcode 13.3+**を使用する必要があります。これは、macOS M1ビルドマシンのベースイメージにそれがプリインストールされているからです。Xcode 13.3.1 (13E500a) は最新版で、codemagic.yaml
ファイルに 13.3
、13.3.1
、edge
、またはlatest
を設定するか、Flutterアプリのワークフローエディタのビルド設定で選択すると、デフォルトで使用されます。
2020年にAppleがカスタムシリコンを発表すると、新アーキテクチャへの2年間の移行が始まりました。開発者は開発者移行キット(DTK=Developer Transition Kit)を利用して、アプリのテスト、アップデート、Appleシリコンへの移行ができました。
当初、開発者たちは、ロゼッタエミュレーションを使って、Intelプロセッサを搭載したMac向けに作られたアプリを利用していました。また、CocoaPods依存関係とSwiftパッケージは、最初の数か月はarm64アーキテクチャに未対応でした。開発者たちが移行を開始し、最新のM1やM1 Pro/Max/Ultraシリーズデバイスを入手するにつれて、オープンソースプロジェクトや、arm64アーキテクチャに対応した様々なSDKを要求するようになりました。
移行がほぼ終了した現在、Alamofire、Kingfisher、あるいはFirebase SDKなど、数多くの人気オープンソースプロジェクトがAppleシリコンマシンに対応するようになりました。これで、ほとんどの場合、ロゼッタエミュレーションを使う必要がなくなり、Appleの効率的なチップの生の処理能力を活用できるようになりました。
新アーキテクチャとの連携
iPhoneのアーキテクチャはすでに「arm64」ですが、Intelは「x86_64」のシミュレーターを使用しました。新しいM1シリーズのデバイスでは、シミュレーターも「arm64」アーキテクチャで動作します。
Appleは、Appleシリコンのアーキテクチャビルドエラーを解決するための詳細記事を提供しています。
Xcodeはすでに、すべてのプラットフォームでビルドして出荷するのに役立つデフォルトのアーキテクチャビルド設定を備えています。設定の1つに アクティブなアーキテクチャのみを構築(Build Active Architectures Only)というブーリアン値があり、デフォルト値はDebug構成の場合はYes、Release構成の場合はNoとなっています。値が Yesに設定されている場合、Xcodeは選択されたアーキテクチャ用に自動的にビルドします。つまり、Appleシリコンマシンを使っている場合はarm64シミュレーター用にビルドし、Intelマシンを使っている場合はx86_64シミュレーター用にビルドします。
デバイスとシミュレーターは異なるアーキテクチャを持つかもしれませんが、特にIntelマシンを使用している場合、Xcodeにどちらか一方のみを対象にビルドさせたいと考えるかもしれません。
プロジェクトに移動し、ターゲットを選択し、ビルド設定を選択します。アーキテクチャセクションで、デバッグビルド用にアクティブなアーキテクチャのみを構築(Build Active Architectures Only)をYES**に設定します。これにより、コンパイラは1つのアーキテクチャ用のバイナリのみを生成するようになります。
Podsも同様にします:
それをNOに設定すると、Xcodeはすべての有効なアーキテクチャ用にプロジェクトを構築します。しかし、次のようなエラーが表示されることがあります:
Could not find module 'ColorKit' for target 'x86_64-apple-ios-simulator'; found:
arm64-apple-ios-simulator, at: /Users/rudrankriyam/Library/Developer/Xcode/DerivedData/Musadora-ccjzyuildzfnokedenrcjqixspxo/Build/Products/Debug-iphonesimulator/ColorKit.swiftmodule
Xcodeのアクティブなアーキテクチャを構築(Build Active Architecture)をYESに設定すると、ビルド時間が劇的に短縮されます。なぜなら、2つのアーキテクチャではなく1つのアーキテクチャ用にコンパイルされるからです。これでさらに作業が加速します!
サードパーティの依存関係を更新
あなたのプロジェクトでは、サードパーティの依存関係を管理するために、CocoaPods、Carthage、および/またはSwiftパッケージマネージャを使用できます。
M1 MacでHomebrewを使うと、CocoaPodsの管理も簡単です。
brew install cocoapods
Carthageを使用する場合は、XCFrameworksを使用するのが最適な解決策です。これにより、アプリを構築するのに必要な有効なアーキテクチャのみを構築できます:
carthage update --use-xcframeworks
Podやパッケージを最新版に更新する必要があるかもしれません。これにより、ユニバーサルバイナリ(x86_64とarm64の両アーキテクチャの実行コードを含む)のサポートを受けられる可能性が高まり、インテルマシンからAppleシリコンマシンへの移行がスムーズに行えるようになります。
この投稿では、サードパーティの依存関係を組み合わせたサンプルプロジェクトを使用します。CocoaPodsとSwiftパッケージマネージャの両方を使用しています。
Swiftパッケージとしてのプロジェクトの依存関係は以下の通りです:
- Kingfisher
- Swinject
- Alamofire
Podsとしてのプロジェクトの依存関係は以下の通りです:
- SwiftLint
- AppsFlyerFramework
最初のプロジェクトでは、XCFrameworkが arm64アーキテクチャをサポートしていない場合に発生するエラーをご紹介するために、古いバージョンのフレームワークが用意されています。
pod 'AppsFlyerFramework', '6.2.0'
ソースコードがないため、自分たちでユニバーサルバイナリを作ることはできません。プロジェクトを実行すると、次のようなエラーが表示されます:
ld: in /Users/rudrankriyam/Downloads/Silicon/Pods/AppsFlyerFramework/iOS/AppsFlyerLib.framework/AppsFlyerLib(AFSDKKeychainFactory.o),
building for iOS Simulator, but linking in object file built for iOS,
file '/Users/rudrankriyam/Downloads/Silicon/Pods/AppsFlyerFramework/iOS/AppsFlyerLib.framework/AppsFlyerLib'
for architecture arm64
シミュレーターでプロジェクトを実行するには、arm64アーキテクチャが必要です。しかし、今回のフレームワークのバージョンでは、それをサポートしていません。
この問題を解決するには、フレームワークのリポジトリを検索し、arm64のサポートを追加するバージョンがリリースされているかどうかを確認します。前述したように、多くの優先フレームワークやオープンソースプロジェクトは、最新のシリコンチップ上での動作に対応しています。幸いなことに、このフレームワークはバージョン 6.3.0
で arm64をサポートするようになったため、Podfile
を更新して最新バージョンを取得できます。
pod 'AppsFlyerFramework'
pod update
コマンドを入力すると、M1デバイスとIntelマシンでプロジェクトを正常に実行できるようになります。
ある依存関係がまだarm64をサポートしていない場合、フレームワークの作者に両方のアーキテクチャをサポートする新しいアップデート版を提供するように依頼できます。ユニバーサルXCFrameworkを提供することでarm64対応に移行したiOS SDKの例として、AppsFlyer iOS SDKは複数の開発者からの要望を受けて、昨年4月にarm64サポートをリリースしました。
多くの依存関係は迅速なサポートを備えている一方で、ご使用のフレームワークは古くなっている可能性があります。また、ソースコードにアクセスできないプロプライエタリなフレームワークである場合もあります。また、これらのフレームワーク/パッケージのアップデートが当面ないと仮定します。その場合、こちらの記事「ネイティブARM64バイナリをiOSシミュレータ上で動作させるためのハッキング」(Hacking native ARM64 binaries to run on iOS Simulator) をご覧ください。その名の通り、ハッキングして動作させるものなので、この極端な回避策は最終手段としてのみ使うことをお勧めいたします。
M1 Mac miniとIntel Mac Proのビルドタイム
移行に成功したオープンソースプロジェクトからヒントを得て、新しいチップに取り組むことができます。そのようなプロジェクトの例をいくつか見てみましょう。こちらをご覧ください。
M1マシンとIntelマシンのビルド時間の違いを理解し、M1 Mac miniの優れた効率性と速度を知るために、公式のWikipedia iOSアプリを構築しテストを実行しました。これは、何百ものテストを行う実戦的なシナリオを実証しています。オープンソースのアプリなので、ご自分で調べることも可能です。
テスト名 | Mac mini M1 | Mac Pro |
---|---|---|
スクリプトのインストール | 17s | 163s |
プロジェクトのビルド | 254s | 280s |
テストの実行 | 270s | 395s |
全体 | 573s | 883s |
特にテストの実行中に、M1ビルドマシンの方が大幅に高速に動作していることが、数字で確認できます。このアプリに対して同じテストを複数回実行した結果、全体のビルド時間が**35~40%**減少していることが確認できました。多くのビルドを実行する場合、数値の差は加算され、より速い反復処理によりかなりの時間を節約できます。
結論
AppleシリコンチップはMacハードウェアの未来であり、これからますます良くなっていきます。一般的なオープンソースのフレームワークやSDKはすでに新しいチップに対応しているため、1年前と比べると移行はずっと簡単です。
再度のお知らせ:M1 Mac miniビルドマシンは、Codemagicですでにご利用いただけます。従量課金(pay as you go)の場合は、単に
instance_type: mac_mini_m1
を使用してお試しください。プロフェッショナルプランをご利用のお客様で、Mac mini M1の試用版をご希望の方は、カスタマーエンジニアリングチームにご連絡いただけますと、新しいマシンで迅速にグリーンビルド(成功ビルド)を実現できます!