Bazel は、外部依存関係、つまりワークスペースのものではなく、ビルドで使用されるソースファイル(テキストとバイナリの両方)をサポートしています。たとえば、GitHub リポジトリでホストされているルールセット、Maven アーティファクト、現在のワークスペース外のローカルマシンのディレクトリなどが該当します。
Bazel 6.0 では、Bazel で外部依存関係を管理する方法が 2 つあります。リポジトリを重視した従来の WORKSPACE
システムと、モジュールを重視した新しい MODULE.bazel
システム(コード名 Bzlmod、フラグ --enable_bzlmod
で有効化)です。この 2 つのシステムは併用できますが、今後の Bazel リリースで WORKSPACE
システムを置き換える方法については、Bzlmod} で移行に関するガイドをご覧ください。{/10.mod}
このドキュメントでは、2 つのシステムについて順番に詳しく説明する前に、Bazel での外部依存関係の管理に関するコンセプトについて説明します。
概念
リポジトリ
ルートに境界マーカー ファイルがあり、Bazel ビルドで使用できるソースファイルを含むディレクトリ ツリー。多くの場合、リポのために短縮されます。
リポジトリ境界マーカー ファイルは、MODULE.bazel
(このリポジトリが Bazel モジュールを表すことを示す)、REPO.bazel
(以下を参照)、またはレガシー コンテキストでは WORKSPACE
または WORKSPACE.bazel
です。リポジトリ境界マーカー ファイルはリポジトリの境界を示します。このようなファイルは、1 つのディレクトリに複数の共存できます。
メイン リポジトリ
現在の Bazel コマンドが実行されているリポジトリ。
メイン リポジトリのルートは、ワークスペース ルートとも呼ばれます。
ワークスペース
すべての Bazel コマンドで共有される環境は、同じメイン リポジトリで実行されます。メイン リポジトリと、すべての定義済みの外部リポジトリのセットが含まれています。
これまで、「リポジトリ」と「ワークスペース」のコンセプトは混同されてきました。「ワークスペース」という用語はメイン リポジトリを指すために使用され、場合によっては「リポジトリ」の同義語として使用されることさえあります。
正規リポジトリ名
リポジトリをアドレス指定できる正規名。ワークスペースのコンテキストでは、各リポジトリに 1 つの正規名があります。正規名が canonical_name
のリポジトリ内のターゲットは、ラベル @@canonical_name//package:target
でアドレス指定できます(二重の @
に注意してください)。
メイン リポジトリでは、正規名として常に空の文字列が使用されます。
わかりやすいリポジトリ名
リポジトリの名前。他のリポジトリのコンテキストで参照できます。これは、リポジトリの「ニックネーム」と考えることができます。正規名 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
ステートメントはサポートされておらず、1 つの関数 repo()
しか使用できない点が異なります。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 Registry)で検索する直接的な依存関係のみを記載する必要があります。このレジストリは依存関係の MODULE.bazel
ファイルを提供します。これにより、Bazel はバージョン解決を実行する前に推移的依存関係グラフ全体を検出できます。
バージョンの解決(モジュールごとに 1 つのバージョンが選択される)の後、Bazel はレジストリを再度参照し、モジュールごとにリポジトリを定義する方法を確認します(ほとんどの場合、http_archive
を使用します)。
モジュールでは、タグと呼ばれるカスタマイズされたデータを指定することもできます。これは、モジュールの解決後にモジュール拡張機能によって使用され、追加のリポジトリを定義します。これらの拡張機能にはリポジトリ ルールに似た機能があり、ファイル I/O やネットワーク リクエストの送信などのアクションを実行できます。特に、Bazel モジュールから構築された依存関係グラフを尊重しながら、Bazel が他のパッケージ管理システムと連携できるようにします。
Bzlmod の外部リンク
- bazelbuild/examples での Bzlmod の使用例
- Bazel 外部依存関係のオーバーホール(元の Bzlmod 設計ドキュメント)
- Bzlmod に関する BazelCon 2021 の講演
- Bzlmod に関する Bazel Community Day のトーク
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 には欠点があるため、Bzlmod は今後の Bazel リリースで以前の WORKSPACE システムに置き換わる予定です。Bzlmod への移行方法については、Bzlmod 移行ガイドをご覧ください。