外部依存関係の概要

問題を報告する ソースを表示 ナイトリー · 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

Bazel は、ワークスペースにないビルドで使用される外部依存関係(テキストとバイナリの両方のソースファイル)をサポートしています。たとえば、GitHub リポジトリでホストされているルールセット、Maven アーティファクト、現在のワークスペース外のローカルマシンのディレクトリなどです。

Bazel 6.0 以降では、Bazel で外部依存関係を管理する方法は 2 つあります。従来のリポジトリ中心の WORKSPACE システムと、新しいモジュール中心の MODULE.bazel システム(コードネーム Bzlmod、フラグ --enable_bzlmod で有効)です。これらの 2 つのシステムは一緒に使用できますが、今後の Bazel リリースでは Bzlmod が WORKSPACE システムに置き換わります。移行方法については、Bzlmod 移行ガイドをご覧ください。

このドキュメントでは、Bazel の外部依存関係管理に関するコンセプトについて説明してから、2 つのシステムについて順に詳しく説明します。

コンセプト

リポジトリ

ルートに境界マーカー ファイルがあり、Bazel ビルドで使用できるソースファイルを含むディレクトリ ツリー。多くの場合、repo と省略されます。

リポジトリ境界マーカー ファイルは、MODULE.bazel(このリポジトリが Bazel モジュールを表すことを示す)、REPO.bazel下記を参照)、または以前のコンテキストでは WORKSPACE または WORKSPACE.bazel です。リポジトリ境界マーカー ファイルは、リポジトリの境界を示します。このようなファイルはディレクトリ内に複数存在できます。

メイン リポジトリ

現在の Bazel コマンドが実行されているリポジトリ。

メイン リポジトリのルートは、ワークスペース ルートとも呼ばれます。

ワークスペース

すべての Bazel コマンドで共有される環境は、同じメイン リポジトリで実行されます。メイン リポジトリと、定義されたすべての外部リポジトリのセットを含みます。

歴史的に、「リポジトリ」と「ワークスペース」の概念は混同されてきました。「ワークスペース」という用語は、メイン リポジトリを指すためによく使用され、「リポジトリ」の同義語として使用されることもあります。

正規リポジトリ名

リポジトリがアドレス指定できる正規名。ワークスペースのコンテキスト内で、各リポジトリには単一の正規名があります。正規名が canonical_name の repo 内のターゲットは、ラベル @@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() という単一の関数のみを使用できます。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 はレジストリに再度問い合わせて、各モジュールの repo を定義する方法を学習します(ほとんどの場合、http_archive を使用します)。

モジュールでは、タグと呼ばれるカスタマイズされたデータも指定できます。このタグは、モジュールの解決後にモジュール拡張機能によって使用され、追加のリポジトリを定義します。これらの拡張機能には、リポジトリ ルールと同様の機能があり、ファイル I/O やネットワーク リクエストの送信などのアクションを実行できます。たとえば、Bazel は 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 の repo を定義します。WORKSPACE システムでは、デフォルトで、リポジトリの正規名は他のすべてのリポジトリに対する表示名でもあります。

WORKSPACE ファイルで使用可能な関数の一覧をご覧ください。

WORKSPACE システムの欠点

WORKSPACE システムが導入されてから数年の間に、ユーザーから次のような多くの問題が報告されています。

  • Bazel は依存関係の WORKSPACE ファイルを評価しないため、直接依存関係に加えて、すべての伝播依存関係をメイン リポジトリの WORKSPACE ファイルで定義する必要があります。
  • この問題を回避するために、プロジェクトは「deps.bzl」パターンを採用しています。このパターンでは、複数のリポジトリを定義するマクロを定義し、ユーザーに WORKSPACE ファイルでこのマクロを呼び出すよう求めます。
    • これには独自の問題があります。マクロは他の .bzl ファイルを load できないため、これらのプロジェクトは、この「deps」マクロで伝播依存関係を定義するか、ユーザーが複数のレイヤ化された「deps」マクロを呼び出すようにすることで、この問題を回避する必要があります。
    • Bazel は WORKSPACE ファイルを順番に評価します。また、依存関係は、バージョン情報なしで URL を指定して http_archive を使用して指定します。つまり、ダイアモンド依存関係の場合、バージョン解決を実行する信頼できる方法はありません(ABC に依存し、BC はどちらも異なるバージョンの D に依存しています)。

WORKSPACE の欠点により、今後の Bazel リリースでは、Bzlmod が従来の WORKSPACE システムに代わる予定です。Bzlmod への移行方法については、Bzlmod 移行ガイドをご覧ください。