変数を作成する

問題を報告 {2/7}

「Make」変数は、「Make 変数」置換に従うとマークされた属性で使用できる展開可能な文字列変数の特別なクラスです。

たとえば、ユーザーが作成したビルド アクションに特定のツールチェーン パスを挿入するために使用できます。

Bazel では、すべてのターゲットで使用できる事前定義変数と、依存関係ターゲットで定義され、それらに依存するターゲットでのみ使用可能なカスタム変数の両方が用意されています。

「Make」という用語が使われている理由は、歴史上、これらの変数の構文とセマンティクスはもともと GNU Make と一致することを意図したものでした。

使う

「Make 変数置換の対象」とマークされている属性は、次のように「Make」変数 FOO を参照できます。

my_attr = "prefix $(FOO) suffix"

つまり、$(FOO) に一致する部分文字列は FOO の値に展開されます。その値が "bar" の場合、最終的な文字列は次のようになります。

my_attr = "prefix bar suffix"

FOO が使用ターゲットで認識されている変数に対応していない場合、Bazel はエラーで失敗します。

名前が文字以外の記号(@ など)である「Make」変数は、かっこなしでドル記号のみを使用して参照することもできます。次に例を示します。

my_attr = "prefix $@ suffix"

$ を文字列リテラルとして記述する(変数が展開されないようにする)には、$$ と記述します。

事前定義された変数

事前定義された「Make」変数は、任意のターゲットで「「Make variable」置換の対象」とマークされている属性で参照できます。

特定のビルド オプション セットについて、これらの変数とその値のリストを表示するには、次のコマンドを実行します。

bazel info --show_make_env [build options]

大文字の出力行を確認します

事前定義の変数の例をご覧ください

ツールチェーン オプション変数

  • COMPILATION_MODE: fastbuilddbg、または opt。(詳細)。

パス変数

  • BINDIR: ターゲット アーキテクチャ用に生成されるバイナリツリーのベース。

    クロスコンパイルをサポートするために、ホスト アーキテクチャでのビルド中に実行されるプログラムに別のツリーが使用される場合があります。

    genrule 内からツールを実行する場合、パスを取得するおすすめの方法は $(execpath toolname) です。ここで、toolnamegenruletools 属性にリストされている必要があります。

  • GENDIR: ターゲット アーキテクチャ用に生成されるコードツリーのベース。

マシン アーキテクチャ変数

  • TARGET_CPU: ターゲット アーキテクチャの CPU(例: k8)。

事前定義された genrule 変数

以下は、genrulecmd 属性で特に利用可能で、通常はその属性を機能させるうえで重要です。

事前定義の genrule 変数の例をご覧ください

  • OUTS: genruleouts リスト。出力ファイルが 1 つしかない場合は、$@ を使用することもできます。
  • SRCS: genrulesrcs リスト(正確には srcs リスト内のラベルに対応するファイルのパス名)。ソースファイルが 1 つしかない場合は、$< を使用することもできます。
  • <: SRCS(単一ファイルの場合)。それ以外の場合、ビルドエラーがトリガーされます。
  • @: OUTS(単一ファイルの場合)。それ以外の場合、ビルドエラーがトリガーされます。
  • RULEDIR: ターゲットの出力ディレクトリ。つまり、genfiles または bin ツリーの下にあるターゲットを含むパッケージの名前に対応するディレクトリです。//my/pkg:my_genrule の場合、//my/pkg:my_genrule の出力がサブディレクトリにある場合でも、常に my/pkg で終了します。

  • @D: 出力ディレクトリ。outs にエントリが 1 つある場合は、そのファイルを含むディレクトリに展開されます。複数のエントリがある場合、すべての出力ファイルが同じサブディレクトリにある場合でも、genfiles ツリー内のパッケージのルート ディレクトリに展開されます。

    注: @D ではなく RULEDIR を使用してください。RULEDIR はセマンティクスがシンプルで、出力ファイルの数に関係なく同じように動作するためです。

    genrule で一時的な中間ファイルを生成する必要がある場合(コンパイラなどの他のツールを使用した場合など)、@D への書き込みを試行し(/tmp も書き込み可能です)、終了前にそれらを削除します。

    特に、入力を含むディレクトリへの書き込みは避けてください。読み取り専用のファイルシステム上にある可能性があります。そうしなくても、ソースツリーが破棄されます。

事前定義されたソース/出力パス変数

事前定義された変数 execpathexecpathsrootpathrootpathslocationlocations は、ラベル パラメータ($(execpath //foo:bar) など)を受け取り、そのラベルで示されるファイルパスを置き換えます。

ソースファイルの場合、ワークスペースのルートからの相対パスです。ルールの出力であるファイルの場合、これはファイルの出力パスです(以下の出力ファイルの説明をご覧ください)。

事前定義されたパス変数の例をご覧ください

  • execpath: Bazel がビルド アクションを実行する execroot の下のパスを示します。

    上記の例では、Bazel は、ワークスペースのルートの bazel-myproject シンボリック リンクでリンクされたディレクトリですべてのビルド アクションを実行します。ソースファイル empty.source はパス bazel-myproject/testapp/empty.source でリンクされています。そのため、実行パス(ルートの下のサブパス)は testapp/empty.source になります。これは、ビルド アクションがファイルを見つけるために使用できるパスです。

    出力ファイルも同様にステージングされますが、サブパス bazel-out/cpu-compilation_mode/bin(またはツールの出力の場合は bazel-out/cpu-opt-exec-hash/bin)が付きます。上記の例では、//testapp:appshow_app_outputtools 属性にあるためツールです。そのため、出力ファイル appbazel-myproject/bazel-out/cpu-opt-exec-hash/bin/testapp/app に書き込まれます。したがって、exec パスは bazel-out/cpu-opt-exec-hash/bin/testapp/app になります。この接頭辞を追加することで、結果が相互に上書きされることなく、たとえば同じビルド内で 2 つの異なる CPU に対して同じターゲットをビルドできます。

    この変数に渡されるラベルは、1 つのファイルのみを表す必要があります。ソースファイルを表すラベルの場合、これは自動的に true になります。ルールを表すラベルの場合、ルールは 1 つの出力のみを生成する必要があります。これが false であるか、ラベルの形式が正しくない場合、ビルドはエラーで失敗します。

  • rootpath: ビルドバイナリが実行時に依存関係を見つけるために使用できるパス。メイン リポジトリに対応する runfiles ディレクトリのサブディレクトリとの相対パスを示します。 注: これは --enable_runfiles が有効になっている場合にのみ機能しますが、Windows のデフォルトは有効ではありません。クロス プラットフォーム サポートの場合は、代わりに rlocationpath を使用してください。

    これは execpath に似ていますが、上記の構成の接頭辞が削除されます。上記の例では、empty.sourceapp の両方でワークスペース相対パス(testapp/empty.sourcetestapp/app)のみが使用されます。

    外部リポジトリ repo 内のファイルの rootpath は、../repo/ で始まり、その後にリポジトリ相対パスが続きます。

    これには、execpath と同じ「1 つの出力のみ」の要件があります。

  • rlocationpath: ビルドバイナリが runfiles ライブラリの Rlocation 関数に渡すパス。実行時に、runfiles ディレクトリ(利用可能な場合)、または runfiles マニフェストを使用して依存関係を検出します。

    これは、構成の接頭辞を含まない点で rootpath と似ていますが、常にリポジトリの名前で始まる点で異なります。上記の例では、 empty.sourceapp がパス myproject/testapp/empty.source myproject/testapp/app になることを意味します。

    外部リポジトリ repo 内のファイルの rlocationpath は、repo/ で始まり、その後にリポジトリ相対パスが続きます。

    実行時に依存関係を見つけるには、このパスをバイナリに渡し、runfile ライブラリを使用してファイル システム パスに解決することをおすすめします。rootpath と比較すると、runfiles ディレクトリが利用できない場合でも、すべてのプラットフォームで動作するという利点があります。

    これには、execpath と同じ「1 つの出力のみ」の要件があります。

  • location: 展開する属性に応じて execpath または rootpath の同義語。これは Starlark 以前の従来の動作であり、特定のルールでの動作を深く理解していない限り、おすすめしません。詳細については、#2475 をご覧ください。

execpathsrootpathsrlocationpathslocations は、それぞれ execpathrootpathrlocationpathslocation の複数形です。複数の出力を生成するラベルがサポートされています。この場合、各出力はスペースで区切って表示されます。出力がないルールやラベルの形式が正しくないと、ビルドエラーが発生します。

参照されるすべてのラベルは、使用ターゲットの srcs、出力ファイル、または deps に存在している必要があります。それ以外の場合、ビルドは失敗します。C++ ターゲットは data 内のラベルを参照することもできます。

ラベルは正規形式である必要はありません。foo:foo//somepkg:foo はすべて問題ありません。

カスタム変数

カスタムの「Make」変数は、「Make variable」置換の対象とマークされているすべての属性から参照できますが、これらの変数を定義している他のターゲットに依存するターゲットでのみ参照できます。

ベスト プラクティスとして、コア Bazel に組み込む正当な理由がない限り、すべての変数はカスタムにする必要があります。これにより、Bazel は、負荷がかかる可能性のある依存関係を読み込んで、taret を使用する変数が考慮しない変数を提供する必要がなくなります。

C++ ツールチェーン変数

以下は C++ ツールチェーン ルールで定義されており、toolchains = ["@bazel_tools//tools/cpp:current_cc_toolchain"] を設定するすべてのルールで使用できます。java_binary などの一部のルールには、ルール定義に C++ ツールチェーンが暗黙的に含まれています。これらの変数は自動的に継承されます。

組み込みの C++ ルールは、「その中でコンパイラを実行する」よりもはるかに高度です。*SAN、ThinLTO、モジュールあり/なしのさまざまなコンパイル モードと、慎重に最適化されたバイナリを、複数のプラットフォームで高速にテストを実行すると同時にサポートするために、内部で生成される可能性のある複数のアクションのそれぞれに正しい入力、出力、コマンドライン フラグが確実に設定されるように、組み込みルールは非常に長い時間をかけて行われています。

これらの変数は、まれに言語の専門家が使用するフォールバック メカニズムです。使用したいとお考えの場合は、まず Bazel デベロッパーにお問い合わせください。

  • ABI: C++ ABI のバージョン。
  • AR: crosstool の「ar」コマンド。
  • C_COMPILER: C/C++ コンパイラ識別子(例: llvm)。
  • CC: C および C++ コンパイラ コマンド。

    常に CC_FLAGSCC と組み合わせて使用することを強くおすすめします。自己責任で実施しないこと。

  • CC_FLAGS: genrules で使用できる C/C++ コンパイラの最小フラグセット。特に、CC が複数のアーキテクチャをサポートしている場合に、正しいアーキテクチャを選択するためのフラグが含まれています。
  • NM: crosstool の「nm」コマンド。
  • OBJCOPY: C/C++ コンパイラと同じスイートの objcopy コマンド。
  • STRIP: C/C++ コンパイラと同じスイートの strip コマンド。

Java ツールチェーン変数

以下は Java ツールチェーン ルールで定義されており、toolchains = ["@bazel_tools//tools/jdk:current_java_runtime"](または同等のホスト ツールチェーンの "@bazel_tools//tools/jdk:current_host_java_runtime")を設定するすべてのルールで使用できます。

JDK のほとんどのツールは直接使用すべきではありません。組み込みの Java ルールは、Java のコンパイルとパッケージ化に対して、インターフェース Jars、ヘッダー インターフェース Jars、高度に最適化された Jar のパッケージ化と統合の実装など、アップストリーム ツールで表現できるよりもはるかに高度なアプローチを使用します。

これらの変数は、まれに言語の専門家が使用するフォールバック メカニズムです。使用したいとお考えの場合は、まず Bazel デベロッパーにお問い合わせください。

  • JAVA: java コマンド(Java 仮想マシン)。可能であれば、代わりに java_binary ルールを使用してください。相対パスを指定できます。java を呼び出す前にディレクトリを変更する必要がある場合は、変更する前に作業ディレクトリをキャプチャする必要があります。
  • JAVABASE: Java ユーティリティを含むベース ディレクトリ。相対パスを指定できます。このディレクトリには「bin」サブディレクトリが含まれます。

Starlark で定義された変数

ルールとツールチェーンの作成者は、TemplateVariableInfo プロバイダを返すことにより、完全なカスタム変数を定義できます。toolchains 属性を使用してこれらに依存しているルールは、それらの値を読み取ります。

Starlark で定義された変数の例をご覧ください。