このページでは、リポジトリ ルールの定義方法と、詳細な例について説明します。
外部リポジトリは、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
のみです。この関数は、指定されたパラメータでルールが再現可能であることを示す None
を返すか、そのルールを同じリポジトリを生成する再現可能なルールに変換する一連のパラメータを含む辞書を返します。たとえば、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 が変更を検出できない場合や、すべてのビルドで大量のオーバーヘッドが発生するためです(ネットワークから取得されるものなど)。したがって、リポジトリが再取得されるのは、次のいずれかが変更された場合のみです。
- リポジトリ ルールの呼び出しに渡される属性。
- リポジトリ ルールの実装を含む Starlark コード。
repository_ctx
のgetenv()
メソッドに渡される環境変数の値、またはrepository_rule
のenviron
属性で宣言された環境変数の値。これらの環境変数の値は、--repo_env
フラグを使用してコマンドラインでハードコードできます。- リポジトリ ルールの実装関数で
watch
されるパスの存在、内容、タイプ。watch
パラメータを使用するrepository_ctx
の他のメソッド(read()
、execute()
、extract()
など)でも、パスが監視されることがあります。- 同様に、
repository_ctx.watch_tree
とpath.readdir
を使用すると、他の方法でパスを監視できます。
bazel fetch --force
が実行されたとき。
repository_rule
には、リポジトリの再取得タイミングを制御するパラメータが 2 つあります。
configure
フラグが設定されている場合、bazel fetch --force --configure
でリポジトリが再取得されます(configure
以外のリポジトリは再取得されません)。local
フラグが設定されている場合、上記のケースに加えて、Bazel サーバーが再起動されたときにリポジトリも再取得されます。
外部リポジトリの強制再取得
外部リポジトリの定義や依存関係が変更されていないにもかかわらず、古くなることがあります。たとえば、ソースをフェッチするリポジトリが、サードパーティ リポジトリの特定のブランチの後に続く場合、そのブランチで新しい commit を利用できます。この場合、bazel fetch --force --all
を呼び出して、すべての外部リポジトリを無条件に再取得するよう bazel に指示できます。
また、一部のリポジトリ ルールはローカルマシンを検査するため、ローカルマシンがアップグレードされると古くなる可能性があります。ここで、repository_rule
定義に configure
属性が設定されている外部リポジトリのみを再取得するように Bazel に指示できます。bazel fetch --force
--configure
を使用します。
例
C++ 自動構成ツールチェーン: リポジトリ ルールを使用して、ローカルの C++ コンパイラ、環境、C++ コンパイラがサポートするフラグを検索し、Bazel の C++ 構成ファイルを自動的に作成します。
Go リポジトリでは、複数の
repository_rule
を使用して、Go ルールの使用に必要な依存関係のリストを定義します。rules_jvm_external は、デフォルトで
@maven
という外部リポジトリを作成します。これは、推移的依存関係ツリー内のすべての Maven アーティファクトのビルド ターゲットを生成します。