このページでは、リポジトリ ルールを定義する方法と、いくつかの例について説明します。
外部リポジトリは Bazel ビルドで使用できるソースファイルを含むディレクトリ ツリーで、対応する リポジトリ ルールを実行することでオンデマンドで生成されます。Repo はさまざまな方法で定義できますが、ビルド ターゲットがビルドルールによって定義されるのと同様に、最終的に各リポジトリは Repo ルールを呼び出して定義されます。サードパーティのライブラリ(Maven パッケージ ライブラリなど)に依存する場合だけでなく、Bazel が実行されているホストに固有の BUILD
ファイルを生成する場合にも使用できます。
リポジトリ ルールの定義
.bzl
ファイルで、repository_rule 関数を使用して新しいリポジトリルールを定義し、グローバル変数に格納します。リポジトリのルールを定義すると、リポジトリを定義する関数としてルールを呼び出すことができます。この呼び出しは通常、モジュール拡張実装関数の中で行われます。
リポジトリ ルール定義の 2 つの主要コンポーネントは、属性スキーマと実装関数です。属性スキーマにより、リポジトリ ルールの呼び出しに渡される属性の名前とタイプが決まります。リポジトリを取得する必要がある場合は、実装関数が実行されます。
属性
属性は、リポジトリ ルールの呼び出しに渡される引数です。リポジトリ ルールが受け入れる属性のスキーマは、repository_rule
の呼び出しでリポジトリ ルールが定義されているときに、attrs
引数を使用して指定されます。url
属性と sha256
属性を文字列として定義する例を以下に示します。
http_archive = repository_rule(
implementation=_impl,
attrs={
"url": attr.string(mandatory=True)
"sha256": attr.string(mandatory=True)
}
)
実装関数内の属性にアクセスするには、repository_ctx.attr.<attribute_name>
を使用します。
def _impl(repository_ctx):
url = repository_ctx.attr.url
checksum = repository_ctx.attr.sha256
すべての repository_rule
には、暗黙的に定義された属性 name
があります。これは、なんらかの魔法のように動作する文字列属性です。リポジトリ ルールの呼び出しへの入力として指定すると、見かけのリポジトリ名を受け取りますが、repository_ctx.attr.name
を使用してリポジトリルールの実装関数から読み取ると、正規のリポジトリ名が返されます。
実装関数
すべてのリポジトリ ルールに implementation
関数が必要です。ルールの実際のロジックが含まれ、厳密に読み込みフェーズで実行されます。
この関数には、入力パラメータ repository_ctx
が 1 つだけあります。この関数は、指定されたパラメータでルールが再現可能であることを示す None
を返します。または、同じリポジトリを生成する再現可能なルールに変換する、このルールのパラメータ セットを含む dict を返します。たとえば、git リポジトリを追跡するルールの場合、最初に指定されたフローティング ブランチではなく、特定の commit ID を返します。
入力パラメータ repository_ctx
は、属性値と非密閉関数(バイナリの検索、バイナリの実行、リポジトリ内のファイルの作成、インターネットからのファイルのダウンロード)にアクセスするために使用できます。詳しくは、API ドキュメントをご覧ください。例:
def _impl(repository_ctx):
repository_ctx.symlink(repository_ctx.attr.path, "")
local_repository = repository_rule(
implementation=_impl,
...)
実装関数はいつ実行されますか。
リポジトリ ルールの実装関数は、Bazel がそのリポジトリのターゲットを必要とするときに実行されます。たとえば、別のターゲット(別のリポジトリ)がそれに依存している場合や、コマンドラインでそのターゲットが記述されている場合などです。その後、実装関数により、ファイル システムにリポジトリが作成されます。これをリポジトリの「フェッチ」と呼びます。
通常のターゲットとは対照的に、リポジトリが異なってしまうような変更が行われた場合、リポジトリは必ずしも再取得されるとは限りません。これは、Bazel が変更を検出できない問題や、すべてのビルドで過度のオーバーヘッドを発生させるもの(ネットワークから取得されるものなど)があるためです。そのため、リポジトリは次のいずれかが変更された場合にのみ再取得されます。
- リポジトリ ルールの呼び出しに渡される属性。
- Repo ルールの実装を構成する Starlark コード。
repository_ctx
のgetenv()
メソッドに渡されるか、repository_rule
のenviron
属性で宣言された、任意の環境変数の値。これらの環境変数の値は、コマンドラインで--repo_env
フラグを使用して有線接続できます。read()
、execute()
、およびラベルによって参照されるrepository_ctx
の同様のメソッドに渡されるファイルのコンテンツ(たとえば、mypkg/label.txt
ではなく//mypkg:label.txt
)bazel fetch --force
の実行時
リポジトリが再取得されるタイミングを制御する repository_rule
には次の 2 つのパラメータがあります。
configure
フラグが設定されている場合、--configure
パラメータが渡されたときにのみ、リポジトリがbazel fetch
で再取得されます(属性が設定されていない場合、このコマンドは再取得を行いません)。local
フラグが設定されている場合、上記の場合に加えて、Bazel サーバーの再起動時にリポジトリも再取得されます。
実装関数を再起動する
要求する依存関係が欠落している場合、リポジトリの取得中に実装関数を再起動できます。その場合、実装関数の実行が停止して欠落している依存関係が解決され、依存関係が解決された後に関数が再実行されます。不要な再起動(ネットワーク アクセスを繰り返す必要があるため、コストがかかる)を避けるために、すべてのラベル引数を既存のファイルに解決できる場合に、ラベル引数がプリフェッチされます。関数の実行中にのみ作成された文字列またはラベルからパスを解決すると、再起動が発生する可能性があります。
外部リポジトリの強制再取得
定義や依存関係を変更せずに外部リポジトリが古くなることがあります。たとえば、ソースを取得するリポジトリがサードパーティのリポジトリの特定のブランチをたどり、そのブランチで新しい commit を利用できます。この場合、bazel fetch --force --all
を呼び出して、すべての外部リポジトリを無条件に再取得するよう bazel にリクエストできます。
さらに、一部のリポジトリ ルールはローカルマシンを検査するため、ローカルマシンがアップグレードされると古い可能性があります。ここでは、repository_rule
定義に configure
属性が設定されている外部リポジトリのみを再取得するよう Bazel に指示できます(bazel fetch --all --configure
を使用します)。
例
C++ 自動構成ツールチェーン: リポジトリ ルールを使用して、ローカル C++ コンパイラ、環境、C++ コンパイラがサポートするフラグを検索して、Bazel 用の C++ 構成ファイルを自動的に作成します。
Go リポジトリは、いくつかの
repository_rule
を使用して、Go ルールを使用するために必要な依存関係のリストを定義します。rules_jvm_external は、デフォルトで
@maven
という外部リポジトリを作成します。このリポジトリは、推移的依存関係ツリー内のすべての Maven アーティファクトのビルド ターゲットを生成します。