Bazel は、外部依存関係と、ワークスペース以外からビルドで使用されるソースファイル(テキストとバイナリの両方)をサポートします。たとえば、GitHub リポジトリ、Maven アーティファクト、現在のワークスペース外のローカルマシン上のディレクトリでホストされているルールセットなどです。
Bazel 6.0 では、Bazel で外部依存関係を管理するには、従来のリポジトリを重視した WORKSPACE
システムと、新しいモジュールに焦点を当てた MODULE.bazel
システム(コード名は Bzlmod、フラグ --enable_bzlmod
が有効)の 2 つの方法があります。これらの 2 つのシステムを同時に使用することもできますが、今後の Bazel リリースでは Bzlmod が WORKSPACE
システムに置き換えられます。
この記事では、Bazel での外部依存関係の管理のコンセプトについて説明してから、2 つのシステムを順番に詳しく説明します。
コンセプト
リポジトリ
Bazel ビルドで使用されるソースファイルを含む WORKSPACE
または WORKSPACE.bazel
ファイルがあるディレクトリ。「repo」と短縮されることが多いです。
メイン リポジトリ
現在の Bazel コマンドが実行されているリポジトリ。
ワークスペース
すべての Bazel コマンドで共有される環境は、同じメイン リポジトリで実行されます。
「リポジトリ」と「ワークスペース」という概念はこれまで混同されてきました。多くの場合、「ワークスペース」という用語はメイン リポジトリを指す用語として用いられており、「リポジトリ」の同義語として使用されることもあります。
正規リポジトリ名
リポジトリがアドレス指定するための正規名。ワークスペースのコンテキスト内では、各リポジトリに 1 つの正規名があります。正規名が canonical_name
であるリポジトリ内のターゲットは、@@canonical_name//pac/kage:target
ラベルで指定できます(@
が 2 つ重複しています)。
メイン リポジトリでは、正規名として常に空の文字列が使用されます。
Apparent リポジトリ名
リポジトリのアドレス指定が可能なリポジトリ名。これは、リポジトリの「ニックネーム」と考えることができます。正規名 michael
のリポジトリは、リポジトリ alice
のコンテキストでは mike
という名前になりますが、bob
bob
のコンテキストでは mickey
になります。この場合、michael
内のターゲットは、alice
のコンテキストでラベル @mike//pac/kage:target
を使用してアドレス指定することができます(単一の @
に注意してください)。
逆に、これはリポジトリ マッピングとして認識できます。各リポジトリは、「見かけのリポジトリ名」から「正規のリポジトリ名」へのマッピングを保持しています。
リポジトリ ルール
リポジトリ定義のスキーマを Bazel に指示するためのリポジトリ定義のスキーマ。たとえば、「特定の URL から ZIP アーカイブをダウンロードして解凍する」、「特定の Maven アーティファクトを取得して java_import
ターゲットとして使用できるようにする」、「ローカル ディレクトリのシンボリック リンク」などが考えられます。すべてのリポジトリは、適切な数の引数を指定してリポジトリ ルールを呼び出すことで定義されます。
独自のリポジトリ ルールを作成する方法については、リポジトリ ルールをご覧ください。
最も一般的なリポジトリ ルールは、URL からアーカイブをダウンロードして抽出する http_archive
と、すでに Bazel リポジトリであるローカル ディレクトリをシンボリックする local_repository
です。
リポジトリの取得
関連するリポジトリ ルールを実行して、ローカル ディスクでリポジトリを利用できるようにするアクション。ワークスペースで定義されたリポジトリは、取得される前にローカル ディスクでは使用できません。
通常、Bazel はリポジトリから情報を取得する必要があるが、リポジトリがまだ取得されていない場合にのみ、リポジトリを取得します。リポジトリがすでに取得されている場合、Bazel はリポジトリの定義が変更された場合にのみ再取得します。
ディレクトリ レイアウト
取得されたリポジトリは、出力ベースのサブディレクトリ external
から正規名で見つけることができます。
次のコマンドを実行すると、正規名 canonical_name
でリポジトリのコンテンツが表示されます。
ls $(bazel info output_base)/external/ canonical_name
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 中央レジストリです。レジストリは、依存関係の MODULE.bazel
ファイルを提供します。これにより、Bazel はバージョンの解決の前に推移的な依存関係グラフ全体を検出できます。
バージョン解決(モジュールごとに 1 つのバージョンが選択される)後の Bazel は、レジストリごとに再度コンサルトを行い、各モジュールのリポジトリを定義する方法を学びます(ほとんどの場合は http_archive
を使用します)。
モジュールでは、タグと呼ばれるカスタマイズされたデータを指定することもできます。これは、モジュールの解決後に追加のモジュールを定義するためにモジュール拡張によって使用されます。これらの拡張機能にはリポジトリ ルールと同様の機能があり、ファイル I/O やネットワーク リクエストなどのアクションを実行できます。これにより、Bazel は他のパッケージ管理システムとやり取りしながら、Bazel モジュールから作成された依存関係グラフを尊重できます。
Bzlmod の外部リンク
- bazelbuild/examples の zzmod の使用例
- Bazel 外部依存関係のオーバーホール(元の Bzlmod 設計ドキュメント)
- Bzlmod に関する BazelCon 2021 の講演
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
システムの導入から数年が経過し、多くの問題点が報告されています。
- Bazel は依存関係の
WORKSPACE
ファイルを評価しないため、直接依存関係に加えて、すべての推移的依存関係をメインリポジトリのWORKSPACE
ファイルで定義する必要があります。 - これを回避するために、プロジェクトで「deps.bzl」パターンを採用しました。このパターンでは、マクロを定義して複数のリポジトリを定義し、ユーザーに
WORKSPACE
ファイルでこのマクロを呼び出すよう求めます。- この問題には独自の問題があります。マクロは他の
.bzl
ファイルをload
できないため、この「deps」マクロで推移的な依存関係を定義するか、ユーザーに複数のレイヤ「deps」マクロを呼び出してこの問題を回避する必要があります。 - Bazel は
WORKSPACE
ファイルを順番に評価します。また、依存関係は、バージョン情報なしで、http_archive
と URL を使用して指定されます。つまり、ひし形の依存関係の場合、バージョン解決を実行する信頼できる方法がないということです(A
はB
とC
に依存し、B
とC
はどちらもD
のさまざまなバージョンに依存します)。
- この問題には独自の問題があります。マクロは他の