Carthage 導入した理由から,色々変更した点について
1. Carthage 導入した理由
Xcode 10 からは new build system がデフォルトになっています。
それにより static framework 作るのに,ld.py
自体は不要になっていましたね。
今のプロジェクトは armv7s (iPhone 5, 5c) 向けにビルドを吐き出すため,そして O3 にするために微妙にコンパイルオプションもいじってビルドしています。
#!/bin/sh -e xcconfig=$(mktemp /tmp/static.xcconfig.XXXXXX) trap 'rm -f "$xcconfig"' INT TERM HUP EXIT echo "ARCHS=x86_64 armv7s arm64" >> $xcconfig echo "IPHONEOS_DEPLOYMENT_TARGET=10.0" >> $xcconfig echo "GCC_OPTIMIZATION_LEVEL=3" >> $xcconfig echo "MACH_O_TYPE=staticlib" >> $xcconfig echo "DEBUG_INFORMATION_FORMAT=dwarf" >> $xcconfig export XCODE_XCCONFIG_FILE="$xcconfig" carthage build "$@"
UI でしか使わない,UI ライブラリー系 PinLayout, Hero, Eureka と一部の層でしか使っていない CryptoSwift を static にしました。
なお static library を採用する理由はここらあたりを見てみるといいです。iPhone 5 とかだと顕著に差が出ます。
2. CI で 50% の確率で失敗する 45 分の壁。
なんか処理が早く終わったらうまくいってそうでない場合失敗するってわかりました。
armv7s と arm64 両方のコードを O3, Link-Time Optimization してるから仕方ないんですけども……
で,それが時間がかかりすぎるので,事前にビルドしてしまえばいいじゃないか! っていう理由で dynamic library として当面の間組み込むのも,Carthage でビルドしてしまいました。
まず,事前調査で
- RealmCocoa
- RealmSwift
- RxSwift
- RxSwiftExt
- RxGesture
- RxRealmDataSources (公式が Carthage 非対応なため,PierrePerrin氏の develop ブランチのものを採用した)
- Starscream
という感じで,赤字のものは static library 不可能でした。
とりあえずこれらを自前でビルドします。O3 かつ armv7s 対応のものとして。static library の Shell Script から MACH_O_TYPE
と DEBUG_INFORMATION_FORMAT
のオプション取り除くだけですね。
3. 結果
bitrise でのビルド時間が 19 分になりました!
もう少し早くしたいですね。ボトルネック解消すれば 12 分前後に収められるかな?
CocoaPods
- Fabric
- Crashlytics
- Starscream (Carthage でそもそもビルドが通らない)
- URLEncodedForm
Carthage (Static)
- CryptoSwift
- Eureka
- Hero
- PinLayout
- RxGesture
- RxSwiftExt
- RxRealmDataSources
Carthage (Dynamic)
- Realm (RealmCocoa, RealmSwift)
- RxSwift (RxAtomic, RxCocoa, RxSwift)
コマンド例
$ pod install $ carthage bootstrap --no-build --no-use-binaries $ ./carthage-build-static.sh CryptoSwift Eureka Hero PinLayout RxSwiftExt RxGesture RxRealmDataSources --platform ios $ ./carthage-build-dynamic.sh realm-cocoa RxSwift --platform ios --no-use-binaries
※ Realm や Rx はあらかじめバイナリーが用意されているようなので --no-use-binaries
した。結果的にファイルサイズ小さくなった気がする。
※ Rx 本体だけは dynamic と static が生成されますが,このオーバーヘッドは仕方ないです。めんどくさいので改善する気もないですがw
まとめ
事前ビルドしておけば,成果物のみのビルドとなり,CI での遅延も大幅に減らすことができます。
zip ファイルであらかじめ framework ファイルを準備しておく必要はありますが,基本的に少しの手間で,開発自体かなりスピードアップできるんじゃないんでしょうか?
また,iPhone XS, XS Max から arm64e という命令セットアーキテクチャーに対応していますが,これらへの対応も問題なくできますね。
具体的に知りたい人は ARMv8.3 とか見てみるといいかも。さわりだけでいい人は stackoverflow で