リポジトリ ルール

問題を報告する ソースを表示

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

外部リポジトリは、WORKSPACE ファイルでのみ使用できるルールで、Bazel の読み込みフェーズで非密閉オペレーションを有効にします。各外部リポジトリ ルールは、それぞれ独自の BUILD ファイルとアーティファクトを持つ独自のワークスペースを作成します。サードパーティのライブラリ(Maven のパッケージ化ライブラリなど)に依存する場合や、Bazel が実行されているホストに固有の BUILD ファイルを生成する場合にも使用できます。

リポジトリ ルールの作成

.bzl ファイルで、repository_rule 関数を使用して、新しいリポジトリ ルールを作成し、グローバル変数に格納します。

カスタム リポジトリ ルールは、ネイティブ リポジトリ ルールと同じように使用できます。必須の name 属性があり、ビルドファイル内のすべてのターゲットを @<name>//package:target として参照できます。ここで、<name>name 属性の値です。

このルールは、明示的にビルドするとき、またはビルドの依存関係である場合に読み込まれます。この場合、Bazel は implementation 関数を実行します。この関数は、リポジトリ、そのコンテンツ、BUILD ファイルの作成方法について説明します。

属性

属性は、urlsha256 などのルール引数です。リポジトリ ルールを定義するときは、属性とそのタイプを一覧表示する必要があります。

local_repository = repository_rule(
    implementation=_impl,
    local=True,
    attrs={"path": attr.string(mandatory=True)})

属性にアクセスするには、repository_ctx.attr.<attribute_name> を使用します。

すべての repository_rule には、(ビルドルールと同様に)暗黙的に定義された属性があります。暗黙的な属性は、ビルドルールと同様、namerepo_mapping の 2 つです。リポジトリ ルールの名前は repository_ctx.name でアクセスできます。repo_mapping の意味は、ネイティブ リポジトリ ルール local_repository および new_local_repository と同じです。

属性名の先頭が _ である場合、この属性は非公開であり、ユーザーが設定することはできません。

実装関数

すべてのリポジトリ ルールには implementation 関数が必要です。このルールの実際のロジックが含まれ、読み込みフェーズでのみ実行されます。

この関数には入力パラメータが 1 つだけ repository_ctx あります。この関数は、指定されたパラメータを指定してルールが再現可能であることを示す None か、そのルールの一連のパラメータを含む辞書を返します。このルールは、同じリポジトリを生成する再現可能なルールに変換します。たとえば、git リポジトリを追跡するルールの場合、最初に指定されたフローティング ブランチではなく、特定の commit 識別子が返されます。

入力パラメータ repository_ctx を使用すると、属性値と非密閉関数にアクセスできます(バイナリの検索、バイナリの実行、リポジトリでのファイルの作成、インターネットからのファイルのダウンロードなど)。詳細については、ライブラリをご覧ください。例:

def _impl(repository_ctx):
  repository_ctx.symlink(repository_ctx.attr.path, "")

local_repository = repository_rule(
    implementation=_impl,
    ...)

実装関数はいつ実行されますか?

リポジトリの実装関数は、Bazel がそのリポジトリからターゲットを必要としているときに実行されます。たとえば、別のターゲットが(別のリポジトリに)あるターゲットが依存している場合、またはコマンドラインで言及されている場合です。実装関数では、ファイル システムにリポジトリを作成する必要があります。これは、リポジトリの「フェッチ」と呼ばれます。

通常のターゲットとは対照的に、リポジトリが異なる原因となるような変更が発生した場合、リポジトリは必ずしも再取得されるわけではありません。これは、Bazel が変更を検出できないもの、またはビルドのたびにオーバーヘッドが多すぎるためです(ネットワークから取得されるものなど)。したがって、リポジトリは、次のいずれかが変更された場合にのみ再取得されます。

  • WORKSPACE ファイルのリポジトリの宣言に渡されるパラメータ。
  • リポジトリの実装を構成する Starlark コード。
  • repository_ruleenviron 属性で宣言されている環境変数の値。これらの環境変数の値は、コマンドラインで --action_env フラグを使用してハードワイヤーできます(ただし、このフラグはビルドのすべてのアクションを無効にします)。
  • ラベルで参照される repository_ctxread()execute() および同様のメソッド(read() など)に渡されるファイルのコンテンツ(例: //mypkg:label.txtmypkg/label.txt ではない)。
  • bazel sync が実行されたとき。

リポジトリが再度取得されるタイミングを制御する repository_rule の 2 つのパラメータがあります。

  • configure フラグが設定されている場合、--configure パラメータが渡されたときにのみ、bazel sync でリポジトリが再取得されます(属性が設定されていない場合、このコマンドは再取得しません)。
  • local フラグが設定されている場合、上記のに加えて、Bazel サーバーの再起動時や、リポジトリの宣言に影響するファイル(WORKSPACE ファイルや読み込みファイルなど)が変更されたときにもリポジトリが再取得されます。この変更により、リポジトリまたはコードの宣言が変更されたかどうかも異なります。

    このような場合、ローカル以外のリポジトリは再取得されません。これは、これらのリポジトリはネットワークと通信する、または高額であると想定されているためです。

実装関数を再起動する

リポジトリの取得中に、リクエストする依存関係が欠けている場合は、実装関数を再起動できます。その場合、実装関数の実行が停止し、不足している依存関係が解決され、依存関係が解決された後に関数が再実行されます。不必要な再起動(ネットワーク アクセスが繰り返されることがあるため高額な)を避けるため、すべてのラベル引数を既存のファイルに解決できる場合、ラベル引数がプリフェッチされます。関数の実行中にのみ作成された文字列またはラベルからのパスを解決しても、再起動が発生することがあります。

外部リポジトリの再取得を強制する

外部リポジトリは、その定義や依存関係を変更せずに古い場合があります。たとえば、ソースを取得するリポジトリがサードパーティ リポジトリの特定のブランチをフォローし、そのブランチで新しい commit が使用可能になる場合があります。この場合、bazel sync を呼び出して、すべての外部リポジトリを無条件に再取得するよう bazel に要求できます。

さらに、一部のルールではローカルマシンの検査が行われ、ローカルマシンがアップグレードされると情報が古くなる可能性があります。ここでは、repository_rule 定義に configure 属性が設定されている外部リポジトリのみを再度取得するように bazel に要求できます。その場合、bazel sync --configure を使用します。

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

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

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