ねこ島

iOSのこととか、日常について雑に書きます

M1 Macへの移行作業ログ

M1 Mac miniを買ったのでiMac 5Kから移行作業をしている。
主にiOSアプリ開発周りで引っかかったところを挙げていきます。

pod installに失敗する

CocoaPods自体はインストールに成功するが問題はその先で、pod install時に以下のように怒られる

/src/vendor/bundle/ruby/2.6.0/gems/ffi-1.13.1/lib/ffi.rb:6:in `require': dlsym(0x7fcdf6710400, Init_ffi_c): symbol not found - /src/vendor/bundle/ruby/2.6.0/gems/ffi-1.13.1/lib/ffi_c.bundle (LoadError)

どうやらffi側の修正対応が必要そうで、issue見るとワークアラウンドがコメントされていた。 https://github.com/CocoaPods/CocoaPods/issues/9907#issuecomment-749389632

arch -x86_64 pod install

これで動いた。ちなみにTerminal自体をRosettaで開いても同じ挙動になる。

(WIP)CarthageとXCFramework対応

これが一番めんどくさかった。iOS Simulatorがx86_64向けにビルドされている既存のframeworkではビルドに失敗する。 解決するためには最近Carthageが対応したXCFrameworkに移行する必要がある。

なぜ移行する必要があるのかというと、今までiOS Simulator(x86_64), iOS(arm64)それぞれのアーキテクチャを元にfat binaryを生成していたが、M1 Macの登場によりiOS Simulator(arm64), iOS(arm64)にアーキテクチャが変わった。この影響で同じアーキテクチャ同士競合してしまい、fat binaryの生成に失敗する。

XCFrameworkはXcode11から用意された新しい形式で、サポートしているプラットフォーム毎のFrameworkを一つにまとめることができる。
プラットフォーム、というところがキモで、アーキテクチャの制約を受けないのでM1 Macでも問題なく動作する。

メリットもあって、CarthageだとBuild Phaseで実行していたcopy-frameworksも不要になる。AppStoreに提出するときにiOS Simulator向けのアーキテクチャをFrameworkから取り除く必要がなくなったためで、これによりビルドが更に早くなる。そういった点ではM1 Macを持っていようがいなかろうが、早めに対応するのが吉かもしれない。

前置きが長くなったが、Carthageでの対応自体は簡単で、オプションの--use-xcframeworksを付与してあげるだけ。

carthage bootstrap --platform iOS --cache-builds --use-xcframeworks

これをやるとXCFrameworkがCarthage/Buildの中に作られる。pre-builtされたFrameworkはCarthage/Build/iOSに入っていた。

次にXCFramework化されたライブラリをBuild Phasesで実行しているcarthage copy-frameworksから落としていくという作業が必要になる。これは手作業で行う。

XcodeGenを採用している場合、XCFrameworkはframeworkを使って指定する。
carthageを指定するとcopy-frameworksに追加されてしまうので今は使わないように。

dependencies:
  - framework: "Carthage/Build/APIKit.xcframework"
  - framework: "Carthage/Build/Auth0.xcframework"
  - framework: "Carthage/Build/Lottie.xcframework"

XcodeGen側でもXCFramework対応が進められているので、そのうちこの対応は不要になると思う。 github.com

pre-builtされたFrameworkがまだXCFramework対応されていなかったのでいったん作業はここまで。

(番外編)iCloud Driveが同期しない

おそらくBig Surの問題。 初期設定後いつまで経ってもiCloud Driveの中身が同期されなかった。

まず確認すべき点は同期の対象になっているかどうか。設定→iCloud Driveのオプションを選択して、デスクトップフォルダと書類フォルダにチェックが入っていることを確認する。 筆者の環境では入っていなかったので注意してほしい。

f:id:nekowen:20210223204618p:plain
iCloud設定

それでもダメな場合、brctlコマンドで現在のSync状態を確認と診断を行うと改善する可能性がある。問題なさそうだが念の為自己責任でお願いします。
以下はRedditで紹介されていたコメントを引用する。

まずSync状態を確認する。

brctl status

ログの上部の方に何かエラーが出ていないか確認する。筆者の環境では>>> BROKEN STRUCTUREと出ており、詳しい原因はAppleのサポートに聞かないとわからないが"何かがおかしいです"状態になっていた。iCloudの情報を保持するDBが壊れてるとかなのか?

次に診断を行う。ログを収集するけど良いか?と聞かれるので返答。

brctl diagnose

そうするとiCloudの管理するファイルやシステムなど色々なログが取られてzipに吐き出される。このファイルは使わないので削除してOK
診断を行うこと自体に意味があるらしく、診断後はBROKEN STRUCTUREの文字がなくなりiCloud Driveの同期が行われるようになった。

iCloudわからーん!

余談

M1 Mac miniを使ってみての感想だが、どの処理を行うにしても動作がスムーズで気に入った。移行元がiMac 5KのFusion Driveという点でそもそもSSD onlyとSSD + HDDでは比較にならないというのはあるかもしれないが…
そして移行作業も思ったほど大きな障壁はなさそうに感じた。M1 Macの販売から3ヶ月くらい経っているのでその間に色々なOSSやソフトウェアが早急に対応してくれていた点も大きい。 少なくとも開発環境においてはM1 Macは実用的なものになっているんじゃないかなと思っている。
ちなみにXcodeRosettaで動かせば従来のビルドとして走るのでフレームワークの対応が辛すぎる場合はRosettaメインに切り替えるのもアリ。シミュレータもx86_64で動く。ただネイティブの恩恵は得られなくなるけど。