Bazel は、ワークスペースにないビルドで使用される外部依存関係(テキストとバイナリの両方のソースファイル)をサポートしています。たとえば、GitHub リポジトリでホストされているルールセット、Maven アーティファクト、現在のワークスペース外のローカルマシンのディレクトリなどです。
このドキュメントでは、システムの概要を説明してから、いくつかのコンセプトについて詳しく説明します。
システムの概要
Bazel の外部依存関係システムは、Bazel モジュール(それぞれがバージョニングされた Bazel プロジェクト)とリポジトリ(リポジトリ)に基づいて動作します。リポジトリは、ソースファイルを含むディレクトリ ツリーです。
Bazel は、作業中のプロジェクトであるルート モジュールから開始します。他のすべてのモジュールと同様に、ディレクトリのルートに MODULE.bazel
ファイルがあり、基本的なメタデータと直接依存関係を宣言する必要があります。基本的な例を次に示します。
module(name = "my-module", version = "1.0")
bazel_dep(name = "rules_cc", version = "0.1.1")
bazel_dep(name = "platforms", version = "0.0.11")
Bazel は、そこから Bazel レジストリ(デフォルトでは Bazel Central Registry)ですべての推移的依存関係モジュールを検索します。レジストリは依存関係の MODULE.bazel
ファイルを提供します。これにより、Bazel はバージョン解決を実行する前に、完全な伝播依存関係グラフを検出できます。
バージョン解決後(モジュールごとに 1 つのバージョンが選択されます)、Bazel はレジストリに再度問い合わせて、各モジュールの repo を定義する方法(つまり、各依存関係モジュールのソースを取得する方法)を学習します。ほとんどの場合、これらはインターネットからダウンロードして解凍したアーカイブにすぎません。
モジュールでは、タグと呼ばれるカスタマイズされたデータも指定できます。このタグは、モジュールの解決後にモジュール拡張機能によって使用され、追加のリポジトリを定義します。これらの拡張機能は、ファイル I/O やネットワーク リクエストの送信などのアクションを実行できます。たとえば、Bazel は Bazel モジュールから構築された依存関係グラフを尊重しながら、他のパッケージ管理システムとやり取りできます。
3 種類のリポジトリ(メイン リポジトリ(作業中のソースツリー)、伝播依存関係モジュールを表すリポジトリ、モジュール拡張機能によって作成されたリポジトリ)が、一緒にワークスペースを形成します。外部リポジトリ(メイン以外のリポジトリ)は、BUILD ファイルのラベル(@repo//pkg:target
など)によって参照された場合など、オンデマンドでフェッチされます。
利点
Bazel の外部依存関係システムには、さまざまなメリットがあります。
依存関係の自動解決
- 確定的なバージョン解決: Bazel は確定的な MVS バージョン解決アルゴリズムを採用し、競合を最小限に抑え、ダイアモンド依存関係の問題に対処します。
- 依存関係管理の簡素化:
MODULE.bazel
は直接依存関係のみを宣言し、転送依存関係は自動的に解決されるため、プロジェクトの依存関係の概要を明確に把握できます。 - 厳格な依存関係の可視性: 直接依存関係のみが公開され、正確性と予測可能性が確保されます。
エコシステムの統合
- Bazel Central Registry: 一般的な依存関係を Bazel モジュールとして検出して管理するための一元化されたリポジトリ。
- Bazel 以外のプロジェクトの採用: Bazel 以外のプロジェクト(通常は C++ ライブラリ)を Bazel 用に適合させ、BCR で利用できるようにすると、コミュニティ全体の統合が効率化され、カスタム BUILD ファイルの重複作業や競合が排除されます。
- 言語固有のパッケージ マネージャーとの統合の統一: ルールセットにより、Bazel 以外の依存関係の外部パッケージ マネージャーとの統合が合理化されます。たとえば、次のような依存関係です。
- Maven の場合は rules_jvm_external
- PyPi の場合は rules_python
- Go モジュールの場合は bazel-gazelle
- Cargo の場合は rules_rust。
高度な機能
- モジュール拡張機能:
use_repo_rule
とモジュール拡張機能を使用すると、カスタム リポジトリ ルールと解決ロジックを柔軟に使用して、Bazel 以外の依存関係を導入できます。 bazel mod
コマンド: このサブコマンドを使用すると、外部依存関係を強力に検査できます。外部依存関係の定義方法とその出所を正確に把握できます。- ベンダーモード: オフライン ビルドを容易にするために、必要な外部依存関係を正確にプリフェッチします。
- Lockfile: ロックファイルを使用すると、ビルドの再現性が向上し、依存関係の解決が高速化されます。
- (近日提供予定)BCR 来歴構成証明: 依存関係の検証済みの来歴を確保することで、サプライ チェーンのセキュリティを強化します。
コンセプト
このセクションでは、外部依存関係に関連するコンセプトについて詳しく説明します。
モジュール
複数のバージョンを持つことができる Bazel プロジェクト。各バージョンは他のモジュールに依存できます。
ローカルの Bazel ワークスペースでは、モジュールはリポジトリで表されます。
詳細については、Bazel モジュールをご覧ください。
リポジトリ
ルートに境界マーカー ファイルがあり、Bazel ビルドで使用できるソースファイルを含むディレクトリ ツリー。多くの場合、repo と省略されます。
リポジトリ境界マーカー ファイルは、MODULE.bazel
(このリポジトリが Bazel モジュールを表すことを示す)、REPO.bazel
(下記を参照)、または以前のコンテキストでは WORKSPACE
または WORKSPACE.bazel
です。リポジトリ境界マーカー ファイルは、リポジトリの境界を表します。このようなファイルはディレクトリ内に複数存在できます。
メイン リポジトリ
現在の Bazel コマンドが実行されているリポジトリ。
メイン リポジトリのルートは、ワークスペース ルートとも呼ばれます。
ワークスペース
すべての Bazel コマンドで共有される環境は、同じメイン リポジトリで実行されます。メイン リポジトリと、定義されたすべての外部リポジトリのセットを含みます。
歴史的に、「リポジトリ」と「ワークスペース」の概念は混同されてきました。「ワークスペース」という用語は、メイン リポジトリを指すためによく使用され、「リポジトリ」の同義語として使用されることもあります。
正規リポジトリ名
リポジトリがアドレス指定できる正規名。ワークスペースのコンテキスト内で、各リポジトリには単一の正規名があります。正規名が canonical_name
であるリポジトリ内のターゲットは、ラベル @@canonical_name//package:target
で参照できます(@
が 2 つあります)。
メイン リポジトリの正規名は常に空の文字列です。
リポジトリ名
特定の他のリポジトリのコンテキストでリポジトリがアドレス指定できる名前。これはリポジトリの「ニックネーム」と考えることができます。正規名が michael
のリポジトリは、リポジトリ alice
のコンテキストでは mike
という表示名を持つ場合がありますが、リポジトリ bob
のコンテキストでは mickey
という表示名を持つ場合があります。この場合、michael
内のターゲットは、alice
のコンテキストでラベル @mike//package:target
で参照できます(単一の @
に注意してください)。
逆に、これはリポジトリ マッピングとして理解できます。各リポジトリは、「見かけ上のリポジトリ名」から「正規のリポジトリ名」へのマッピングを維持します。
リポジトリ ルール
リポジトリの定義のスキーマ。リポジトリのマテリアライズ方法を Bazel に指示します。たとえば、「特定の URL から ZIP アーカイブをダウンロードして解凍する」、「特定の Maven アーティファクトを取得して java_import
ターゲットとして利用できるようにする」、「ローカル ディレクトリをシンボリック リンクする」などです。すべてのリポジトリは、適切な数の引数を指定してリポジトリ ルールを呼び出すことで定義されます。
独自のリポジトリ ルールを作成する方法については、リポジトリ ルールをご覧ください。
最も一般的なリポジトリ ルールは、URL からアーカイブをダウンロードして解凍する http_archive
と、すでに Bazel リポジトリであるローカル ディレクトリをシンボリック リンクする local_repository
です。
リポジトリを取得する
関連するリポジトリ ルールを実行して、ローカルディスクでリポジトリを使用可能にするアクション。ワークスペースで定義されたリポジトリは、フェッチされるまでローカルディスクでは使用できません。
通常、Bazel は、リポジトリから何かが必要で、リポジトリがまだフェッチされていない場合にのみ、リポジトリをフェッチします。リポジトリがすでにフェッチされている場合、Bazel は定義が変更された場合にのみ再フェッチします。
fetch
コマンドを使用すると、リポジトリ、ターゲット、またはビルドの実行に必要なすべてのリポジトリのプリフェッチを開始できます。この機能により、--nofetch
オプションを使用してオフライン ビルドが可能になります。
--fetch
オプションは、ネットワーク アクセスを管理するために使用します。デフォルト値は true です。ただし、false(--nofetch
)に設定すると、キャッシュに保存されている依存関係のバージョンが使用されます。存在しない場合、コマンドは失敗します。
フェッチの制御の詳細については、フェッチ オプションをご覧ください。
ディレクトリ レイアウト
フェッチされたリポジトリは、出力ベースのサブディレクトリ external
の正規名で確認できます。
次のコマンドを実行すると、正規名 canonical_name
のリポジトリの内容を確認できます。
ls $(bazel info output_base)/external/ canonical_name
REPO.bazel ファイル
REPO.bazel
ファイルは、リポジトリを構成するディレクトリ ツリーの最上位の境界をマークするために使用されます。リポジトリ境界ファイルとして機能するものは何も含める必要はありませんが、リポジトリ内のすべてのビルド ターゲットに共通の属性を指定するために使用することもできます。
REPO.bazel
ファイルの構文は BUILD
ファイルと似ていますが、load
ステートメントがサポートされていない点が異なります。repo()
関数は、BUILD
ファイルの package()
関数と同じ引数を受け取ります。package()
はパッケージ内のすべてのビルド ターゲットに共通の属性を指定しますが、repo()
はリポジトリ内のすべてのビルド ターゲットに同様に共通の属性を指定します。
たとえば、次の REPO.bazel
ファイルを作成すると、リポジトリ内のすべてのターゲットに共通のライセンスを指定できます。
repo(
default_package_metadata = ["//:my_license"],
)
以前の WORKSPACE システム
古いバージョンの Bazel(9.0 より前)では、WORKSPACE
(または WORKSPACE.bazel
)ファイルでリポジトリを定義することで外部依存関係が導入されました。このファイルの構文は BUILD
ファイルと似ており、ビルドルールではなくリポジトリ ルールを使用します。
次のスニペットは、WORKSPACE
ファイルで http_archive
リポジトリ ルールを使用する例です。
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "foo",
urls = ["https://example.com/foo.zip"],
sha256 = "c9526390a7cd420fdcec2988b4f3626fe9c5b51e2959f685e8f4d170d1a9bd96",
)
このスニペットは、正規名が foo
の repo を定義します。WORKSPACE
システムでは、デフォルトで、リポジトリの正規名は他のすべてのリポジトリに対する表示名でもあります。
WORKSPACE
ファイルで使用可能な関数の一覧をご覧ください。
WORKSPACE
システムの欠点
WORKSPACE
システムの導入後、ユーザーから次のような多くの問題が報告されました。
- Bazel は依存関係の
WORKSPACE
ファイルを評価しないため、直接依存関係に加えて、すべての伝播依存関係をメイン リポジトリのWORKSPACE
ファイルで定義する必要があります。 - この問題を回避するため、プロジェクトでは「deps.bzl」パターンを採用しています。このパターンでは、複数のリポジトリを定義するマクロを定義し、ユーザーに
WORKSPACE
ファイルでこのマクロを呼び出すよう求めます。- これには独自の問題があります。マクロは他の
.bzl
ファイルをload
できないため、これらのプロジェクトは、この「deps」マクロで伝播依存関係を定義するか、ユーザーが複数のレイヤ化された「deps」マクロを呼び出すようにすることで、この問題を回避する必要があります。 - Bazel は
WORKSPACE
ファイルを順番に評価します。また、依存関係は、バージョン情報なしで URL を指定してhttp_archive
を使用して指定します。つまり、ダイアモンド依存関係の場合、バージョン解決を実行する信頼できる方法はありません(A
はB
とC
に依存し、B
とC
はどちらも異なるバージョンのD
に依存しています)。
- これには独自の問題があります。マクロは他の
WORKSPACE の欠点により、新しいモジュールベースのシステム(コードネーム「Bzlmod」)が、Bazel 6 から 9 の間に従来の WORKSPACE システムに徐々に置き換えられました。Bzlmod への移行方法については、Bzlmod 移行ガイドをご覧ください。