Xcode Cloudから無理やりMagicPodにARM64アプリをアップロードする

おはようございます。noteでiOSアプリ開発をしているwaturaです。最近、自動車免許をとったんですが、よくもまあみんな運転できるよなぁと感じています。運転めっちゃ怖くないですか?

※ この記事はnote株式会社 Advent Calendar 2022の16日目の記事です。
15日目の記事はLeetCodeで頭の体操とコンピュータサイエンスのお勉強でした。
ちょっとLeetCodeやってみたいなぁって思いました。

MagicPod

note iOSアプリではMagicPodを使ってテストを行っています。

いくつかMagicPod関連の記事があるので、前提としてみていただけるとうれしいです。

画像をアップロードできない問題

MagicPodのヘルプページにもあるのですが、一部の条件下で画像を選択出来なくなります。それが下記なのですが、ばっちしnoteアプリが当てはまっていました。

1. x86やx86_64向けにビルドされたアプリ(.app )ファイルを使っている
2. PHPickerViewControllerを使っている

iOS クラウド端末で画像を選択できない

MagicPodにはXcode Cloudからアプリをアップロードしています。Xcode CloudはIntel Macなようなので、Simulator向けビルドはx86向けにビルドされてしまいます。そして、PHPickerViewControllerを使っています。そのため、上記の条件に当てはまってしまい、画像が選択できず、画像がアップロードできるかどうかのテストが必ず失敗するという事態になってしまっていました。

MagicPodの方に相談したりして、一時しのぎの対応として INTEL_MACオプションを設定し、iOS 14を使うようにしていました。

iOS 14を切る準備はしたい

いまのところ切る予定は決まっていないのですが、アプリエンジニアとしては早く新しい機能を取り込んでいきたいし、プリプロセッサで条件分岐をかくのもあれなので、早く15以上にしていきたいなぁと思っています。
しかし、たとえnote社内ルール的にiOS 14をきれる状態になったとしても、MagicPodでテストを実行し続けるために、14対応を維持し続けなければいけませんでした。
これを解消するためには、なんらかの方法でMagicPodで画像アップロードまわりを対応する必要がありました。

そのためにできることとしては、おおむね次の2つです。

  1. PHPickerViewControllerを使うテストをやめる

  2. arm64でビルドしたものをアップロードする

画像アップロード機能があるnoteというアプリで、「CIが画像アップロードに対応しなくなるから、画像アップロードのテストを削除します。」は、「なんのためのテストだよ。」となってしまうのでどう考えてもNGです。

それでは、arm64でビルドしたものをアップロードする方法を考えていきます。

arm64でビルドしたものをアップロードするには

  1. arm64環境のCIを使ってビルドする

  2. M1, M2のPCでビルドする

のどちらかだと思っていました。しかし、実際には「x86環境からでもarm64向けのビルドができる」ことがわかりました。
まあ、考えてみれば簡単なことなのですが、iOS実機がそもそもarm系CPUなのでIntel macからでもarm64ビルドは出来てもおかしくないはずでした。

Xcode Cloudでarm64 simulator向けビルドを行う

注意としては、
1. 無理やりビルドしているだけなので動かなくなる可能性はある
2. Xcode CloudがApple Siliconになれば万事解決
3. 余分なビルドを実行しているので実行時間が延びる
4. ビルドするタイミングによっては動かない
5. Artifactとして保存するようにはまだしていない
とかがあります。
また、Xcode Cloudで実行するとはしていますが、Xcode Cloud以外の環境でもほぼほぼ同様に実行できるかと思います。

やったこと

  1. Xcode Cloudでテスト環境向けビルドしているときのxcodebuildコマンドをコピってくる

  2. コピったコマンドの意味をある程度理解する

  3. xcodebuildコマンドでiphonesimulator向けのビルドにする方法を探す

Xcode Cloudのログをみていくと、xcodebuild build-for-testing hogehogeというコマンドを実行しているところが見つかるかと思います。そこがxcodebuildをつかって、Simulator向けビルドをしているところになります。
そのコマンドをなるべく周到するかんじで、いじくっていきました。
その結果がこのgistになります。(使っているものから、ちょっといじっていたりするのでそのままでは動かないかもしれません)

重要なのはラスト2行になります。

-arch arm64
-sdk iphonesimulator

ここです。これは、ビルドするときのarcharm64にして、sdkとしiphonesimulatorをつかってビルドしてください!というオプションになります。
-archがなかった場合は、x86ビルドになり、-sdkがなかった場合はiphoneos向けのビルドになります。なので、両方を指定する必要があります。

また、コピペしたコマンドでは、destinationとしてiPhone Simulatorが指定されていたのですが、Simulatorを指定してある場合は、archが指定できなくなります。destinationの向いている先のarchとsdkを自動で使ってくれるという設定なので、当然といえば当然です。

この処理と、別記事のmagicpodにアップロードするスクリプトをci_post_clone.shで実行するようにしました。
すくなくともこのスクリプトのままでは、実行するタイミングをci_post_xcodebuild.shにしてはダメです。このスクリプトで作られるアプリがXcode Cloudがつかうつもりで作っていたアプリを上書きしてしまっているためです。Xcode CloudのSimulatorで実行しようとしたさいにエラーが発生します。
なので、Xcode Cloudがビルドする前か、テストし終わったあとに実行する必要があります。
MagicPodの実行には非常に時間がかかっているので、1分でも早くテストを開始しておきたいのと、Xcode Cloudがビルドした結果も保持しておきたかったので、post_cloneのタイミングで実行するようにしました。

まとめ

iOS 14をそのうち切りたい。切りたいが、MagicPodがiOS 14じゃないとダメなんだ。じゃあ、なんとかするぞ!ではじめたことなんですが、無事にできました。

  • MagicPodでPHPickerViewControllerを使いたかったら、iOS 14かarm64のアプリを用意する必要がありました。

  • Xcode Cloudはx86環境なので、何も考えずにアップロードするとx86アプリがアップロードされる。

  • 無理やりxcodebuildをたたくようにして、arm64アプリをつくって、MagicPodにアップロードするようにしました。

  • これで、iOS 15以上をターゲットにするようにできて、かつ、MagicPodも使えるので、幸せに少し近づきました。

こんなかんじでテストをしたりしてガシガシ作っているアプリなので、ぜひ使ってみてください。


▼noteエンジニアアドベントカレンダーはこちら

▼さらにnoteの技術記事が読みたい方はこちら