「Make」変数

「Make」変数は、展開可能な文字列変数の特別なクラスで、「Subject to 'Make variable' substitution」とマークされている属性で使用できます。

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

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

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

使用

「Subject to 'Make variable' substitution」とマークされている属性は、次のように「Make」変数 FOO を参照できます。

my_attr = "prefix $(FOO) suffix"

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

my_attr = "prefix bar suffix"

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

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

my_attr = "prefix $@ suffix"

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

事前定義変数

事前定義の「Make」変数は、どのターゲットでも「Subject to 'Make variable' substitution」とマークされている属性で参照できます。

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

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 に書き込まれます。したがって、実行パスは 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/ で始まり、その後にリポジトリ相対パスが続きます。

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

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

  • location: 展開される属性に応じて、execpath または rootpath の同義語。これは Starlark 以前の従来の動作であり、特定のルールでどのように機能するかを理解している場合を除き、おすすめしません。詳しくは、#2475 をご覧ください。

execpathsrootpathsrlocationpathslocations は、それぞれ execpathrootpathrlocationpathslocation の複数のバリエーションです。複数の出力を生成するラベルがサポートされます。この場合、各出力はスペースで区切ります。ゼロ出力ルールや不適切な形式のラベルがあると、ビルドエラーが発生します。

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

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

カスタム変数

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

ベスト プラクティスとして、すべての変数はカスタムにすることをおすすめします。ただし、これらをコアの Bazel に組み込むべき理由が特にない場合は、カスタム変数を使用することをおすすめします。これにより、コストの高い依存関係を読み込まなくても、taret を使用する変数を気にしない変数を提供する必要がなくなります。

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

以下のコードは C++ ツールチェーン ルールで定義されており、toolchains = ["@bazel_tools//tools/cpp:current_cc_toolchain"](またはホスト ツールチェーンと同等の場合は "@bazel_tools//tools/cpp:current_cc_host_toolchain")を設定するすべてのルールで使用できます。一部のルール(java_binary など)は、ルール定義に暗黙的に C++ ツールチェーンを含みます。これらの変数は自動的に継承されます。

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

これらの変数は、まれに言語エキスパートが使用する代替メカニズムです。使用を希望される場合は、まず Bazel デベロッパーにお問い合わせください。

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

    CC_FLAGS は常に CC と組み合わせて使用することを強くおすすめします。この操作は自己責任で行ってください。

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

Java ツールチェーン変数

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

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

これらの変数は、まれに言語エキスパートが使用する代替メカニズムです。使用を希望される場合は、まず Bazel デベロッパーにお問い合わせください。

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

Starlark 定義の変数

ルールとツールチェーンのライターは、TemplateVariableInfo プロバイダを返すことで完全なカスタム変数を定義できます。toolchains 属性でこれらに依存するルールは、値を読み取ることができます。

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