Xcode から Bazel への移行

問題を報告 ソースを表示

このページでは、Bazel を使用して Xcode プロジェクトをビルドまたはテストする方法について説明します。Xcode と Bazel の違いと、Xcode プロジェクトを Bazel プロジェクトに変換する手順について説明しています。また、一般的なエラーに対処するためのトラブルシューティング ソリューションについても説明します。

Xcode と Bazel の違い

  • Bazel では、すべてのビルド ターゲットとその依存関係に加え、対応するビルド設定をビルドルールで明示的に指定する必要があります。

  • Bazel では、プロジェクトが依存するすべてのファイルがワークスペース ディレクトリ内にあるか、WORKSPACE ファイルでインポートとして指定されている必要があります。

  • Bazel を使用して Xcode プロジェクトをビルドする場合、BUILD ファイルが信頼できる情報源になります。Xcode でプロジェクトに携わっている場合は、BUILD ファイルを更新するたびに、rules_xcodeproj を使用して、BUILD ファイルと一致する新しいバージョンの Xcode プロジェクトを生成する必要があります。ターゲットへの依存関係の追加など、BUILD ファイルに対する特定の変更については、プロジェクトを再生成する必要がないため、開発時間を短縮できます。Xcode を使用しない場合は、bazel build コマンドと bazel test コマンドでビルドとテストを行うことができます。ただし、このガイドで後述する特定の制限があります。

始める前に

始める前に、次のことを行います。

  1. Bazel をインストールします(まだインストールしていない場合)。

  2. Bazel とそのコンセプトに詳しくない場合は、iOS アプリのチュートリアルをご覧ください。WORKSPACE ファイルと BUILD ファイルを含む Bazel ワークスペースと、ターゲット、ビルドルール、Bazel パッケージのコンセプトを理解している必要があります。

  3. プロジェクトの依存関係を分析して理解します。

プロジェクトの依存関係を分析する

Xcode とは異なり、Bazel では BUILD ファイル内のすべてのターゲットについて、すべての依存関係を明示的に宣言する必要があります。

外部依存関係の詳細については、外部依存関係の操作をご覧ください。

Bazel を使用した Xcode プロジェクトのビルドまたはテスト

Bazel を使用して Xcode プロジェクトをビルドまたはテストする手順は次のとおりです。

  1. WORKSPACE ファイルを作成する

  2. (試験運用版)SwiftPM の依存関係を統合する

  3. BUILD ファイルを作成します。

    a. アプリケーション ターゲットを追加する

    b. (省略可)テスト ターゲットを追加する

    c. ライブラリ ターゲットを追加する

  4. (省略可)ビルドを細かくする

  5. ビルドを実行する

  6. rules_xcodeproj を使用して Xcode プロジェクトを生成する

ステップ 1: WORKSPACE ファイルを作成する

新しいディレクトリに WORKSPACE ファイルを作成します。このディレクトリが Bazel ワークスペースのルートになります。プロジェクトで外部依存関係を使用しない場合は、このファイルは空にできます。プロジェクトがプロジェクトのディレクトリにないファイルまたはパッケージに依存している場合は、これらの外部依存関係を WORKSPACE ファイルに指定します。

ステップ 2: (試験運用版)SwiftPM の依存関係を統合する

swift_bazel を使用して SwiftPM の依存関係を Bazel ワークスペースに統合するには、次のチュートリアルで説明されているように、それらを Bazel パッケージに変換する必要があります。

ステップ 3: BUILD ファイルを作成する

ワークスペースと外部依存関係を定義したら、BUILD ファイルを作成して、Bazel にプロジェクトの構造を伝える必要があります。Bazel ワークスペースのルートに BUILD ファイルを作成し、次のようにプロジェクトの初期ビルドを行うように構成します。

ヒント: パッケージとその他の Bazel のコンセプトの詳細については、ワークスペース、パッケージ、ターゲットをご覧ください。

ステップ 3a: アプリケーション ターゲットを追加する

macos_application または ios_application ルール ターゲットを追加します。このターゲットは、それぞれ macOS または iOS のアプリケーション バンドルをビルドします。ターゲットでは、少なくとも次の項目を指定します。

  • bundle_id - バイナリのバンドル ID(リバース DNS パスの後にアプリ名が続く)。

  • provisioning_profile - Apple Developer アカウントからプロビジョニング プロファイル(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 はテスト出力をビルドしますが、テストは、rules_xcodeproj で生成されたプロジェクトを通じて Xcode 内で実行する必要があります。テスト ターゲットを次のように追加します。

  • macos_unit_test: macOS でライブラリ ベースとアプリケーション ベースの単体テストを実行します。

  • ios_unit_test: iOS でライブラリ ベースの単体テストを実行します。iOS シミュレータを必要とするテストの場合、Bazel はテスト出力をビルドしますが、テストは実行しません。rules_xcodeproj を使用して Xcode プロジェクトを生成し、Xcode 内からテストを実行する必要があります。

  • Xcode を使用して iOS シミュレータでユーザー インターフェース テストを実行するために必要な出力をビルドするための ios_ui_testrules_xcodeproj を使用して Xcode プロジェクトを生成し、Xcode 内からテストを実行する必要があります。Bazel では UI テストをネイティブに実行できません。

少なくとも、minimum_os_version 属性の値を指定します。bundle_identifierinfoplists などの他のパッケージ属性は、デフォルトで最もよく使用される値に設定されていますが、それらのデフォルトがプロジェクトと互換性があることを確認し、必要に応じて調整してください。iOS シミュレータを必要とするテストの場合は、test_host 属性の値として ios_application ターゲット名も指定します。

ステップ 3c: ライブラリ ターゲットを追加する

Objective-C ライブラリごとに objc_library ターゲットを追加し、アプリケーションやテストが依存する Swift ライブラリごとに swift_library ターゲットを追加します。

次のようにライブラリ ターゲットを追加します。

  • アプリケーション ライブラリ ターゲットを依存関係としてアプリケーション ターゲットに追加します。

  • テスト ライブラリ ターゲットをテスト ターゲットに依存関係として追加します。

  • srcs 属性に実装ソースをリストします。

  • hdrs 属性のヘッダーを一覧表示します。

さまざまなタイプのアプリケーションの既存のサンプルを、rules_apple のサンプル ディレクトリで直接参照できます。次に例を示します。

ビルドルールの詳細については、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: rules_xcodeproj を使用して Xcode プロジェクトを生成する

Bazel でビルドする場合、WORKSPACE ファイルと BUILD ファイルがビルドに関する信頼できる情報源になります。Xcode がこれを認識できるようにするには、rules_xcodeproj を使用して、Bazel 互換の Xcode プロジェクトを生成する必要があります。

トラブルシューティング

Bazel エラーは、更新を適用したときなど、選択した Xcode バージョンと同期しなくなったときに発生することがあります。Xcode でエラーが発生した場合は、次の方法をお試しください。たとえば、「Apple CROSSTOOL を使用するには、Xcode バージョンを指定する必要があります」。

  • Xcode を手動で実行し、利用規約に同意します。

  • Xcode select を使用して、正しいバージョンを指定し、ライセンスに同意して、Bazel の状態をクリアします。

  sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
  sudo xcodebuild -license
  bazel sync --configure
  • 問題が解決しない場合は、bazel clean --expunge を実行してみてください。