iOSアプリ開発のXcodeプロジェクト設定と仲良くなろう
🎄この記事はNAVITIME JAPAN Advent Calendar 2023の11日目の記事です。
こんにちは、かっしかしです。
ナビタイムジャパンでトラックカーナビのiOSアプリ開発を担当しています。
最近iOSアプリ開発を始めた人や、Xcodeのプロジェクト設定に見慣れてない人に読んでもらえると嬉しいです。
この記事はXcode15.0を元に作成しました。iOSアプリのプロジェクト設定を主に説明しています。
Xcodeのプロジェクト設定を開いてもわからない項目が多くてスルーしてしまったことはないでしょうか?また、エラーの内容を調べてプロジェクト設定を変更する必要が出てきた時、変更したらどうなってしまうのか不安になったりしたことはありませんか?
プロジェクト設定の項目を変更するとどのように作用するのかを知っておくことで、もし変更が必要になった際にも何をやっているのかを理解しながら進めることができます。また、ビルド実行時間を短縮したいと思った際に、自分のプロジェクトの設定がどのようになっているのかを知ることで、改善点を考えることができます。
Xcodeでサンプルプロジェクトを作成してみよう
手元のXcodeを開いて、新規のプロジェクトを作成しながら読み進めるとより理解が深まるかと思います。プロジェクトの作成方法は下記です。
Xcodeを開いて、File > New > Project…を選択
Project templateが表示されるので、iOSタブのAppを選択
Product Nameにプロジェクト名を入力
保存先を選択するとプロジェクトが作成される
プロジェクト設定からターゲットを追加してみよう
左側のペインからProject Navigator(一番左側)を開き、青色のプロジェクトアイコンを選択することで、プロジェクト設定を開きます。
Xcodeのプロジェクト設定は.xcodeprojファイルの記述がGUIで表現されています。プロジェクト設定を表示するとプロジェクトとターゲットの一覧が表示されます。
下はサンプルプロジェクトにいくつかターゲットを追加してみた図です。
試しに新しくターゲットを追加してみましょう。ここではUnit Test用のターゲットを追加します。他にもFramework, Widget Extensionなど色々と選択肢が表示されます。
TARGETSリストの下部の+ボタンでTarget templateを表示
Unit Testing Bundleを選択
Product Nameでターゲットの名前を入力
ターゲット、スキーム、コンフィギュレーションについて
先ほど作成したターゲットには、テンプレートリストに表示されるように、多数の種類があることがわかりました。それぞれ異なる種類の成果物を作成するターゲットがあるのです。ターゲットでビルド対象となるファイルやライブラリなどのインプットと、ビルドの成果物のアプトプットが設定されています。
コンフィギュレーションは、各種ビルド設定のまとまりです。デフォルトで開発時に使用するDebugと本番用に使用するReleaseが用意されています。
スキームは各アクション(Run, Test, Profile, Analyze, Archive)でどのターゲットをビルド対象とするか選択し、各アクションで利用するコンフィギュレーションを設定するものです。例えば、アプリターゲットのコンフィギュレーションを変更することで、Debugで検証用のアプリを作成するスキーム、Releaseで本番用のアプリを作成するスキームなどを用意できます。
実際にサンプルプロジェクトのスキーム設定を確認してみると、ビルドしたいターゲットとコンフィギュレーションが設定されていることが確認できます。
Xcodeエディターの上部のスキームをクリック
Edit Scheme…を選択
Buildを選択するとビルド対象のターゲットを確認できる
Runを選択するとBuild Configurationの項目にて設定されているコンフィギュレーションが確認できる
ターゲットの設定画面を開こう
ターゲットの設定画面は複数のタブで構成されています。それぞれのタブについて簡単に説明します。
General
サポート端末、OSバージョン、表示名称、バージョン設定、依存設定など様々な設定を行うことができます
Signing & Capabilities
主に証明書関連の設定を行います。Appleが提供するサービス(CloudKit、Game Center、アプリ内購入など)の利用設定もこちらから行うことができます
Resource Tags
On-Demand Resources機能のタグ文字列を管理することができます。容量の大きなリソースをアプリに同梱せず後からダウンロードできるようにする仕組みです
Info
Info.plistを確認することなどができます
Build Settings
ビルド設定を一覧できます。コンフィギュレーションごとに設定を行うことができます。後で詳しく見てみましょう
Build Phases
ビルド実行時に行う処理を記載することができます。こちらも後で設定を追加してみましょう
Build Rules
独自の拡張子のファイルをビルドする際の設定を行うことができます
この中でBuild SettingsとBuild Phasesについて詳しくみていきます。Build Settingsの項目数は多数あり、スルーしがちなタブ項目だと思うので、一度じっくり眺めてみましょう。
また、Build Phasesでは色々な設定が可能な一方、自分の感覚ではメンテナンスが行き届かないで不要な設定が残ってしまっていることが多い場所です。定期的に見直すと改善ポイントの発見があるかもしれません。
Build Settingsの一覧を眺めよう
プロジェクト設定のBuild Settingsからターゲットのビルド設定を変更することができます。
こちらからビルド設定の一覧が確認できます。
https://developer.apple.com/documentation/xcode/build-settings-reference
Xcodeからも、右側ペインのQuick Helpにて、それぞれのビルド設定の説明を表示することもできます。
設定項目はたくさんあって、全ては把握しきれません。私が触った経験のある設定項目について紹介します。
Architectures
成果物のCPUアーキテクチャの種類を設定できます。arm64, x86_64などが選択できます
Debug Information Format
クラッシュログを解析する際に必要なdSYMファイルを生成するかどうかを設定できます。Debugコンフィギュレーションのデフォルト設定では生成しないようになっています
私のプロジェクトではDebugでも不要なdSYMを生成する設定になっておりビルド時間が無駄になっていました
Swift Compiler Compilation Mode
Swiftファイルを再度ビルドする際の設定です。Incrementalにすると変更されたファイルのみがビルドされます。Whole Moduleは常に全てのファイルをビルド対象とします。
普段の開発ではIncrementalに設定しておくことで、開発時のビルド時間を短縮できます
Swift Compiler Other Swift Flags
Swiftコンパイラが認識できるフラグを設定することができます
コード内で検証用のコードとリリース用の処理を分岐したいときに、ここで設定したフラグを参照しています
現在はActive Compilation Conditionsを使う方が良さそうです(参考)
Build Phasesで好きなスクリプトを実行してみよう
Build Phasesにて、ビルド実行時に行うタスクを記載することができます。また、コンパイル対象のソースファイルや、依存するターゲットやフレームワーク、アプリに必要なリソースファイルをコピーする処理などもここに記載されています。
そして、自分で好きなスクリプトを追加することが可能です。試しに下記のように設定をしてみましょう。
Build Phases上部の+ボタンを押してNew Run Script Phaseを選択
最下部にRun Scriptという名前で項目が追加されるので、名前をクリックしてHello Script1に変更
項目はドラッグすることができるので、Compile Sourcesの前に移動
続いてもう一つScript Phaseを追加し、Hello Script2として設定
Shellを記載するテキストボックスに下記を記載
Hello Script1の項目に下記を記載
echo "Hello🚚"
Hello Script2の項目に下記を記載
echo "Hello🚚🚚"
そして、ビルドを実行します。すると、ビルドログは下図のような結果になりました。ビルドログは左側ペインの一番右側にある項目から確認することができます。
Hello Script1が実行された後、アプリターゲットのSwiftファイルのコンパイルが行われ、Hello Script2が実行されています。Build Phasesで設定した処理が上から順に実行されています。
ここで、私が実際に行っているBuild Phasesの処理を紹介します。皆さんのプロジェクトでもどのような処理が行われているのか確認してみてください。
R.swiftの実行
R.swiftによってリソースファイルを扱うようにしています。R.swiftはBuild Tool PluginによってSwift Package Managerで実行形式が取得できるのですが、XcodeCloudで実行するとエラーが発生してしまいます。(参考)
そこでshell実行でR.swift.generatedのファイル生成処理を行うようにしています。
SwiftLintの実行
Lintをビルド時に実行することで、早く修正点を開発者に知らせることができます。後述するのですが、対象ファイルを絞ることで実行時間を短縮するようにしています。
発展編:ビルド時間を短縮できるところを探そう
Intel Macで開発をしていた時代から比べると、Apple SiliconのMacでかなりビルド時間は早くなりましたが、まだまだ改善の余地はあるかもしれません。調査する方法を紹介します。
ビルドログを眺めると何か発見があるかもしれません。ビルドログでは、ビルドの開始から終了までのログが文字列で出力されます。また、よりグラフィカルにタイムラインを表示する機能がXcode14にて搭載されました。下図ではオレンジ色の部分が外部パッケージのコンパイル処理となっており、大部分を占めていることがわかります。また、コンパイルは並列に実行されるので複数のスレッドで表示されています。
ビルドログを左側ペインの一番右側にある項目から表示
右端のビュー表示切り替えボタンからAssistant ビューを表示(もしくはcontrol + option + command + enter)
ビルドログの特定の行を選択するとその行のタイムラインがフォーカスされる
ビルド時間短縮について考えてみよう
x86とarm64のビルド時間の差
ビルド設定のArchitecturesの項目と関連する内容です。
私のプロジェクトでは、XCFrameworkに対応していない社内ライブラリをM1 Macで使用する際にiPhone端末用のアプリビルドはarm64で行い、シミュレータ用のアプリビルドはx86で行うという設定を行いました。この時のx86向けのビルド時間が遅いことがわかりました。x86向けのビルドは内部的にRosseta2によって行われていると思いますが、その分だけオーバーヘッドがあるのかなと思います。
試しにサンプルプロジェクトにてArchitecturesの項目を変更してビルドを行ったところ、1秒ほどの差がありました。これはファイル数に応じて変化が大きくなるため、大きなプロジェクトほど影響を受けます。
XCFrameworkを使用することにより、シミュレータ用のアプリビルドでもarm64アーキテクチャでビルド実行ができるようになります。現在社内向けライブラリをXCFrameworkでビルドできるように対応中なので、今後は解決できると思います。
SwiftLintの対象を変更のあったファイルのみにする
ビルドログを見ていると、SwiftLintがコンパイル後に毎回実行されていることに気がつきました。SwiftLintの実行対象ファイルがプロジェクトのソース全体になっていたため、変更されていないファイルもLintの対象になっていたのです。そこでこちらの情報を参考にして、変更を行なったファイルのみをLintの対象にするようにしました。
手元のプロジェクトではLint処理に1.1秒かかっていた処理が0.7秒に短縮されました。この時間は対象ファイル数に応じて変動します。
Firebase CrashlyticsのdSYMアップロードの処理
公式ドキュメントではBuild PhasesにてdSYMファイルをアップロードするスクリプトを追加するようになっています。しかし、開発中にはCrashlyticsでクラッシュを解析する必要がないので、この処理は不要と考えました。
Build Phasesで実行することをやめて、代わりにCIにてアプリを作成するスクリプトにdSYMアップロード処理を追加しました。手元ではこのアップロード処理に0.1秒かかっていましたので、この分だけビルド時間を短縮できました。
コア数によるビルド並列化の影響
Macを新しくすればCPUの進化により、ビルドは高速化すると思いますが、CPUのコア数にも注目してみたいです。タイムライン表示にて確認したように、Xcodeは並列ビルドを行います。これはMacのコア数分並列実行されるため、コア数が多いMacならビルド時間への効果も高いことになります。Mac買い替えの際にはこちらも意識してみるとよいかもしれません。
いくつか紹介したビルド短縮の対応ですが、これらの対応は1回あたりの短縮時間はわずかでした。しかし、開発を続けていきビルドを何度も繰り返していくと大きな差になると思います。
そのほか改善点、気をつける点についてAppleがドキュメントを作成しています。
今回は、サンプルプロジェクトのプロジェクト設定を触ってみたり、実際にビルド時間を短縮する方法について紹介しました。この機会に、作業しているプロジェクト設定を見直してみてはいかがでしょうか。
Xcodeにより親しみを持って、皆さんのプロジェクトがより良いものになれば幸いです。