リポジトリのルール

問題を報告 ソースを表示 Nightly · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

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

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

リポジトリ ルールの作成

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

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

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

属性

属性は、attrs ルール引数に辞書として渡されるルール引数です。属性とその型は、リポジトリ ルールを定義するときに一覧表示されます。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_repositorynew_local_repository の場合と同じです。

属性名が _ で始まる場合、その属性は非公開であり、ユーザーは設定できません。

実装関数

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

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

入力パラメータ 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 フラグを使用してハードコードできます(ただし、このフラグはビルドのすべてのアクションを無効にします)。
  • ラベル(//mypkg:label.txt など。mypkg/label.txt は除く)で参照される repository_ctxread()execute() などのメソッドに渡されるすべてのファイルの内容
  • bazel sync が実行されたとき。

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

  • configure フラグが設定されている場合、リポジトリは bazel sync でのみ再取得されます。これは、--configure パラメータが渡された場合です(属性が設定されていない場合、このコマンドは再取得を引き起こしません)。
  • 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 アーティファクトのビルド ターゲットを生成します。