Bazel は、ビルドで使用される、ワークスペース以外のソースファイル(テキストとバイナリの両方)である外部依存関係をサポートしています。たとえば、GitHub リポジトリでホストされているルールセット、Maven アーティファクト、現在のワークスペース以外のローカルマシン上のディレクトリなどがこれに該当します。
Bazel 6.0 では、Bazel で外部依存関係を管理する方法が 2 つあります。リポジトリを中心とした従来の WORKSPACE
システムと、モジュール中心の MODULE.bazel
システム(コードネーム Bzlmod、--enable_bzlmod
フラグで有効化)です。この 2 つのシステムは一緒に使用できますが、今後の Bazel リリースでは Bzlmod が WORKSPACE
システムに代わるものです。移行ガイド(Bzl0)をご覧ください。{/1Bzl0}
このドキュメントでは、Bazel での外部依存関係の管理に関するコンセプトについて説明してから、2 つのシステムを順番に詳しく説明します。
概念
リポジトリ
ルートに境界マーカー ファイルがあるディレクトリ ツリー。Bazel ビルドで使用できるソースファイルが含まれています。多くの場合、単に「repo」と省略されます。
リポジトリの境界マーカー ファイルは、MODULE.bazel
(このリポジトリが Bazel モジュールを表すことを示す)、REPO.bazel
(下記を参照)、レガシー コンテキストでは WORKSPACE
または WORKSPACE.bazel
のいずれかです。リポジトリの境界マーカー ファイルは、リポジトリの境界を示します。このようなファイルは 1 つのディレクトリに複数存在できます。
メイン リポジトリ
現在の Bazel コマンドが実行されているリポジトリ。
メイン リポジトリのルートは、ワークスペース ルートとも呼ばれます。
ワークスペース
すべての Bazel コマンドで共有される環境は、同じメイン リポジトリで実行されます。メイン リポジトリと、定義済みのすべての外部リポジトリのセットが含まれています。
従来、「リポジトリ」と「ワークスペース」のコンセプトは混同されてきました。「ワークスペース」という用語はメイン リポジトリを指すことが多く、場合によっては「リポジトリ」の同義語として使用されることさえあります。
正規リポジトリ名
リポジトリのアドレスに使用できる正規名。ワークスペースのコンテキスト内では、各リポジトリに正規名が 1 つ割り当てられます。正規名が canonical_name
であるリポジトリ内のターゲットは、ラベル @@canonical_name//pac/kage:target
でアドレスを指定できます(@
が二重になっていることに注意してください)。
メイン リポジトリには、正規名として常に空の文字列があります。
見かけのリポジトリ名
リポジトリが他のリポジトリのコンテキストでアドレス指定可能な名前。これは、リポジトリのニックネームと考えることができます。正規名 michael
のリポジトリは、リポジトリ alice
のコンテキストでは見かけ上の名前 mike
を持つことがありますが、リポジトリ bob
のコンテキストでは見かけ上の名前 mickey
になることがあります。この場合、michael
内のターゲットは、alice
のコンテキストでラベル @mike//pac/kage:target
でアドレス指定できます(単一の @
に注意してください)。
逆に、これはリポジトリ マッピングと捉えることもできます。各リポジトリは「見かけ上のリポジトリ名」から「正規のリポジトリ名」へのマッピングを維持しています。
リポジトリ ルール
リポジトリの実体化方法を Bazel に指示するリポジトリ定義のスキーマ。たとえば、「特定の URL から zip アーカイブをダウンロードして抽出する」、「特定の Maven アーティファクトを取得して java_import
ターゲットとして使用できるようにする」、「ローカル ディレクトリのシンボリック リンク」などです。すべてのリポジトリは、適切な数の引数を指定してリポジトリ ルールを呼び出すことによって定義されます。
独自のリポジトリ ルールを作成する方法の詳細については、リポジトリ ルールをご覧ください。
最も一般的なリポジトリルールは、URL からアーカイブをダウンロードして抽出する http_archive
と、すでに Bazel リポジトリとなっているローカル ディレクトリにシンボリック リンクを設定する local_repository
です。
リポジトリを取得する
関連するリポジトリルールを実行して、リポジトリをローカル ディスクで使用できるようにするアクション。ワークスペースで定義されたリポジトリは、取得前はローカル ディスクで使用できません。
通常、Bazel はリポジトリから何かが必要で、リポジトリがまだフェッチされていない場合にのみリポジトリを取得します。リポジトリがすでに取得されている場合、Bazel は定義が変更された場合にのみ再取得します。
fetch
コマンドを使用すると、1 つのリポジトリ、ターゲット、またはビルドの実行に必要なすべてのリポジトリのプリフェッチを開始できます。この機能により、--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()
は 1 つだけです。repo()
は、BUILD
ファイルの package()
関数と同じ引数を取ります。package()
はパッケージ内のすべてのビルド ターゲットに共通の属性を指定しますが、repo()
は同様にリポジトリ内のすべてのビルド ターゲットに共通属性を指定します。
たとえば、次の REPO.bazel
ファイルを使用すると、リポジトリ内のすべてのターゲットに共通のライセンスを指定できます。
repo(
default_package_metadata = ["//:my_license"],
)
Bzlmod で外部依存関係を管理する
新しい外部依存関係サブシステムである Bzlmod は、リポジトリ定義で直接機能しません。代わりに、モジュールから依存関係グラフを作成し、グラフに対して拡張機能を実行して、それに応じてリポジトリを定義します。
Bazel モジュールは、複数のバージョンを持つことができる Bazel プロジェクトです。各バージョンでは、依存する他のモジュールに関するメタデータがパブリッシュされます。モジュールのリポジトリ ルート(WORKSPACE
ファイルと同じ場所)に MODULE.bazel
ファイルが必要です。このファイルはモジュールのマニフェストであり、名前、バージョン、依存関係のリストなどの情報を宣言します。基本的な例を次に示します。
module(name = "my-module", version = "1.0")
bazel_dep(name = "rules_cc", version = "0.0.1")
bazel_dep(name = "protobuf", version = "3.19.0")
モジュールは、Bzlmod が Bazel レジストリ(デフォルトでは Bazel Central レジストリ)で検索する直接的な依存関係のみをリストする必要があります。このレジストリは依存関係の MODULE.bazel
ファイルを提供します。これにより、バージョンの解決を実行する前に、Bazel が推移的な依存関係グラフ全体を検出できます。
モジュールごとに 1 つのバージョンが選択されるバージョン解決後、Bazel は再度レジストリを参照し、各モジュールのリポジトリを定義する方法を確認します(通常は http_archive
を使用します)。
モジュールでは、タグと呼ばれるカスタマイズされたデータを指定することもできます。これは、追加のリポジトリを定義するために、モジュールの解決後にモジュール拡張機能で使用されます。これらの拡張機能にはリポジトリ ルールに似た機能があり、ファイル I/O やネットワーク リクエストの送信などのアクションを実行できます。特に、Bazel モジュールからビルドされた依存関係グラフを尊重しながら、Bazel が他のパッケージ管理システムとやり取りできるようになります。
Bzlmod の外部リンク
- bazelbuild/examples での bazlmod の使用例
- Bazel 外部依存関係の全面的な見直し(元の Bzlmod 設計ドキュメント)
- BazelCon 2021 での Bzlmod に関する講演
- Bzlmod に関する Bazel コミュニティ デーの講演
WORKSPACE
を使用してリポジトリを定義する
これまでは、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
のリポジトリを定義しています。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 には欠点があるため、今後の Bazel リリースでは、従来の WORKSPACE システムが Bzlmod に置き換わる予定です。Bzlmod への移行方法については、Bzlmod 移行ガイドをご覧ください。