外部依存関係の概要

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

このドキュメントでは、システムの概要を説明してから、いくつかのコンセプトについて詳しく説明します。

システムの概要

Bazel の外部依存関係システムは、Bazel モジュール(それぞれバージョン管理された Bazel プロジェクト)と リポジトリ(ソースファイルを含むディレクトリ ツリー)に基づいています。

Bazel は、ルート モジュール(作業中のプロジェクト)から開始します。 すべてのモジュールと同様に、ディレクトリ ルートに MODULE.bazel ファイルがあり、基本的なメタデータと直接的な依存関係を宣言する必要があります。基本的な例を次に示します。

module(name = "my-module", version = "1.0")

bazel_dep(name = "rules_cc", version = "0.1.1")
bazel_dep(name = "platforms", version = "0.0.11")

そこから、Bazel は Bazel レジストリ(デフォルトでは Bazel Central Registry)ですべての推移的な依存関係モジュールを検索します。レジストリは依存関係の MODULE.bazel ファイルを提供します。これにより、Bazel はバージョン解決を実行する前に、推移的な依存関係グラフ全体を検出できます。

バージョン解決(各モジュールに 1 つのバージョンが選択される)後、 Bazel はレジストリを再度参照して、各モジュールのリポジトリを定義する方法 (各依存関係モジュールのソースを取得する方法)を確認します。ほとんどの場合、これらはインターネットからダウンロードして抽出されたアーカイブです。

モジュールは、モジュール解決後にモジュール拡張機能によって使用され、追加のリポジトリを定義するタグと呼ばれるカスタマイズされたデータの一部を指定することもできます。これらの拡張機能は、ファイル I/O やネットワーク リクエストの送信などのアクションを実行できます。これにより、Bazel は他のパッケージ管理システムと連携しながら、Bazel モジュールから構築された依存関係グラフを尊重できます。

3 種類のリポジトリ(メイン リポジトリ(作業中のソースツリー)、推移的な依存関係モジュールを表すリポジトリ、モジュール拡張機能によって作成されたリポジトリ)は、ワークスペースを構成します。外部リポジトリ(メイン リポジトリ以外)は、BUILD ファイルのラベル(@repo//pkg:target など)で参照される場合など、必要に応じて取得されます。

特典

Bazel の外部依存関係システムには、さまざまなメリットがあります。

依存関係の自動解決

  • 決定論的なバージョン解決: Bazel は決定論的な MVS バージョン解決アルゴリズムを採用し、 競合を最小限に抑え、ダイヤモンド依存関係の問題に対処します。
  • 依存関係の管理の簡素化: MODULE.bazel は直接的な 依存関係のみを宣言し、推移的な依存関係は自動的に解決されるため、 プロジェクトの依存関係の概要を明確に把握できます。
  • 厳格な依存関係の可視性: 直接的な依存関係のみが表示されるため、正確性と 予測可能性が確保されます。

エコシステムの統合

  • Bazel Central Registry: Bazel モジュールとして一般的な依存関係を検出して管理するための一元化された リポジトリ。
  • Bazel 以外のプロジェクトの採用: Bazel 以外のプロジェクト(通常は C++ ライブラリ)が Bazel に適応され、BCR で利用可能になると、コミュニティ全体の統合が効率化され、カスタム BUILD ファイルの重複した作業や競合が解消されます。
  • 言語固有のパッケージ マネージャーとの統合: ルールセットは、次のような Bazel 以外の依存関係の外部パッケージ マネージャーとの統合を効率化します。

高度な機能

  • モジュール拡張機能: use_repo_rule とモジュール 拡張機能を使用すると、カスタム リポジトリ ルールと 解決ロジックを柔軟に使用して、Bazel 以外の依存関係を導入できます。
  • bazel mod コマンド: サブコマンドを使用すると、 外部依存関係を強力に検査できます。外部依存関係がどのように定義され、どこから取得されたかを正確に把握できます。
  • ベンダーモード: オフライン ビルドを容易にするために必要な外部依存関係を事前に取得します。
  • ロックファイル: ロックファイルにより、ビルドの再現性が向上し、 依存関係の解決が高速化されます。
  • (近日公開)BCR の出所証明: 依存関係の出所が確認されることで、サプライ チェーンのセキュリティが強化されます。

コンセプト

このセクションでは、外部依存関係に関連するコンセプトについて詳しく説明します。

モジュール

複数のバージョンを持つことができる Bazel プロジェクト。各バージョンは他のモジュールに依存できます。

ローカルの Bazel ワークスペースでは、モジュールはリポジトリで表されます。

詳細については、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 ファイル

The REPO.bazel ファイルは、リポジトリを構成するディレクトリ ツリーの最上位の境界をマークするために使用されます。リポジトリ境界ファイルとして機能するために何も含める必要はありませんが、リポジトリ内のすべてのビルドターゲットに共通の属性を指定するためにも使用できます。

REPO.bazel ファイルの構文は BUILD ファイルと似ていますが、load ステートメントはサポートされていません。repo() 関数は、package() 関数 ファイルの BUILD と同じ引数を取ります。package() はパッケージ内のすべてのビルドターゲットに共通の属性を指定しますが、repo() はリポジトリ内のすべてのビルドターゲットに対して同様の処理を行います。

たとえば、次の REPO.bazel ファイルを使用して、リポジトリ内のすべてのターゲットに共通のライセンスを指定できます。

repo(
    default_package_metadata = ["//:my_license"],
)

従来の WORKSPACE システム

古い Bazel バージョン(9.0 より前)では、 ファイルでリポジトリを定義することで、外部依存関係が導入されていました。WORKSPACEWORKSPACE.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 で指定されます。つまり、ダイヤモンド依存関係(ABC に依存し、BC が両方とも異なるバージョンの D に依存する)の場合、バージョン解決を確実に行う方法はありません。

WORKSPACE の欠点により、Bazel 6 と 9 の間で、新しいモジュールベースのシステム(コードネーム「Bzlmod」)が従来の WORKSPACE システムに徐々に置き換わりました。 Bzlmod への移行方法については、Bzlmod 移行ガイドをご覧ください 。