外部依存関係の操作

Bazel は、他のプロジェクトのターゲットに依存できます。これらの他のプロジェクトからの依存関係は、外部依存関係と呼ばれます。

ワークスペース ディレクトリWORKSPACE ファイル(または WORKSPACE.bazel ファイル)は、他のプロジェクトのソースを取得する方法を Bazel に伝えます。これらの他のプロジェクトには、独自のターゲットを持つ 1 つ以上の BUILD ファイルを含めることができます。メイン プロジェクト内の BUILD ファイルは、WORKSPACE ファイルの名前を使用して、これらの外部ターゲットに依存できます。

たとえば、システムに 2 つのプロジェクトがあるとします。

/
  home/
    user/
      project1/
        WORKSPACE
        BUILD
        srcs/
          ...
      project2/
        WORKSPACE
        BUILD
        my-libs/

project1/home/user/project2/BUILD で定義されたターゲット :foo に依存する場合、project2 という名前のリポジトリが /home/user/project2 にあることを指定できます。これにより、/home/user/project1/BUILD のターゲットは @project2//:foo に依存できます。

WORKSPACE ファイルを使用すると、ファイル システムの他の部分にあるターゲットや、インターネットからダウンロードしたターゲットに依存できます。BUILD ファイルと同じ構文を使用しますが、リポジトリ ルール( ワークスペース ルールとも呼ばれます)という別のルールセットを使用できます。Bazel には、組み込みのリポジトリ ルールと、埋め込みの Starlark リポジトリ ルールが用意されています。ユーザーは、カスタム リポジトリ ルールを作成して、より複雑な動作を実現することもできます。

サポートされている外部依存関係のタイプ

いくつかの基本的なタイプの外部依存関係を使用できます。

他の Bazel プロジェクトに依存する

2 つ目の Bazel プロジェクトのターゲットを使用する場合は、 local_repositorygit_repository または http_archive を使用して、ローカル ファイル システムからシンボリック リンクを作成したり、Git リポジトリを参照したり、 ダウンロードしたりできます。

たとえば、my-project/ というプロジェクトに取り組んでいて、同僚のプロジェクト coworkers-project/ のターゲットに依存するとします。どちらのプロジェクトも Bazel を使用しているため、同僚のプロジェクトを外部依存関係として追加し、同僚が定義したターゲットを独自の BUILD ファイルから使用できます。my_project/WORKSPACE に次のように追加します。

local_repository(
    name = "coworkers_project",
    path = "/path/to/coworkers-project",
)

同僚にターゲット //foo:bar がある場合、プロジェクトは @coworkers_project//foo:bar として参照できます。外部プロジェクト名は 有効なワークスペース名である必要があります。

Bazel 以外のプロジェクトに依存する

new_ などの new_local_repository で始まるルールを使用すると、Bazel を使用しないプロジェクトからターゲットを作成できます。

たとえば、my-project/ というプロジェクトに取り組んでいて、同僚のプロジェクト coworkers-project/ に依存するとします。同僚のプロジェクトは make を使用してビルドしますが、生成される .so ファイルのいずれかに依存したいと考えています。これを行うには、my_project/WORKSPACE に次のように追加します。

new_local_repository(
    name = "coworkers_project",
    path = "/path/to/coworkers-project",
    build_file = "coworker.BUILD",
)

build_file は、既存のプロジェクトにオーバーレイする BUILD ファイルを指定します。例:

cc_library(
    name = "some-lib",
    srcs = glob(["**"]),
    visibility = ["//visibility:public"],
)

これにより、プロジェクトの BUILD ファイルから @coworkers_project//:some-lib に依存できます。

外部パッケージに依存する

Maven アーティファクトとリポジトリ

ルールセット rules_jvm_external を使用して、Maven リポジトリからアーティファクトをダウンロードし、Java 依存関係として使用できるようにします。

依存関係をフェッチする

デフォルトでは、外部依存関係は bazel build 中に必要に応じてフェッチされます。特定のターゲットセットに必要な依存関係をプリフェッチする場合は、bazel fetchを使用します。すべての外部依存関係を無条件にフェッチするには、 bazel sync を使用します。 フェッチされたリポジトリは出力ベースに保存されるため、フェッチは ワークスペースごとに行われます。

依存関係のシャドウイング

可能な限り、プロジェクトに単一バージョン ポリシーを設定することをおすすめします。これは、コンパイルして最終的なバイナリに含める依存関係に必要です。ただし、そうでない場合は、依存関係をシャドウイングできます。次のシナリオを考えてみます。

myproject/WORKSPACE

workspace(name = "myproject")

local_repository(
    name = "A",
    path = "../A",
)
local_repository(
    name = "B",
    path = "../B",
)

A/WORKSPACE

workspace(name = "A")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "testrunner",
    urls = ["https://github.com/testrunner/v1.zip"],
    sha256 = "...",
)

B/WORKSPACE

workspace(name = "B")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "testrunner",
    urls = ["https://github.com/testrunner/v2.zip"],
    sha256 = "..."
)

依存関係 AB はどちらも testrunner に依存していますが、testrunner のバージョンが異なります。これらのテストランナーが myproject 内で共存できない理由はありませんが、名前が同じであるため競合します。両方の依存関係を宣言するには、myproject/WORKSPACE を更新します。

workspace(name = "myproject")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "testrunner-v1",
    urls = ["https://github.com/testrunner/v1.zip"],
    sha256 = "..."
)
http_archive(
    name = "testrunner-v2",
    urls = ["https://github.com/testrunner/v2.zip"],
    sha256 = "..."
)
local_repository(
    name = "A",
    path = "../A",
    repo_mapping = {"@testrunner" : "@testrunner-v1"}
)
local_repository(
    name = "B",
    path = "../B",
    repo_mapping = {"@testrunner" : "@testrunner-v2"}
)

このメカニズムを使用して、ダイヤモンドを結合することもできます。たとえば、AB の依存関係が同じでも名前が異なる場合、これらの依存関係は myproject/WORKSPACE で結合できます。

コマンドラインからリポジトリをオーバーライドする

宣言されたリポジトリをコマンドラインからローカル リポジトリでオーバーライドするには、 --override_repository フラグを使用します。このフラグを使用すると、ソースコードを変更せずに外部リポジトリの内容を変更できます。

たとえば、@foo をローカル ディレクトリ /path/to/local/foo にオーバーライドするには、 --override_repository=foo=/path/to/local/foo フラグを渡します。

ユースケースの一部を示します。

  • 問題のデバッグ。たとえば、http_archive リポジトリをローカル ディレクトリにオーバーライドして、変更を簡単に加えることができます。
  • ベンダリング。ネットワーク呼び出しができない環境の場合は、ネットワーク ベースのリポジトリ ルールをオーバーライドして、代わりにローカル ディレクトリを指すようにします。

プロキシの使用

Bazel は、HTTPS_PROXY 環境変数と HTTP_PROXY 環境変数からプロキシ アドレスを取得し、これを使用して HTTP/HTTPS ファイルをダウンロードします(指定されている場合)。

IPv6 をサポート

IPv6 専用のマシンでは、Bazel は変更なしで依存関係をダウンロードできます。ただし、デュアルスタック IPv4/IPv6 マシンでは、Bazel は Java と同じ規則に従います。IPv4 が有効になっている場合は、IPv4 が優先されます。状況によっては(IPv4 ネットワークが外部アドレスを解決または到達できない場合など)、Network unreachable 例外が発生し、ビルドが失敗することがあります。 このような場合は、IPv6 を優先するように Bazel の動作をオーバーライドできます java.net.preferIPv6Addresses=true システム プロパティを使用して。 詳細:

推移的依存関係

Bazel は、WORKSPACE ファイルに記載されている依存関係のみを読み取ります。プロジェクト (A) が別のプロジェクト (B) に依存し、その WORKSPACE ファイルに 3 つ目の プロジェクト (C) への依存関係が記載されている場合は、プロジェクトの WORKSPACE ファイルに BC の両方を追加する必要があります。この要件により、 WORKSPACE ファイルのサイズが大きくなる可能性がありますが、1 つのライブラリにバージョン 1.0 の C が含まれ、別のライブラリにバージョン 2.0 の C が含まれる可能性を抑えることができます。

外部依存関係のキャッシュ

デフォルトでは、Bazel は外部依存関係の定義が変更された場合にのみ、外部依存関係を再ダウンロードします。定義で参照されているファイル(パッチや BUILD ファイルなど)の変更も bazel によって考慮されます。

再ダウンロードを強制するには、bazel sync を使用します。

レイアウト

外部依存関係はすべて、出力ベースのサブディレクトリ externalの下のディレクトリにダウンロードされます。ローカル リポジトリの場合、新しいディレクトリを作成する代わりに、シンボリック リンクが作成されます。external ディレクトリを表示するには、次を実行します。

ls $(bazel info output_base)/external

bazel clean を実行しても、外部ディレクトリは実際には削除されません。すべての外部アーティファクトを削除するには、bazel clean --expunge を使用します。

オフライン ビルド

オフラインでビルドを実行することが望ましい場合や、必要な場合があります。飛行機での移動などの 簡単なユースケースでは、 必要な リポジトリをbazel fetch または bazel sync でプリフェッチするだけで十分です。また、 --nofetch オプションを使用すると、ビルド中にさらにリポジトリをフェッチすることを無効にできます。

必要なファイルの提供を bazel とは異なるエンティティが行う真のオフライン ビルドの場合、bazel は --distdir オプションをサポートしています。リポジトリ ルールが Bazel に ctx.downloadまたは ctx.download_and_extract を介してファイルをフェッチするように要求し、必要なファイルのハッシュ値を指定すると、Bazel は最初に、指定されたオプションのディレクトリで、指定された最初の URL のベース名に一致するファイルを検索し、ハッシュが一致する場合はそのローカル コピーを使用します。

Bazel 自体は、この手法を使用して、配布 アーティファクトからオフラインでブートストラップします。 これを行うには、必要な外部依存関係をすべて内部のに収集します。distdir_tar

ただし、bazel では、ネットワークを呼び出すかどうかに関係なく、リポジトリ ルールで任意のコマンドを実行できます。そのため、bazel にはビルドを完全にオフラインにするオプションはありません。したがって、ビルドがオフラインで正しく動作するかどうかをテストするには、bazel がブートストラップ テストで行うように、ネットワークを外部でブロックする必要があります。

ベスト プラクティス

リポジトリ ルール

リポジトリ ルールは通常、次のことを行う必要があります。

  • システム設定を検出し、ファイルに書き込む。
  • システム内の他の場所でリソースを見つける。
  • URL からリソースをダウンロードする。
  • BUILD ファイルを生成するか、外部リポジトリ ディレクトリにシンボリック リンクを作成する。

可能な限り、repository_ctx.execute の使用は避けてください。たとえば、Make を使用してビルドする Bazel 以外の C++ ライブラリを使用する場合は、repository_ctx.download() を使用して、ビルドする BUILD ファイルを作成することをおすすめします。ctx.execute(["make"])

git_repositorynew_git_repository よりも http_archive を優先します。その理由は次のとおりです。

  • Git リポジトリ ルールはシステム git(1) に依存しますが、HTTP ダウンローダーは Bazel に組み込まれており、システム依存関係はありません。
  • http_archive はミラーとして urls のリストをサポートしますが、git_repository は単一の remote のみをサポートします。
  • http_archiveリポジトリ キャッシュで動作しますが、 git_repository では動作しません。詳細については、 #5116 をご覧ください。

bind() を使用しないでください。問題点と代替案については、「bind の削除を検討する」をご覧ください。