Edited at

iOSのビルド高速化 7つの方法


1.並列ビルド

ターミナルで、defaults write com.apple.dt.Xcode IDEBuildOperationMaxNumberOfConcurrentCompileTasks 4 を実行。

これはよく出てくる対策です。


2.Build Active Architecture Only

XcodeのTarget→Build Setting→Build Active Architecture OnlyDebugだけYESにしましょう。

これをすると、ビルドしたい端末に最適なアーキテクチャでのみビルドしてくれます。

NOにすると、すべてのアーキテクチャでビルドして全最適化を行われます。

不要なアーキテクチャのビルド分時間がかかるということです。

※Releaseでは必ずNOにしましょう。


3.Find Implicit Dependencies

ビルドしたいターゲットのEdit Scheme → Buildで設定できます。

これのチェックを外しましょう。

チェックがあると、自動的に依存ライブラリとしてビルドされるようになるので、自分でLink with Librariesにライブラリを追加したりしなくて済みます。

ただ、一度Podsなどの依存ライブラリをビルドしてしまえば、依存ライブラリとして認識されてるので、毎回ビルドする意味はありませんので、チェックを外します。

※pod install/update後は、必ず一回チェックもどしてからビルドするようにしましょう。


4.Embedded Framework

Utility系や、独自に編集したライブラリなどをEmbbed Frameworkで切り出しましょう。

差分コンパイルが効きやすくなり、コンパイル時間が短縮されます。

ld: warning: object file () was built for newer iOS version (9.3) than being linked (8.0)

上記のようなwarningは、作成したフレームワークのDeployment Targetが、アプリのターゲットと、Podfileに記述してるPlatformと一致してないために出るものです。

一致させればwarningが出なくなります。


5.Run Script Phaseをスキップ

Run Scriptでは、ビルド時にCocoaPodsやCarthageで導入したフレームワークを毎回コピーしています。使ってるフレームワークが多ければ多いほど、Run Scriptの時間が増え、ビルド時間がどんどん増えていくわけです。

一度これを行えば、Derived Dataにコピーされてるので、毎回実行しなくていいのです。

Target→Build PhaseにあるそれぞれのRun Script Phaseの設定で、Run script only when installingというのがあります。

これのチェックを入れると、最初のインストール時のみに実行されるようになります。

ただし、PodsやCarthageでライブラリを追加・更新などを行うと、それをコピーしないとビルドに失敗するため、毎回このチェックを外し直さないといけなくなります。

Podsを更新したときに、Run script only when installingにチェックを外し、一度ビルドするとチェックを入れるようにすると便利そうです。

以下のサイトを参考にしました。

https://medium.com/@r.izumita/speed-up-building-on-xcode-by-stopping-run-script-phases-361579a8ba8d#.tjmvql7go

やることは、

1.Run script only when installingのチェックを入れたり、外したりするスクリプトを作成

2. Podfileに、上記のスクリプトを使ってチェックを外すようにする

3. 上記のスクリプトを使ってチェックを入れなおすスクリプトを、ビルド後に実行させる

2について、私は以下のようなコードを、Podfileの一番最後に追記しました。

require 'open3'

Open3.capture3("ruby update_run_script_setting.rb --no-only --project=プロジェクト.xcodeproj --target=ターゲット --phases='[CP] Embed Pods Frameworks','[CP] Copy Pods Resources','Copy Carthage Framework'")

3については、Edit Scheme → Build → Post Actionsに以下のコードを追加しました。

cd $SRCROOT;

ruby update_run_script_setting.rb --only --project=プロジェクト.xcodeproj --target=ターゲット --phases='[CP] Embed Pods Frameworks','[CP] Copy Pods Resources','Copy Carthage Framework'


6.Podsをやめて、Carthageにする

Carthageにすると、ライブラリを事前にビルドしておくため、その分早くなります。

参考: Carthageを使ってビルド時間を短縮しよう


7.コードを見直す

Target -> Build Settings -> Other Swift Flag ni -Xfrontend-warn-long-function-bodies=閾値を追加します。

例えば、閾値のところを100とすると、100ms時間がかかってるコードにwarningが表示されて、どこに処理に時間がかかってるのかがわかるようになります。

参考: コンパイルに時間がかかるSwiftのコードへWarningを発生させる

また、warningが出るのも遅い原因になるため、地道にwarningを直していきましょう。

型推論も遅い原因になります。

ArrayやDictionaryで型を指定しないと、その分コンパイラが型を推測する必要があるため遅くなるようです。

私もswiftでArrayとDictionaryを多用していたクラスファイルがあったのですが、型を指定してあげると、そのファイルでかかってるコンパイル時間が短くなりました。

参考: 激遅Swiftのコンパイル時間が75%ほど短縮したお話

追記: 6/23に投稿されたCyberAgentさんの記事もおもしろい


Twitterはこちら

https://twitter.com/aiueoieru