ルールのチュートリアル

<ph type="x-smartling-placeholder"></ph> 問題を報告する <ph type="x-smartling-placeholder"></ph> ソースを表示 夜間 · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

Starlark は、Python に似た Bazel で使用するために開発され、その後採用されました。 分析できますBazel の BUILD ファイルと .bzl ファイルは、次の言語で記述します。 Starlark は「Build Language」としてよく知られていますが、単に 「Starlark」と呼ばれます。特に、ある特徴が 組み込みまたは「ネイティブ」ではなく、Build Language で表現されます。部品 使用されます。Bazel は多くのビルド関連機能でコア言語を強化 globgenrulejava_binary など。

詳しくは、 BazelStarlark のドキュメント: 詳細情報が表示され、 ルール SIG テンプレートを 新しいルールセットの作成を開始できます。

空のルール

最初のルールを作成するには、foo.bzl ファイルを作成します。

def _foo_binary_impl(ctx):
    pass

foo_binary = rule(
    implementation = _foo_binary_impl,
)

rule 関数を呼び出すと、次の処理が行われます。 コールバック関数を定義する必要があります。ロジックはここで行いますが、 今のところは関数を空のままにしておくことができます。ctx 引数 ターゲットに関する情報を提供します。

ルールは、BUILD ファイルから読み込んで使用できます。

同じディレクトリに BUILD ファイルを作成します。

load(":foo.bzl", "foo_binary")

foo_binary(name = "bin")

これで、ターゲットをビルドできるようになりました。

$ bazel build bin
INFO: Analyzed target //:bin (2 packages loaded, 17 targets configured).
INFO: Found 1 target...
Target //:bin up-to-date (nothing to build)

このルールは何も行いませんが、すでに他のルールと同じように動作します。つまり、 必須の名前。visibilitytestonlytags

評価モデル

先に進む前に、コードがどのように評価されているかを理解することが重要です。

print ステートメントを使用して foo.bzl を更新します。

def _foo_binary_impl(ctx):
    print("analyzing", ctx.label)

foo_binary = rule(
    implementation = _foo_binary_impl,
)

print("bzl file evaluation")

BUILD:

load(":foo.bzl", "foo_binary")

print("BUILD file")
foo_binary(name = "bin1")
foo_binary(name = "bin2")

ctx.label 分析するターゲットのラベルに対応します。ctx オブジェクトには、 多くの有用なフィールドとメソッドがあります。詳細は API リファレンス

コードをクエリします。

$ bazel query :all
DEBUG: /usr/home/bazel-codelab/foo.bzl:8:1: bzl file evaluation
DEBUG: /usr/home/bazel-codelab/BUILD:2:1: BUILD file
//:bin2
//:bin1

いくつか観察してみましょう。

  • "bzl ファイルの評価"が最初に出力されます。BUILD ファイルを評価する前に、 Bazel は、読み込まれるすべてのファイルを評価します。複数の BUILD ファイルが読み込まれている場合 foo.bzl の場合、「bzl file Evaluation」は 1 件しか表示されません。なぜなら Bazel は評価結果をキャッシュに保存します。
  • コールバック関数 _foo_binary_impl は呼び出されません。Bazel クエリの読み込み BUILD ファイルですが、ターゲットは分析されません。

ターゲットを分析するには、cquery(構成済み クエリ)、または build コマンドを使用します。

$ bazel build :all
DEBUG: /usr/home/bazel-codelab/foo.bzl:2:5: analyzing //:bin1
DEBUG: /usr/home/bazel-codelab/foo.bzl:2:5: analyzing //:bin2
INFO: Analyzed 2 targets (0 packages loaded, 0 targets configured).
INFO: Found 2 targets...

ご覧のとおり、_foo_binary_impl は 2 回(ターゲットごとに 1 回)呼び出されるようになりました。

「bzl file Evaluation」は「BUILD ファイル」も再度出力されて foo.bzl の評価は bazel query の呼び出し後にキャッシュに保存されるためです。 Bazel は、実際に実行された場合にのみ print ステートメントを出力します。

ファイルの作成

ルールをより有用なものにするには、ファイルを生成するようにルールを更新してください。まず、 名前を付けます。この例では、「 ターゲット:

ctx.actions.declare_file(ctx.label.name)

ここで bazel build :all を実行すると、エラーが発生します。

The following files have no generating action:
bin2

ファイルを宣言するたびに、ファイルの生成方法を Bazel に指示する必要があります。 作成します。ctx.actions.write を使用する。 指定した内容のファイルを作成します。

def _foo_binary_impl(ctx):
    out = ctx.actions.declare_file(ctx.label.name)
    ctx.actions.write(
        output = out,
        content = "Hello\n",
    )

コードは有効ですが、何の動作も起こりません。

$ bazel build bin1
Target //:bin1 up-to-date (nothing to build)

ctx.actions.write 関数が Bazel を学習させるアクションを登録しました ファイルの生成方法を説明します。ただし、Bazel は、次の状態になるまでファイルを作成しません。 確認できます。最後に、Bazel にファイルを ルールの出力であり、ルール内で使用される一時ファイルではない 説明します。

def _foo_binary_impl(ctx):
    out = ctx.actions.declare_file(ctx.label.name)
    ctx.actions.write(
        output = out,
        content = "Hello!\n",
    )
    return [DefaultInfo(files = depset([out]))]

後で DefaultInfo 関数と depset 関数を確認します。現在のところ、 最後の行がルールの出力を選択する方法であると仮定します。

次に、Bazel を実行します。

$ bazel build bin1
INFO: Found 1 target...
Target //:bin1 up-to-date:
  bazel-bin/bin1

$ cat bazel-bin/bin1
Hello!

ファイルが正常に生成されました。

属性

ルールをより有用なものにするには、 attr モジュールを実行してルール定義を更新します。

username という文字列属性を追加します。

foo_binary = rule(
    implementation = _foo_binary_impl,
    attrs = {
        "username": attr.string(),
    },
)

次に、BUILD ファイルで設定します。

foo_binary(
    name = "bin",
    username = "Alice",
)

コールバック関数の値にアクセスするには、ctx.attr.username を使用します。次に例を示します。

def _foo_binary_impl(ctx):
    out = ctx.actions.declare_file(ctx.label.name)
    ctx.actions.write(
        output = out,
        content = "Hello {}!\n".format(ctx.attr.username),
    )
    return [DefaultInfo(files = depset([out]))]

この属性は必須にすることも、デフォルト値を設定することもできます。注目すべき点は、 attr.string のドキュメントをご覧ください。 ブール値など、他のタイプの属性を使用することもできます。 または整数のリスト

依存関係

依存関係属性(attr.label など) および attr.label_list、 属性を所有するターゲットから、属性を所有するターゲットへの依存関係を宣言します。 属性値に出現するラベルを表します。この種の属性は 表します。

BUILD ファイルでは、ターゲット ラベルは次のような文字列オブジェクトとして表示されます。 //pkg:name。実装関数では、ターゲットは Target オブジェクト。たとえば、返されたファイルを表示して Target.files を使用してターゲットごとに設定できます。

複数のファイル

デフォルトでは、ルールによって作成されたターゲットのみが依存関係として表示されます( foo_library() のターゲット)。属性で許容されるターゲットの指定が 入力ファイル(リポジトリ内のソースファイルなど)を使用する場合、 allow_files で、使用可能なファイル拡張子のリスト(または True 任意のファイル拡張子を許可する)を選択します。

"srcs": attr.label_list(allow_files = [".java"]),

ファイルのリストには ctx.files.<attribute name> でアクセスできます。対象 たとえば、srcs 属性のファイルのリストには、

ctx.files.srcs

単一ファイル

必要なファイルが 1 つだけの場合は、allow_single_file を使用します。

"src": attr.label(allow_single_file = [".java"])

このファイルは ctx.file.<attribute name> でアクセスできます。

ctx.file.src

テンプレートを使用してファイルを作成する

テンプレートに基づいて .cc ファイルを生成するルールを作成できます。また、 ctx.actions.write を使用して、ルールで作成された文字列を出力できます。 ただし、2 つの問題があります。まず、テンプレートに 大きければ、別のファイルに入れてメモリ効率が上がり、 長い文字列を構築することです。2 つ目は、別の Pod に ユーザーにとっては便利です。代わりに、 ctx.actions.expand_template テンプレートファイルの置換を実行します

template 属性を作成してテンプレートへの依存関係を宣言する ファイル:

def _hello_world_impl(ctx):
    out = ctx.actions.declare_file(ctx.label.name + ".cc")
    ctx.actions.expand_template(
        output = out,
        template = ctx.file.template,
        substitutions = {"{NAME}": ctx.attr.username},
    )
    return [DefaultInfo(files = depset([out]))]

hello_world = rule(
    implementation = _hello_world_impl,
    attrs = {
        "username": attr.string(default = "unknown person"),
        "template": attr.label(
            allow_single_file = [".cc.tpl"],
            mandatory = True,
        ),
    },
)

ユーザーはルールを次のように使用できます。

hello_world(
    name = "hello",
    username = "Alice",
    template = "file.cc.tpl",
)

cc_binary(
    name = "hello_bin",
    srcs = [":hello"],
)

テンプレートをエンドユーザーに公開したくない場合は、必ず デフォルト値を設定して、属性を非公開にすることもできます。

    "_template": attr.label(
        allow_single_file = True,
        default = "file.cc.tpl",
    ),

アンダースコアで始まる属性は非公開であり、 BUILD ファイル。テンプレートが暗黙的な依存関係になりました。すべての hello_world target はこのファイルと依存関係があります。このファイルは必ず公開してください 他のパッケージに追加するには、BUILD ファイルを更新し、 exports_files:

exports_files(["file.cc.tpl"])

さらに先へ