このページでは、リポジトリ ルールを定義する方法について説明し、詳細な例を示します。
外部リポジトリは、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 リポジトリを追跡するルールの場合、元々指定されたフローティング ブランチではなく、特定のコミット識別子を返すことになります。
入力パラメータ 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 アーティファクトのビルド ターゲットを生成します。