このページでは、リポジトリ ルールの定義方法と、詳細な例について説明します。
外部リポジトリは、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
関数が必要です。ルールの実際のロジックが含まれており、読み込みフェーズで厳密に実行されます。
この関数には、入力パラメータが 1 つ(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 アーティファクトのビルド ターゲットを生成します。