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