Build static frameworks to speed up app’s launch times
iOSのライブラリ管理ツールCarthage
の動的フレームワークを静的フレームワークにしてアプリ起動時間を短くした話
話すこと
本記事は、下記のCarthage
のDocumentsにある Build static frameworks to speed up app’s launch timesを実際に試してつまづいた点について話します。
先駆者がいらっしゃるので、そちらの記事もぜひ参考にしてください。
ざっくりした手順
- carthage update --platform ios --no-use-binaries
- ld.pyを設置
carthage-build-static.sh
を作成- chmod +x ~
- 静的フレームワークの作成
1. carthage update --platform ios --no-use-binaries
Documentsにも書いてある通り、--no-use-binaries
オプションを付けてcarthage update
する。
もともとあるバイナリデータを用いていると、依存?があったりして上手く静的フレームワークを作成できないらしい。
carthage update --platform ios --no-use-binaries
2. ld.pyを設置
Xcode 9以降(New Build System)を使っている方は必要ありません
下記からld.py
をDownloadし、Project内の好きな場所に置きます。
swift-staticlibs/ld.py at master · keith/swift-staticlibs · GitHub
3. carthage-build-static.sh
を作成
Xcode 9のNew Build Systemを使っているかで違います
New Build Systemを使っている方
#!/bin/sh -e xcconfig=$(mktemp /tmp/static.xcconfig.XXXXXX) trap 'rm -f "$xcconfig"' INT TERM HUP EXIT echo "MACH_O_TYPE = staticlib" >> $xcconfig echo "DEBUG_INFORMATION_FORMAT = dwarf" >> $xcconfig export XCODE_XCCONFIG_FILE="$xcconfig" carthage build "$@"
上記をcarthage-build-static.sh
として保存します。
issueに書いてあったものを参考にさせていただきました。
New Build Systemを使っていない方
#!/bin/sh -e xcconfig=$(mktemp /tmp/static.xcconfig.XXXXXX) trap 'rm -f "$xcconfig"' INT TERM HUP EXIT echo "LD = $PWD/the/path/to/ld.py" >> $xcconfig echo "DEBUG_INFORMATION_FORMAT = dwarf" >> $xcconfig export XCODE_XCCONFIG_FILE="$xcconfig" carthage build "$@"
上記をcarthage-build-static.sh
として保存します。
echo "LD = $PWD/the/path/to/ld.py" >> $xcconfig
その時に、PATHをld.py
を置いた場所に変更してください。
直下に置いた際は、$PWD/ld.py
になります。
4. chmod +x ~
実行権限を与えるため、コマンドを実行します。
chmod +x carthage-build-static.sh # ↓Xcode 8以前を使っている方は不要 chmod +x ld.py
5. 静的フレームワークの作成
まず、正しく静的フレームワークが作成できているか、1つのライブラリで確認します。
自分の場合はSnapKit
で試しました。
./carhage-build-static <Library名> --platform ios
実行後、Carthage/Build/iOS/Static/~
にFrameworkが生成されていれば成功です。(CarthageのDocumentにはStaticディレクトリ下に生成されると書いてありませんでした...)
静的なものかどうかは、
file Carthage/Build/iOS/Static/<Library名>.framework/<Library名>
このコマンドを打って下の様にcurrent ar archive
かどうかで確認できます。
確認できたら、CarthageでCarthage/Build/iOS/Static/~
にあるライブラリを追加しましょう。
carthage copy-frameworks
にあるInput Filesに動的フレームワークのPATHを登録している場合は、消しましょう。
更に、もともと作成していたCarthage/Build/iOS/~
にある動的フレームワークは削除しましょう。
削除しないと、動的のものを参照してしまいimage not found
のエラーが出てしまう可能性があります。
エラーが出ずに実行できたら、全てのライブラリに適用しましょう。
./carhage-build-static --platform ios
これを実行すれば、Carthageに登録しているライブラリ全ての静的フレームワークが作成されます。
あとは同様にアプリに登録するだけです。
注意する点
イメージリソースを使用しているライブラリは、静的フレームワークを使用できません。
具体的にはSVProgressHUD
がそうでした。作成は成功するのですが、Build時にエラーが出ます。
linker
エラーなどが出た際は、それが発生しているライブラリを動的なものに戻しましょう。
静的フレームワークが作成されない場合
このissueを参考にしてみてください。それでも作成できない場合はあきらめましょう...
結果
環境
Xcode - Version 10.0
Simulator - iPhoneXs MAX iOS 12.0
Time
Before(Dynamic) | After(Static) | |
---|---|---|
total pre-main time | 882.84 milliseconds (100.0%) | 794.82 milliseconds (100.0%) |
dylib loading time | 270.73 milliseconds (30.6%) | 233.54 milliseconds (29.3%) |
ebase/binding time | 248.72 milliseconds (28.1%) | 225.53 milliseconds (28.3%) |
objC setup time | 82.90 milliseconds (9.3%) | 77.49 milliseconds (9.7%) |
initializer time | 280.31 milliseconds (31.7%) | 258.05 milliseconds (32.4%) |
動的フレームワークを静的にしたので、表のdylib loading time
が大幅に減少するはずなのですが、
270msec -> 233msecとあまり大きな結果は得られませんでした。
大きめのアプリでもやってみましたが、参考の記事よりも大幅に減少する結果にはなりませんでした。
全てのライブラリを静的にできてないからでしょうか、それともNew Build Systemが上手くやっているおかげなのでしょうか...
Before | After | |
---|---|---|
total pre-main time | 2.7 seconds (100.0%) | 2.3 seconds (100.0%) |
dylib loading time | 706.75 milliseconds (25.6%) | 492.44 milliseconds (20.6%) |
ebase/binding time | 1.2 seconds (44.2%) | 1.1 seconds (46.4%) |
objC setup time | 164.16 milliseconds (5.9%) | 218.17 milliseconds (9.1%) |
initializer time | 666.76 milliseconds (24.1%) | 565.18 milliseconds (23.7%) |
終わりに
期待していたよりあまり効果がでず、うーん..という感じです。
CIなどを行なっている場合は、変更する努力に見合う成果が得られるか検討する必要がありそうですね。
参考
CarthageでStatic FrameworkとしてビルドしてiOSアプリの起動時間を短縮する – Ryoichi Izumita – Medium
Static frameworks - Task failed with exit code 65 · Issue #2425 · Carthage/Carthage · GitHub
Automatically change dynamic frameworks to static? · Issue #2575 · Carthage/Carthage · GitHub