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_repository
、git_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_local_repository
など、new_
の接頭辞を持つルールを使用すると、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
を使用します。フェッチされたリポジトリは出力ベースに保存されるため、フェッチはワークスペースごとに行われます。
依存関係のシェーディング
可能な限り、プロジェクトに 1 つのバージョン ポリシーを設定することをおすすめします。これは、コンパイルして最終バイナリとなる依存関係に必要です。ただし、そうではない場合は、依存関係をシャドーできます。次のシナリオを考えてみます。
自分のプロジェクト/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(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 = "..."
)
依存関係の A
と B
はどちらも 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"}
)
このメカニズムは、ダイアモンドの結合にも使用できます。たとえば、A
と B
に同じ依存関係があり、異なる名前で呼び出している場合、これらの依存関係は 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
例外が発生してビルドが失敗することがあります。このような場合は、java.net.preferIPv6Addresses=true
システム プロパティを使用して、IPv6 を優先するように Bazel の動作をオーバーライドできます。詳細は以下のとおりです。
--host_jvm_args=-Djava.net.preferIPv6Addresses=true
起動オプションを使用します。たとえば、.bazelrc
ファイルに次の行を追加します。startup --host_jvm_args=-Djava.net.preferIPv6Addresses=true
インターネットに接続する必要がある Java ビルド ターゲットを実行している場合(統合テストで必要な場合もあります)、
--jvmopt=-Djava.net.preferIPv6Addresses=true
ツールフラグも使用します。たとえば、.bazelrc
ファイルに次の行を追加します。build --jvmopt=-Djava.net.preferIPv6Addresses
依存関係のバージョン解決など、rules_jvm_external を使用している場合は、
COURSIER_OPTS
環境変数に-Djava.net.preferIPv6Addresses=true
を追加して、Coursier に JVM オプションを指定します。
推移的依存関係
Bazel は、WORKSPACE
ファイルにリストされている依存関係のみを読み取ります。プロジェクト(A
)が別のプロジェクト(B
)に依存していて、そのプロジェクトの WORKSPACE
ファイルにサードパーティ プロジェクト(C
)の依存関係がリストされている場合は、プロジェクトの WORKSPACE
ファイルに B
と C
の両方を追加する必要があります。この要件により WORKSPACE
ファイルのサイズが大きくなる可能性がありますが、一方のライブラリにバージョン 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
がサポートされます。リポジトリ ルールが ctx.download
または ctx.download_and_extract
を介してファイルを取得するように Bazel に依頼し、必要なファイルのハッシュの合計を指定すると、Bazel はまず、指定されたディレクトリで、指定された最初の URL のベース名に一致するファイルを探し、ハッシュが一致する場合はローカルコピーを使用します。
Bazel 自体も、この手法を使用してディストリビューション アーティファクトからオフラインでブートストラップします。これは、内部 distdir_tar
に必要な外部依存関係をすべて収集することで実現します。
ただし、bazel では、ネットワークに対して呼び出しているかどうかを知らなくても、リポジトリ ルール内の任意のコマンドを実行できます。したがって、Bazel では、ビルドを完全にオフラインに強制するオプションはありません。そのため、ビルドがオフラインで正しく機能するかどうかをテストするには、Bazel がブートストラップ テストで行っているように、ネットワークの外部ブロックが必要です。
ベスト プラクティス
リポジトリ ルール
通常、リポジトリ ルールは次の処理を担当する必要があります。
- システム設定を検出してファイルに書き込む。
- システムの他の場所でリソースを見つける。
- URL からリソースをダウンロードする。
- BUILD ファイルを生成するか、外部リポジトリ ディレクトリにシンボリック リンクする。
可能であれば、repository_ctx.execute
は使用しないでください。たとえば、Make を使用してビルドされる Bazel 以外の C++ ライブラリを使用する場合は、ctx.execute(["make"])
を実行するのではなく、repository_ctx.download()
を使用してビルドする BUILD ファイルを作成することをおすすめします。
git_repository
と new_git_repository
よりも http_archive
を優先します。その理由は次のとおりです。
- Git リポジトリ ルールはシステムの
git(1)
に依存しますが、HTTP ダウンローダは Bazel に組み込まれており、システムの依存関係はありません。 http_archive
はミラーとしてurls
のリストをサポートし、git_repository
は単一のremote
のみをサポートします。http_archive
はリポジトリ キャッシュで機能しますが、git_repository
では機能しません。詳しくは、#5116 をご覧ください。
bind()
を使用しない。問題と代替方法について詳しくは、bind の削除を検討するをご覧ください。