“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"
如需将 $ 写为字符串字面量(即阻止变量
扩展),请写入 $$.
Predefined variables
Predefined "Make" variables can be referenced by any attribute marked as "Subject to 'Make variable' substitution" on any target.
To see the list of these variables and their values for a given set of build options, run
bazel info --show_make_env [build options]
and look at the top output lines with capital letters.
See an example of predefined variables.
Toolchain option variables
COMPILATION_MODE:fastbuild,dbg, oropt. (more details)
Path variables
-
BINDIR: The base of the generated binary tree for the target architecture.Note that a different tree may be used for programs that run during the build on the host architecture, to support cross-compiling.
If you want to run a tool from within a
genrule, the recommended way to get its path is$(execpath toolname), where toolname must be listed in thegenrule'stoolsattribute. GENDIR: The base of the generated code tree for the target architecture.
Machine architecture variables
-
TARGET_CPU: The target architecture's CPU, e.g.k8.
Predefined genrule variables
The following are specially available to genrule's
cmd attribute and are
generally important for making that attribute work.
See an example of predefined genrule variables.
OUTS: Thegenrule'soutslist. If you have only one output file, you can also use$@.-
SRCS: Thegenrule'ssrcslist (or more precisely: the path names of the files corresponding to labels in thesrcslist). If you have only one source file, you can also use$<. -
<:SRCS, if it is a single file. Else triggers a build error. -
@:OUTS, if it is a single file. Else triggers a build error. -
RULEDIR: The output directory of the target, that is, the directory corresponding to the name of the package containing the target under thegenfilesorbintree. For//my/pkg:my_genrulethis always ends inmy/pkg, even if//my/pkg:my_genrule's outputs are in subdirectories. -
@D: The output directory. If outs has one entry, this expands to the directory containing that file. If it has multiple entries, this expands to the package's root directory in thegenfilestree, even if all output files are in the same subdirectory!Note: Use
RULEDIRover@DbecauseRULEDIRhas simpler semantics and behaves the same way regardless of the number of output files.If the genrule needs to generate temporary intermediate files (perhaps as a result of using some other tool like a compiler), it should attempt to write them to
@D(although/tmpwill also be writable) and remove them before finishing.Especially avoid writing to directories containing inputs. They may be on read-only filesystems. Even if not, doing so would trash the source tree.
Note: If the filenames corresponding to the input labels or the output
filenames contain spaces, ', or other special characters (or your
genrule is part of a Starlark macro which downstream users may invoke on such
files), then $(SRCS) and $(OUTS) are not suitable
for interpolation into a command line, as they do not have the semantics that
"${@}" would in Bash.
One workaround is to convert to a Bash array, with
mapfile SRCS <<< "$$(sed -e 's/ /\\n/g' <<'genrule_srcs_expansion' $(SRC) genrule_srcs_expansion ),然后在后续命令行中使用"$$\{SRCS[@]}"代替$(SRCS)。更稳健的方法是编写 Starlark 规则。预定义源/输出路径变量
预定义变量
execpath、execpaths、rootpath、rootpaths、location和locations采用标签参数(例如$(execpath //foo:bar)),并替换由该标签表示的文件路径。对于源文件,这是相对于工作区根目录的路径。 对于作为规则输出的文件,这是文件的 输出路径 (请参阅下文对 输出文件的说明)。
-
execpath:表示 execroot 下 Bazel 运行构建操作的路径。在上面的示例中,Bazel 在工作区根目录中由
bazel-myproject符号链接链接的目录中运行所有构建操作。源文件empty.source链接到路径bazel-myproject/testapp/empty.source. 因此,其 exec 路径(即根目录下的子路径)为testapp/empty.source。这是构建操作可用于查找文件的路径。输出文件的暂存方式类似,但也会以子路径
bazel-out/cpu-compilation_mode/bin(或对于工具的输出:bazel-out/cpu-opt-exec-hash/bin)为前缀。在上面的示例中,//testapp:app是一个工具,因为它出现在show_app_output的tools属性中。因此,其输出文件app会写入bazel-myproject/bazel-out/cpu-opt-exec-hash/bin/testapp/app. 因此,exec 路径为bazel-out/cpu-opt-exec-hash/bin/testapp/app。借助此额外的前缀 ,您可以在同一构建中为(例如)两个不同的 CPU 构建同一目标,而不会导致结果相互覆盖。传递给此变量的标签必须恰好表示一个文件。对于 表示源文件的标签,这会自动成立。对于表示规则的标签,该规则必须恰好生成一个输出。如果此条件不成立或标签格式不正确,构建会失败并显示错误。
-
rootpath:表示构建的二进制文件在运行时可用于 查找依赖项的路径,相对于其 runfiles 目录的子目录(对应于主代码库)。 注意:这仅在启用--enable_runfiles时有效,而默认情况下 Windows 上未启用此选项。请改用rlocationpath以实现 跨平台支持。这与
execpath类似,但会剥离上述配置 前缀。在上面的示例中,这意味着empty.source和app都使用纯工作区相对 路径:testapp/empty.source和testapp/app。外部代码库
repo中文件的rootpath将以../repo/开头,后跟 代码库相对路径。这与
execpath具有相同的“仅一个输出”要求。 -
rlocationpath:构建的二进制文件可以传递给 runfiles 库的Rlocation函数的路径,以便在运行时查找依赖项,无论是在 runfiles 目录中(如果可用)还是使用 runfiles 清单。这与
rootpath类似,因为它不包含 配置前缀,但不同之处在于它始终以 代码库的名称开头。在上面的示例中,这意味着empty.source和app会生成以下 路径:myproject/testapp/empty.source和myproject/testapp/app。外部代码库
repo中文件的rlocationpath将以repo/开头,后跟代码库相对路径。将此路径传递给二进制文件并使用 runfiles 库将其解析为文件系统路径,是在运行时查找依赖项的首选方法。与
rootpath相比,它的优势在于它适用于所有平台,即使 runfiles 目录不可用也是如此。这与
execpath具有相同的“仅一个输出”要求。 -
location:execpath或rootpath的同义词,具体取决于要扩展的属性。这是 旧版 Starlark 之前的行为,除非您确实知道它对特定规则的作用,否则不建议使用 。如需了解详情,请参阅 #2475 。
execpaths、rootpaths、rlocationpaths、
和 locations 分别是 execpath、
rootpath、rlocationpath 和location、
的复数形式。它们支持生成多个输出的标签,在这种情况下
每个输出都会列出,并以空格分隔。零输出规则和格式错误的
标签会生成构建错误。
所有引用的标签都必须出现在使用目标的 srcs、
输出文件或 deps 中。否则,构建会失败。C++ 目标也可以引用 data 中的标签。
标签不必采用规范形式:foo、:foo
和 //somepkg:foo 都可以。
自定义变量
任何标记为 "受‘Make 变量’替换影响"的属性都可以引用自定义"Make"变量,但仅限于 依赖于 定义这些变量的其他目标的目标。
最佳实践是,除非有充分的理由将所有变量嵌入到核心 Bazel 中,否则所有变量都应该是自定义变量。这样可以避免 Bazel 加载 可能开销高昂的依赖项,以提供使用目标可能 不关心的变量。
C++ 工具链变量
以下变量在 C++ 工具链规则中定义,适用于任何
设置了 toolchains =
["@bazel_tools//tools/cpp:toolchain_type"]
的规则。某些规则(例如 java_binary)会在其规则定义中隐式
包含 C++ 工具链。它们会自动继承这些变量
。
内置 C++ 规则比“对其运行编译器 ”复杂得多。为了支持各种编译模式(例如 *SAN、ThinLTO、 带/不带模块以及经过精心优化的二进制文件),同时在多个平台上快速运行测试,内置规则会尽力确保在每个可能内部生成的多个操作中设置正确的输入、输出和命令行标志。
这些变量是一种后备机制,在 极少数情况下供语言专家使用。如果您想使用这些变量,请先与 Bazel 开发者 联系。
ABI:C++ ABI 版本。-
AR:来自 crosstool 的“ar”命令。 -
C_COMPILER: C/C++ 编译器标识符,例如llvm。 -
CC:C 和 C++ 编译器命令。我们强烈建议始终将
CC_FLAGS与 结合使用CC。否则,您将自行承担风险。 CC_FLAGS:一组最小的标志,供 genrule 使用 C/C++ 编译器。特别是,如果CC支持多种架构,则此变量包含用于选择正确架构的标志。-
DUMPBIN:来自 Microsoft Visual Studio 的 Microsoft COFF 二进制文件转储程序 (dumpbin.exe)。 -
NM:来自 crosstool 的“nm”命令。 -
OBJCOPY:与 C/C++ 编译器来自同一套件的 objcopy 命令。 -
STRIP:与 C/C++ 编译器来自同一套件的 strip 命令。
Java 工具链变量
以下变量在 Java 工具链规则中定义,适用于任何设置了 toolchains =
["@rules_java//toolchains:current_java_runtime"](或 "@rules_java//toolchains:current_host_java_runtime" 对于主机工具链等效项)的规则。
JDK 中的大多数工具都不应直接使用。与上游工具可以表达的内容相比,内置 Java 规则使用更复杂的方法进行 Java 编译和打包 ,例如接口 Jar、标头接口 Jar 以及高度优化的 Jar 打包和合并实现。
这些变量是一种后备机制,在 极少数情况下供语言专家使用。如果您想使用这些变量,请先与 Bazel 开发者 联系。
-
JAVA:“java”命令(Java 虚拟机)。请避免使用此命令,并尽可能改用java_binary规则 。可能是相对路径。如果您必须在调用java之前更改 目录,则需要先捕获 工作目录,然后再更改它。 JAVABASE:包含 Java 实用程序的基准目录。可能是相对路径。它将包含一个 "bin" 子目录。
Starlark 定义的变量
规则和 工具链 编写者可以通过返回
TemplateVariableInfo
提供程序来定义
完全自定义的变量。然后,任何通过
toolchains 属性依赖于这些变量的规则都可以读取其值: