リポジトリのルール

問題を報告する ソースを表示 ナイトリー · 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

このページでは、リポジトリ ルールの定義方法と、詳細な例について説明します。

外部リポジトリは、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_ctxgetenv() メソッドに渡される環境変数の値、または repository_ruleenviron 属性で宣言された環境変数の値。これらの環境変数の値は、--repo_env フラグを使用してコマンドラインでハードコードできます。
  • リポジトリ ルールの実装関数で watch されるパスの存在、内容、タイプ。
    • watch パラメータを使用する repository_ctx の他のメソッド(read()execute()extract() など)でも、パスが監視されることがあります。
    • 同様に、repository_ctx.watch_treepath.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 アーティファクトのビルド ターゲットを生成します。