このページでは、リポジトリ ルールを作成する方法について説明し、詳細な例を示します。
外部リポジトリは、WORKSPACE ファイルでのみ使用できるルールで、Bazel の読み込みフェーズで非密閉型のオペレーションを可能にします。各外部リポジトリ ルールは、独自の BUILD ファイルとアーティファクトを使用して、独自のワークスペースを作成します。これらは、サードパーティ ライブラリ(Maven パッケージ ライブラリなど)に依存するために使用できますが、Bazel が実行されているホストに固有の BUILD ファイルを生成するためにも使用できます。
リポジトリ ルールの作成
.bzl ファイルで、
repository_rule 関数を使用して新しい
リポジトリ ルールを作成し、グローバル変数に保存します。
カスタム リポジトリ ルールは、ネイティブ リポジトリ ルールと同様に使用できます。必須の name 属性があり、ビルドファイル内のすべてのターゲットは @<name>//package:target として参照できます。ここで、 <name> は name 属性の値です。
ルールは、明示的にビルドする場合、またはビルドの依存関係である場合に読み込まれます。この場合、Bazel は implementation 関数を実行します。この関数は、リポジトリ、そのコンテンツ、BUILD ファイルの作成方法を記述します。
属性
属性は、attrs ルール引数に dict として渡されるルール引数です。
属性とその型は、リポジトリ ルールを定義するときに定義されます。url 属性と sha256 属性を文字列として定義する例を次に示します。
local_repository = repository_rule(
implementation=_impl,
local=True,
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 には、暗黙的に定義された属性があります(ビルドルールと同様)。2 つの暗黙的な属性は、name(ビルドルールの場合と同様)と repo_mapping です。リポジトリ ルールの名前には repository_ctx.name でアクセスできます。repo_mapping の意味は、
ネイティブ リポジトリ ルール
local_repository
と
new_local_repositoryの場合と同じです。
属性名が _ で始まる場合、その属性は非公開であり、ユーザーは設定できません。
実装関数
すべてのリポジトリ ルールには implementation 関数が必要です。これにはルールの実際のロジックが含まれており、読み込みフェーズで厳密に実行されます。
この関数には、入力パラメータが 1 つだけあります。repository_ctx です。この関数は、指定されたパラメータでルールを再現できることを示す None を返すか、そのルールを再現可能なルールにして同じリポジトリを生成するルールのパラメータのセットを含む dict を返します。たとえば、git リポジトリを追跡するルールの場合、元々指定されていたフローティング ブランチではなく、特定の commit ID を返します。
入力パラメータ repository_ctx を使用して、属性値と非密閉型関数(バイナリの検索、バイナリの実行、リポジトリでのファイルの作成、インターネットからのファイルのダウンロード)にアクセスできます。詳細については、ライブラリをご覧ください
。例:
def _impl(repository_ctx):
repository_ctx.symlink(repository_ctx.attr.path, "")
local_repository = repository_rule(
implementation=_impl,
...)
実装関数はいつ実行されますか?
リポジトリの実装関数は、Bazel がそのリポジトリのターゲットを必要とするときに実行されます。たとえば、別のターゲット(別のリポジトリ内)がそのリポジトリに依存している場合や、コマンドラインでそのリポジトリが指定されている場合などです。実装関数は、ファイル システムにリポジトリを作成することが想定されています。これはリポジトリの「フェッチ」と呼ばれます。
通常、リポジトリが異なる原因となる変更が発生した場合でも、通常ターゲットとは異なり、リポジトリが必ずしも再フェッチされるとは限りません。これは、Bazel が変更を検出できないものや、ビルドごとにオーバーヘッドが大きすぎるもの(ネットワークからフェッチされるものなど)があるためです。そのため、リポジトリは次のいずれかが変更された場合にのみ再フェッチされます。
WORKSPACEファイル内のリポジトリの宣言に渡されるパラメータ。- リポジトリの実装を構成する Starlark コード。
repository_ruleのenviron属性で宣言された環境変数の値。これらの環境変数の値は、コマンド ラインで--action_envフラグを使用してハードコードできます(ただし、このフラグを使用すると、ビルドのすべてのアクションが無効になります)。- ラベル(
//mypkg:label.txtなど。mypkg/label.txtではない)で参照されるrepository_ctxのread()、execute()などのメソッドに渡されるファイルのコンテンツ。 bazel syncが実行された場合。
リポジトリが再フェッチされるタイミングを制御する repository_rule のパラメータは 2 つあります。
configureフラグが設定されている場合、リポジトリはbazel syncでのみ再フェッチされます。このとき、--configureパラメータが渡されます( 属性が設定されていない場合、このコマンドを実行しても再フェッチは行われません)。localフラグが設定されている場合、上記の場合に加えて、Bazel サーバーが再起動したとき、またはリポジトリの宣言に影響するファイル(WORKSPACEファイルやロードするファイルなど)が変更されたときにも、リポジトリが再フェッチされます。これは、変更によってリポジトリの宣言やコードが変更されたかどうかに関係なく行われます。このような場合、ローカル以外のリポジトリは再フェッチされません。これは、これらのリポジトリがネットワークと通信するか、他の方法でコストがかかることが想定されるためです。
実装関数の再起動
リポジトリのフェッチ中に、リクエストされた依存関係が不足している場合、実装関数を再起動できます。この場合、実装関数の実行が停止し、不足している依存関係が解決されます。依存関係が解決されると、関数が再実行されます。不要な再起動(ネットワーク アクセスを繰り返す必要があるためコストがかかる)を回避するため、すべてのラベル引数を既存のファイルに解決できる場合は、ラベル引数がプリフェッチされます。なお、関数の実行中にのみ構築された文字列またはラベルからパスを解決すると、再起動が発生する可能性があります。
外部リポジトリの再フェッチを強制する
定義や依存関係が変更されなくても、外部リポジトリが古くなることがあります。たとえば、ソースをフェッチするリポジトリがサードパーティ リポジトリの特定のブランチを追跡し、そのブランチで新しい commit が利用可能になっている場合などです。この場合、bazel sync を呼び出すことで、すべての外部リポジトリを無条件に再フェッチするように Bazel に指示できます。
また、ローカル マシンを検査するルールもあり、ローカル マシンがアップグレードされると古くなる可能性があります。この場合、bazel に
、
repository_rule
定義に configure 属性が設定されている外部リポジトリのみを再フェッチするように指示するには、bazel sync --configure を使用します。
例
C++ 自動構成ツールチェーン: リポジトリ ルールを使用して、ローカル C++ コンパイラ、環境、C++ コンパイラがサポートするフラグを検索することで、Bazel 用の C++ 構成ファイルを自動的に作成します。
Go リポジトリ は、複数の
repository_ruleを使用して、依存関係のリストを定義します Go ルールの使用に必要です。rules_jvm_external は、デフォルトで
@mavenという名前の外部リポジトリを作成します。このリポジトリは、推移的な依存関係ツリー内のすべての Maven アーティファクトのビルドターゲットを生成します。