このページでは、リポジトリ ルールを定義する方法について説明し、詳細な例を示します。
外部リポジトリは、Bazel ビルドで使用可能なソースファイルを含むディレクトリ ツリーです。これは、対応するリポジトリ ルールを実行することでオンデマンドで生成されます。リポジトリはさまざまな方法で定義できますが、最終的には、ビルド ターゲットがビルドルールを呼び出すことで定義されるのと同様に、リポジトリルールを呼び出すことで定義されます。これらは、サードパーティ ライブラリ(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 を返すか、そのルールを再現可能なものにして同じリポジトリを生成するパラメータのセットを含む辞書を返します。たとえば、git リポジトリを追跡するルールの場合、元々指定されたフローティング ブランチではなく、特定の commit 識別子を返すことになります。
入力パラメータ repository_ctx を使用して、属性値と非ハーメチック関数(バイナリの検索、バイナリの実行、リポジトリでのファイルの作成、インターネットからのファイルのダウンロード)にアクセスできます。詳細については、API ドキュメントをご覧ください。例:
def _impl(repository_ctx):
repository_ctx.symlink(repository_ctx.attr.path, "")
local_repository = repository_rule(
implementation=_impl,
...)
実装関数はいつ実行されますか?
リポジトリ ルールの実装関数は、Bazel がそのリポジトリのターゲットを必要とするときに実行されます。たとえば、別のターゲット(別のリポジトリ内)がそれに依存している場合や、コマンドラインで言及されている場合などです。実装関数は、ファイル システムにリポジトリを作成することが想定されています。これは、リポジトリの「フェッチ」と呼ばれます。
通常のターゲットとは異なり、リポジトリが異なる原因となる変更があっても、リポジトリが再取得されるとは限りません。これは、Bazel が変更を検出できないものや、すべてのビルドでオーバーヘッドが大きすぎるもの(ネットワークから取得されるものなど)があるためです。そのため、リポジトリは次のいずれかが変更された場合にのみ再取得されます。
- リポジトリルールの呼び出しに渡される属性。
- リポジトリ ルールの実装を構成する Starlark コード。
repository_ctxのgetenv()メソッドに渡されるか、repository_ruleのenviron属性で宣言された環境変数の値。これらの環境変数の値は、--repo_envフラグを使用してコマンドラインでハードワイヤードできます。- リポジトリルールの実装関数で
watchされるパスの存在、コンテンツ、タイプ。read()、execute()、extract()など、watchパラメータを持つrepository_ctxの他のメソッドも、パスの監視を引き起こす可能性があります。- 同様に、
repository_ctx.watch_treeとpath.readdirを使用すると、パスが他の方法で監視される可能性があります。
bazel fetch --forceが実行されたとき。
repository_rule には、リポジトリが再取得されるタイミングを制御する 2 つのパラメータがあります。
configureフラグが設定されている場合、リポジトリはbazel fetch --force --configureで再取得されます(configure以外のリポジトリは再取得されません)。localフラグが設定されている場合、上記の場合に加えて、Bazel サーバーが再起動されたときにもリポジトリが再取得されます。
外部リポジトリの再取得を強制する
外部リポジトリは、定義や依存関係が変更されていなくても、古くなることがあります。たとえば、ソースを取得するリポジトリがサードパーティ リポジトリの特定のブランチをフォローし、そのブランチで新しいコミットが利用可能になっている場合があります。この場合、bazel fetch --force --all を呼び出すことで、すべての外部リポジトリを無条件で再取得するように bazel に指示できます。
また、一部の repo ルールはローカルマシンを検査するため、ローカルマシンがアップグレードされると古くなる可能性があります。ここでは、repository_rule 定義に configure 属性が設定されている外部リポジトリのみを再取得するように Bazel に指示できます。その場合は、bazel fetch --force
--configure を使用します。
例
C++ 自動構成ツールチェーン: リポジトリ ルールを使用して、ローカル C++ コンパイラ、環境、C++ コンパイラがサポートするフラグを検索し、Bazel 用の C++ 構成ファイルを自動的に作成します。
Go リポジトリでは、複数の
repository_ruleを使用して、Go ルールの使用に必要な依存関係のリストを定義します。rules_jvm_external は、デフォルトで
@mavenという外部リポジトリを作成します。このリポジトリは、推移的依存関係ツリー内のすべての Maven アーティファクトのビルド ターゲットを生成します。