このページでは、Bazel を使用して Xcode プロジェクトをビルドまたはテストする方法について説明します。Xcode と Bazel の違いと、Xcode プロジェクトを Bazel プロジェクトに変換する手順について説明します。また、一般的なエラーに対処するためのトラブルシューティング ソリューションも提供しています。
Xcode と Bazel の違い
Bazel では、すべてのビルド ターゲットとその依存関係、およびビルドルールを介して対応するビルド設定を明示的に指定する必要があります。
Bazel では、プロジェクトが依存するすべてのファイルがワークスペース ディレクトリ内にあるか、
WORKSPACE
ファイルでインポートとして指定されている必要があります。Bazel で Xcode プロジェクトをビルドする場合、
BUILD
ファイルが信頼できる情報源になります。Xcode でプロジェクトを操作する場合は、BUILD
ファイルを更新するたびに、Tulsi を使用して、BUILD
ファイルと一致する新しいバージョンの Xcode プロジェクトを生成する必要があります。Xcode を使用していない場合は、bazel build
コマンドとbazel test
コマンドを使用してビルドとテストを行うことができますが、このガイドで後述する特定の制限があります。ディレクトリ レイアウトやビルドフラグなど、ビルド構成スキーマの違いにより、Xcode がビルドの「全体像」を完全に認識できないため、Xcode の一部の機能が動作しないことがあります。以下を挙げています。
Tulsi で変換に選択したターゲットによっては、Xcode がプロジェクト ソースを適切にインデックスに登録できない場合があります。Xcode ではプロジェクトのソースコードをすべて表示できないため、Xcode のコード補完とナビゲーションに影響します。
Bazel は、これらの機能に対して Xcode が想定する出力を生成しないため、静的分析、アドレス サニタイザー、スレッド サニタイザーが機能しない可能性があります。
Tulsi で Xcode プロジェクトを生成し、そのプロジェクトを使用して Xcode 内からテストを実行すると、Bazel ではなく Xcode がテストを実行します。Bazel でテストを実行するには、
bazel test
コマンドを手動で実行します。
始める前に
始める前に、次のことを行います。
まだインストールしていない場合は、Bazel をインストールします。
Bazel とそのコンセプトに慣れていない場合は、iOS アプリのチュートリアルを完了してください。
WORKSPACE
ファイルとBUILD
ファイルを含む Bazel ワークスペース、ターゲット、ビルドルール、Bazel パッケージのコンセプトを理解する必要があります。プロジェクトの依存関係を分析して把握する。
プロジェクトの依存関係を分析する
Xcode とは異なり、Bazel では、BUILD
ファイル内のすべてのターゲットのすべての依存関係を明示的に宣言する必要があります。
外部依存関係の詳細については、外部依存関係の操作をご覧ください。
Bazel を使用して Xcode プロジェクトをビルドまたはテストする
Bazel を使用して Xcode プロジェクトをビルドまたはテストする手順は次のとおりです。
ステップ 1: WORKSPACE
ファイルを作成する
新しいディレクトリに WORKSPACE
ファイルを作成します。このディレクトリが Bazel ワークスペースのルートになります。プロジェクトで外部依存関係を使用していない場合は、このファイルを空にできます。プロジェクトがプロジェクトのディレクトリにないファイルまたはパッケージに依存している場合は、これらの外部依存関係を WORKSPACE
ファイルに指定します。
ステップ 2: (試験運用版)CocoaPods の依存関係を統合する
CocoaPods の依存関係を Bazel ワークスペースに統合するには、CocoaPods の依存関係の変換で説明されているように、それらを Bazel パッケージに変換する必要があります。
ステップ 3: BUILD
ファイルを作成する
ワークスペースと外部依存関係を定義したら、プロジェクトの構造を Bazel に伝える BUILD
ファイルを作成する必要があります。Bazel ワークスペースのルートに BUILD
ファイルを作成し、次のようにプロジェクトの初期ビルドを行うように構成します。
ヒント: パッケージとその他の Bazel コンセプトの詳細については、ワークスペース、パッケージ、ターゲットをご覧ください。
ステップ 3a: アプリケーション ターゲットを追加する
macos_application
または ios_application
ルール ターゲットを追加します。このターゲットは、それぞれ macOS または iOS のアプリケーション バンドルをビルドします。ターゲットには、少なくとも次の項目を指定します。
bundle_id
- バイナリのバンドル ID(リバース DNS パスとアプリ名)。provisioning_profile
- Apple デベロッパー アカウントのプロビジョニング プロファイル(iOS デバイス用にビルドする場合)。families
(iOS のみ)- iPhone、iPad、またはその両方用にアプリケーションをビルドするかどうか。infoplists
- 最終的な Info.plist ファイルに統合する .plist ファイルのリスト。minimum_os_version
- アプリがサポートする macOS または iOS の最小バージョン。これにより、Bazel は正しい API レベルでアプリケーションをビルドします。
ステップ 3b:(省略可)テスト対象を追加する
Bazel の Apple ビルドルールは、iOS と macOS でのライブラリベースの単体テストの実行と、macOS でのアプリケーション ベースのテストに対応しています。iOS のアプリケーション ベースのテストまたはどちらかのプラットフォームの UI テストの場合、Bazel はテスト出力をビルドしますが、テストは Tulsi で生成されたプロジェクトを介して Xcode 内で実行する必要があります。次のようにテスト ターゲットを追加します。
macos_unit_test
: macOS でライブラリベースとアプリケーションベースの単体テストを実行します。ios_unit_test
: iOS でライブラリベースの単体テストを実行します。iOS シミュレータが必要なテストの場合、Bazel はテスト出力をビルドしますが、テストは実行しません。Tulsi で Xcode プロジェクトを生成し、Xcode 内からテストを実行する必要があります。ios_ui_test
: Xcode を使用して iOS シミュレータでユーザー インターフェース テストを実行するために必要な出力をビルドします。Tulsi で Xcode プロジェクトを生成し、Xcode 内からテストを実行する必要があります。Bazel は UI テストをネイティブに実行できません。
少なくとも、minimum_os_version
属性の値を指定します。bundle_identifier
や infoplists
などの他のパッケージング属性は、デフォルトで最もよく使用される値に設定されますが、これらのデフォルトがプロジェクトと互換性があることを確認し、必要に応じて調整します。iOS シミュレータが必要なテストの場合は、test_host
属性の値として ios_application
ターゲット名も指定します。
ステップ 3c: ライブラリ ターゲットを追加する
Objective-C ライブラリごとに objc_library
ターゲットを追加し、アプリケーションやテストが依存する Swift ライブラリごとに swift_library
ターゲットを追加します。
ライブラリ ターゲットを次のように追加します。
アプリケーション ライブラリ ターゲットをアプリケーション ターゲットの依存関係として追加します。
テスト ライブラリ ターゲットをテスト ターゲットの依存関係として追加します。
実装ソースを
srcs
属性にリストします。hdrs
属性のヘッダーを一覧表示します。
ビルドルールの詳細については、Bazel の Apple ルールをご覧ください。
この時点で、ビルドをテストすることをおすすめします。
bazel build //:<application_target>
ステップ 4:(省略可)ビルドを細分化する
プロジェクトが大きい場合や、プロジェクトのサイズが増加している場合は、複数の Bazel パッケージに分割することを検討してください。粒度を細かくすることで、次のメリットが得られます。
ビルドの増分性の向上
ビルドタスクの並列処理の増加
将来のユーザーによるメンテナンス性の向上
ターゲットとパッケージ全体でソースコードの可視性をより適切に制御できる。これにより、実装の詳細を含むライブラリが公開 API に漏洩するなどの問題を防ぐことができます。
プロジェクトを細分化する際のヒント:
各ライブラリを独自の Bazel パッケージに配置します。依存関係が最も少ないものから依存関係ツリーを上に向かって確認します。
BUILD
ファイルを追加してターゲットを指定する際は、これらの新しいターゲットを、それらに依存するターゲットのdeps
属性に追加します。glob()
関数はパッケージの境界を越えないため、パッケージの数が増えると、glob()
で一致するファイルは減少します。BUILD
ファイルをmain
ディレクトリに追加する場合は、対応するtest
ディレクトリにもBUILD
ファイルを追加します。パッケージ全体に正常な公開設定の上限を適用します。
BUILD
ファイルに大きな変更を加えた後は、プロジェクトをビルドし、ビルドエラーが発生したら修正します。
ステップ 5: ビルドを実行する
完全に移行されたビルドを実行し、エラーや警告なしで完了することを確認します。すべてのアプリとテスト ターゲットを個別に実行すると、発生したエラーの原因を簡単に見つけることができます。
次に例を示します。
bazel build //:my-target
ステップ 6: Tulsi で Xcode プロジェクトを生成する
Bazel でビルドする場合、WORKSPACE
ファイルと BUILD
ファイルがビルドに関する信頼できる情報源になります。Xcode にこのことを認識させるには、Tulsi を使用して Bazel 互換の Xcode プロジェクトを生成する必要があります。
トラブルシューティング
Bazel エラーは、更新を適用するなど、選択した Xcode バージョンと同期が取れなくなる場合に発生することがあります。Xcode で「Apple CROSSTOOL を使用するには Xcode バージョンを指定する必要があります」などのエラーが発生した場合は、次の手順をお試しください。
Xcode を手動で実行し、利用規約に同意します。
Xcode 選択を使用して、正しいバージョンを指定します。ライセンスを承認し、Bazel の状態を消去します。
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
sudo xcodebuild -license
bazel sync --configure
- それでも問題が解決しない場合は、
bazel clean --expunge
の実行も試してください。