リポジトリのルール

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

外部リポジトリは、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 を返すか、そのルールを再現可能なルールにして同じリポジトリを生成するルールのパラメータのセットを含む dict を返します。たとえば、git リポジトリを追跡するルールの場合、元々指定されていたフローティング ブランチではなく、特定のコミット 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 のメソッドに渡される環境変数、または environ 属性で宣言された環境変数の値。getenv()repository_ruleこれらの環境変数の値は、コマンドラインで --repo_env フラグを使用してハードコードできます。
  • リポジトリ ルールの実装関数で watchedされているパスの存在、コンテンツ、タイプ。
    • 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 サーバーが再起動したときにもリポジトリが再フェッチされます。

外部リポジトリの再フェッチを強制する

定義や依存関係を変更しなくても、外部リポジトリが古くなることがあります。たとえば、ソースをフェッチするリポジトリがサードパーティ リポジトリの特定のブランチを追跡し、そのブランチで新しいコミットが利用可能になっている場合などです。この場合、Bazel にすべての外部リポジトリを無条件に再フェッチするように指示できます bazel fetch --force --all を呼び出すことによって。

また、一部のリポジトリ ルールはローカルマシンを検査するため、ローカルマシンがアップグレードされると古くなる可能性があります。この場合、 定義に configure 属性が設定されている外部リポジトリのみを再フェッチするように Bazel に指示するには、bazel fetch --force --configure を使用します。repository_rule

  • C++ 自動構成 ツールチェーン: リポジトリ ルールを使用して、ローカル C++ コンパイラ、環境、C++ コンパイラがサポートするフラグを検索することで、Bazel 用の C++ 構成ファイルを自動的に作成します。

  • Go リポジトリ は、複数の repository_rule を使用して、Go ルールを 使用するために必要な依存関係のリストを定義します。

  • rules_jvm_external は、デフォルトで @maven という外部リポジトリを作成します。このリポジトリは、推移的依存関係ツリー内のすべての Maven アーティファクトのビルド ターゲットを生成します。