规则
别名
查看规则来源alias(name, actual, compatible_with, deprecation, features, restricted_to, tags, target_compatible_with, testonly, visibility)
alias
规则会创建规则可以称为的其他名称。
别名仅适用于“常规”目标。特别是 package_group
和 test_suite
无法实现别名。
别名规则有自己的可见性声明。在所有其他方面,它的行为类似于其引用的规则(例如,别名的 testtest 会被忽略;引用的规则的 testonlyness 被使用),但有一些细微的例外情况:
-
如果命令行中提到了其别名,则测试不会运行。如需定义运行所引用的测试的别名,请使用
test_suite
规则,其tests
属性中只有一个目标。 -
定义环境组时,不支持
environment
规则的别名。它们在--target_environment
命令行选项中也不受支持。
示例
filegroup( name = "data", srcs = ["data.txt"], ) alias( name = "other", actual = ":data", )
参数
属性 | |
---|---|
name |
此目标的唯一名称。 |
actual
|
|
config_setting
查看规则来源config_setting(name, constraint_values, define_values, deprecation, distribs, features, flag_values, licenses, tags, testonly, values, visibility)
匹配预期的配置状态(表示为 build 标志或平台限制),以触发可配置的属性。如需了解如何使用此规则,请参阅选择;如需查看一般功能,请参阅 可配置属性。
示例
以下代码可匹配任何设置了 --compilation_mode=opt
或 -c opt
的 build(在命令行中或通过 .bazelrc 文件隐式构建):
config_setting( name = "simple", values = {"compilation_mode": "opt"} )
以下代码会匹配任何以 ARM 为目标平台并应用自定义 FOO=bar
的 build(例如 bazel build --cpu=arm --define FOO=bar ...
):
config_setting( name = "two_conditions", values = { "cpu": "arm", "define": "FOO=bar" } )
以下代码可匹配任何设置了用户定义的标志
--//custom_flags:foo=1
(无论是在命令行中明确设置,还是通过 .bazelrc 文件隐式设置)的 build:
config_setting( name = "my_custom_flag_is_set", flag_values = { "//custom_flags:foo": "1" }, )
下面针对的 build 以 x86_64 架构和 glibc 2.25 版本为目标平台,并假设存在带 //example:glibc_2_25
标签的 constraint_value
。请注意,如果平台定义了以上两个限制条件之外的其他限制条件值,则仍会匹配。
config_setting( name = "64bit_glibc_2_25", constraint_values = [ "@platforms//cpu:x86_64", "//example:glibc_2_25", ] )在上述所有情况下,都可能会在 build 中更改配置,例如,当需要针对与其依赖项不同的平台构建目标时。这意味着,即使
config_setting
与顶级命令行标志不匹配,它也可能会匹配某些 build 目标。
备注
- 如需了解当多个
config_setting
与当前配置状态匹配时会发生的情况,请参阅选择。 - 对于支持简写形式(例如
--compilation_mode
与-c
)的标志,values
定义必须使用完整形式。它们使用任一形式自动匹配调用。 -
如果某个标志接受多个值(例如
--copt=-Da --copt=-Db
或列表类型的 Starlark 标志),则当实际列表中任何位置都存在"a"
时,values = { "flag": "a" }
就会匹配。values = { "myflag": "a,b" }
的工作方式相同:这与--myflag=a --myflag=b
、--myflag=a --myflag=b --myflag=c
、--myflag=a,b
和--myflag=c,b,a
匹配。确切的语义因标志而异。例如,--copt
不支持在同一实例中有多个值:--copt=a,b
会生成["a,b"]
,而--copt=a --copt=b
会生成["a", "b"]
(因此values = { "copt": "a,b" }
会匹配前者,但不匹配后者)。但--ios_multi_cpus
(对于 Apple 规则)确实:-ios_multi_cpus=a,b
和ios_multi_cpus=a --ios_multi_cpus=b
都会生成["a", "b"]
。请检查标志定义并仔细测试您的条件,以验证确切的期望值。 - 如果您需要定义并非由内置构建标志建模的条件,请使用
Starlark 定义的标志。您也可以使用
--define
,但这样可提供的支持会更弱,因此不推荐使用。如需查看更多讨论,请点击此处。 - 避免在不同软件包中重复相同的
config_setting
定义。请改为引用规范软件包中定义的通用config_setting
。 values
、define_values
和constraint_values
可以在同一个config_setting
中任意组合中使用,但必须至少为任一给定的config_setting
设置一个组合。
参数
属性 | |
---|---|
name |
此目标的唯一名称。 |
constraint_values
|
config_setting 而指定的最小 constraint_values 集。(此处未考虑执行平台。)平台拥有的任何其他限制条件值都会被忽略。如需了解详情,请参阅
可配置的 build 属性。
如果两个 |
define_values
|
values 相同,但专门用于 --define 标志。
这意味着: config_setting( name = "a_and_b", values = { "define": "a=1", "define": "b=2", }) 不起作用,因为相同的键 ( config_setting( name = "a_and_b", define_values = { "a": "1", "b": "2", }) 与
|
flag_values
|
values 相同,但适用于
用户定义的 build 标志。
这是一个不同的属性,因为用户定义的标志作为标签进行引用,而内置标志作为任意字符串进行引用。 |
values
|
此规则会继承在 为方便起见,将配置值指定为 build 标志(不含前面的 如果未在命令行中明确设置标志,系统会使用其默认值。
如果某个键在字典中多次出现,则仅使用最后一个实例。
如果某个键引用了可在命令行中多次设置的标志(例如
|
文件组
查看规则来源filegroup(name, srcs, data, compatible_with, deprecation, distribs, features, licenses, output_group, restricted_to, tags, target_compatible_with, testonly, visibility)
使用 filegroup
为目标集合提供一个方便的名称。然后,您可以从其他规则引用这些内容。
建议使用 filegroup
,而不是直接引用目录。
后者不好听,因为构建系统并不全面了解该目录下的所有文件,因此当这些文件发生更改时,它可能无法重新构建。与 glob 结合使用时,filegroup
可以确保构建系统明确知道所有文件。
示例
如需创建由两个源文件组成的 filegroup
,请执行以下操作:
filegroup( name = "mygroup", srcs = [ "a_file.txt", "some/subdirectory/another_file.txt", ], )
或者,使用 glob
来浏览 testdata 目录:
filegroup( name = "exported_testdata", srcs = glob([ "testdata/*.dat", "testdata/logs/**/*.log", ]), )
如需使用这些定义,请使用任意规则中的标签引用 filegroup
:
cc_library( name = "my_library", srcs = ["foo.cc"], data = [ "//my_package:exported_testdata", "//my_package:mygroup", ], )
参数
属性 | |
---|---|
name |
此目标的唯一名称。 |
srcs
|
通常使用 glob 表达式的结果作为 |
data
|
在 |
output_group
|
“输出组”是规则的实现中指定的目标输出工件的类别。 |
genquery
查看规则来源genquery(name, deps, data, compatible_with, deprecation, distribs, exec_compatible_with, exec_properties, expression, features, licenses, opts, restricted_to, scope, strict, tags, target_compatible_with, testonly, visibility)
genquery()
运行使用 Blaze 查询语言指定的查询,并将结果转储到文件中。
为了确保构建一致,只允许查询访问 scope
属性中指定的目标的传递闭合。如果 strict
未指定或为 true,则违反此规则的查询将在执行期间失败(如果 strict
为 false,系统将直接跳过范围外的警告,并发出警告)。若要确保不会发生这种情况,最简单的方法是在作用域内指定与查询表达式相同的标签。
此处允许的查询和命令行之间的唯一区别在于,此处不允许使用包含通配符目标规范(例如 //pkg:*
或 //pkg:all
)的查询。
这样做有两个原因:第一,因为 genquery
必须指定一个作用域来阻止查询的传递闭合范围之外的目标影响其输出;第二,由于 BUILD
文件不支持通配符依赖项(例如,不允许使用 deps=["//a/..."]
)。
系统使用 --order_output=full
对 Genquery 的输出进行排序,以便执行确定性输出。
输出文件的名称是规则的名称。
示例
以下示例将指定目标的传递闭合中的标签列表写入文件。
genquery( name = "kiwi-deps", expression = "deps(//kiwi:kiwi_lib)", scope = ["//kiwi:kiwi_lib"], )
参数
属性 | |
---|---|
name |
此目标的唯一名称。 |
expression
|
a/BUILD 文件中这个属性中的标签 :b 将引用目标 //:b 。
|
opts
|
bazel query 的命令行选项。此处不允许使用某些查询选项:--keep_going 、--query_file 、--universe_scope 、--order_results 和 --order_output 。此处未指定的选项将具有默认值,就像在 bazel query 命令行中一样。
|
scope
|
|
strict
|
|
genrule
查看规则来源genrule(name, srcs, outs, cmd, cmd_bash, cmd_bat, cmd_ps, compatible_with, deprecation, distribs, exec_compatible_with, exec_properties, exec_tools, executable, features, licenses, local, message, output_licenses, output_to_bindir, restricted_to, tags, target_compatible_with, testonly, toolchains, tools, visibility)
genrule
会使用用户定义的 Bash 命令生成一个或多个文件。
Genrule 是通用 build 规则,如果任务没有特定规则,则可以使用这些规则。例如,您可以运行 Bash 单行代码。但是,如果您需要编译 C++ 文件,请遵守现有的 cc_*
规则,因为您已经代您完成所有繁重工作。
请注意,genrule 需要 shell 来解释命令参数。也可以轻松引用 PATH 中可用的任意程序,不过这会使命令非封闭,并且可能无法重现。 如果您只需运行单个工具,请考虑改用 run_binary。
请勿使用 genrule 运行测试。测试和测试结果(包括缓存政策和环境变量)有特殊的分配规定。测试通常需要在构建完成后并在目标架构上运行,而 Genrule 会在构建期间和执行架构上执行(两者可能不同)。如果您需要通用测试规则,请使用 sh_test
。
交叉编译注意事项
如需详细了解交叉编译,请参阅用户手册。
虽然 genrule 在构建期间运行,但其输出通常在构建之后用于部署或测试。考虑为微控制器编译 C 代码的示例:编译器会接受 C 源文件并生成在微控制器上运行的代码。生成的代码显然无法在用于构建它的 CPU 上运行,但 C 编译器(如果从源代码编译)必须这样做。
构建系统使用执行配置来描述运行 build 的机器,使用目标配置来描述应该会运行 build 输出的机器。提供了一些选项供您配置,并将相应的文件隔离到不同的目录中,以避免冲突。
对于 genrule,构建系统可确保正确构建依赖项:为 target 配置构建 srcs
(如有必要),为 exec 配置构建 tools
,输出被视为针对 target 配置。此外,它还提供 genMake 变量可以传递给相应工具的
“Make”变量。
genrule 有意不定义 deps
属性:其他内置规则使用规则之间传递的依赖于语言的元信息自动确定如何处理依赖规则,但这种级别的自动化不适用于 genrule。Genrule 仅在文件和 runfiles 级别发挥作用。
特殊情况
可执行文件执行编译:在某些情况下,构建系统需要运行 genrule,以便也可以在构建期间执行输出。例如,如果某个 genrule 构建了一个自定义编译器,而该编译器稍后又被另一个 genrule 使用,则第一个编译器必须针对执行配置生成其输出,因为这是编译器会在另一个 genrule 中运行。在这种情况下,构建系统会自动执行正确的操作:为执行配置(而不是目标配置)构建第一条 genrule 的 srcs
和 outs
。如需了解详情,请参阅用户手册。
JDK 和 C++ 工具:为了使用 JDK 或 C++ 编译器套件中的工具,构建系统提供了一组要使用的变量。如需了解详情,请参阅“Make”变量。
Genrule 环境
genrule 命令由 Bash shell 执行,该 shell 已配置为使用 set -e -o pipefail
在命令或流水线发生故障时失败。
构建工具在经过清理的进程环境中执行 Bash 命令,该环境仅定义 PATH
、PWD
、TMPDIR
等核心变量。为了确保构建可重现,用户 shell 环境中定义的大多数变量都不会传递给 genrule 的命令。但是,Bazel(而不是 Blaze)会传递用户的 PATH
环境变量的值。
对 PATH
值的任何更改都会导致 Bazel 在下一个 build 中重新执行该命令。
genrule 命令不应访问网络,除非连接到属于其本身子项的进程(尽管目前未强制执行此操作)。
构建系统会自动删除任何现有输出文件,但会在运行 genrule 之前创建任何必要的父目录。如果发生故障,它还会移除所有输出文件。
一般建议
- 确保由基因规则运行的工具具有确定性和封闭性。他们不应将时间戳写入其输出,而应为集和映射使用稳定的排序,也应仅将相对文件路径写入输出,而不应写入绝对路径。如果不遵循此规则,会导致意外的构建行为(Bazel 不会按预期构建重建的 Genrule),并降低缓存性能。
- 请务必广泛使用
$(location)
作为输出、工具和来源。由于为不同的配置隔离输出文件,genrule 不能依赖于硬编码和/或绝对路径。 - 请务必编写一个常见的 Starlark 宏,以防在多个位置使用相同或非常相似的 Genrule。如果 genrule 比较复杂,不妨考虑在脚本中实现或将其作为 Starlark 规则实现。这可以提高可读性和可测试性。
- 请确保退出代码正确指示 Genrule 是成功还是失败。
- 不要将信息性消息写入 stdout 或 stderr。虽然这对于调试很有用,但很容易变为噪音;成功的 Gengen 应该静默。另一方面,如果 Gengen 失败,则应该发出良好的错误消息。
$$
evaluates to a$
, a literal dollar-sign, so in order to invoke a shell command containing dollar-signs such asls $(dirname $x)
, one must escape it thus:ls $$(dirname $$x)
。- 避免创建符号链接和目录。Bazel 不会复制由 genrule 创建的目录/符号链接结构,而且对目录的依赖项检查不合理。
- 在其他规则中引用 genrule 时,您可以使用 genrule 的标签或各个输出文件的标签。有时,一种方法更具可读性,有时另一种方法是:在使用方规则的
srcs
中按名称引用输出,以避免意外选择 genrule 的其他输出,但如果 genrule 生成许多输出,则可能很繁琐。
示例
此示例会生成 foo.h
。没有来源,因为该命令不接受任何输入。由该命令运行的“binary”是与 genrule 位于同一软件包中的 Perl 脚本。
genrule( name = "foo", srcs = [], outs = ["foo.h"], cmd = "./$(location create_foo.pl) > \"$@\"", tools = ["create_foo.pl"], )
以下示例展示了如何使用 filegroup
以及另一个 genrule
的输出。请注意,您也可以使用 $(SRCS)
而不是显式 $(location)
指令;为了便于演示,此示例使用后者。
genrule( name = "concat_all_files", srcs = [ "//some:files", # a filegroup with multiple files in it ==> $(locations) "//other:gen", # a genrule with a single output ==> $(location) ], outs = ["concatenated.txt"], cmd = "cat $(locations //some:files) $(location //other:gen) > $@", )
参数
属性 | |
---|---|
name |
此目标的唯一名称。 您可以在其他 BUILD 规则的 srcs 或 deps 部分中按名称引用此规则。如果规则生成源文件,应使用 srcs 属性。
|
srcs
|
此属性不适合列出由
构建系统可确保在运行 genrule 命令之前构建这些前提条件;这些 build 使用与原始构建请求相同的配置进行构建。这些前提条件的文件的名称以 |
outs
|
输出文件不得跨越软件包边界。 输出文件名将被解释为相对于软件包。
如果设置了
genrule 命令应在预定位置创建每个输出文件。该位置在 |
cmd
|
$(location)
和“Make”变量。
cmd_bash 、cmd_ps 和 cmd_bat 的回退(如果它们都不适用)。
如果命令行长度超过平台限制(在 Linux/macOS 上为 64K,在 Windows 上为 8K),那么 genrule 会将命令写入脚本并执行该脚本以进行解决。这适用于所有 cmd 属性( |
cmd_bash
|
此属性的优先级高于 |
cmd_bat
|
此属性的优先级高于
|
cmd_ps
|
此属性的优先级高于
为了让 Powershell 更易于使用且不易出错,我们在在 genrule 中执行 Powershell 命令之前运行以下命令以设置环境。
|
exec_tools
|
tools 。
在一段时间内, |
executable
|
将此标志设置为 True 表示输出是可执行文件,并且可以使用 不支持为生成的可执行文件声明数据依赖项。 |
local
|
如果设置为 True,此选项会强制使用“本地”策略运行此
这等同于提供“local”作为标记 ( |
message
|
执行此构建步骤时将输出的进度消息。默认情况下,消息为“正在生成输出”(或同样平缓的讯息),但您可以提供更具体的消息。请在 |
output_licenses
|
common attributes
|
output_to_bindir
|
如果设置为 True,此选项会使输出文件写入 |
tools
|
构建系统可确保在运行 genrule 命令之前构建这些前提条件;这些工具是使用 exec 配置构建的,因为这些工具是在构建期间执行的。您可以使用
由 |
test_suite
查看规则来源test_suite(name, compatible_with, deprecation, distribs, features, licenses, restricted_to, tags, target_compatible_with, testonly, tests, visibility)
test_suite
定义了一组对人类“有用”的测试。这样,项目就可以定义多组测试,例如“在签入之前必须运行的测试”、“我们的项目压力测试”或“所有小测试”。blaze test
命令遵循这种组织形式:对于像 blaze test //some/test:suite
这样的调用,Blaze 会先枚举 //some/test:suite
目标以传递方式包含的所有测试目标(我们称之为“test_suite 扩展”),然后 Blaze 会构建并测试这些目标。
示例
一种测试套件,用于运行当前软件包中的所有小测试。
test_suite( name = "small_tests", tags = ["small"], )
运行一组指定测试的测试套件:
test_suite( name = "smoke_tests", tests = [ "system_unittest", "public_api_unittest", ], )
一种测试套件,用于运行当前软件包中的所有不易测试的测试。
test_suite( name = "non_flaky_test", tags = ["-flaky"], )
参数
属性 | |
---|---|
name |
此目标的唯一名称。 |
tags
|
以“-”字符开头的标记将被视为排除标记。前面的“-”字符不会被视为标记的一部分,因此套件标记“-small”与测试的“small”大小匹配。所有其他标记都被认为是肯定标记。 (可选)为了更明确地标记标记,标记还可以以“+”字符开头,这样便不会作为标记文本的一部分进行求值。它只是让正向和负向区分更加清晰易读。 只有与所有正标记且无否定标记匹配的测试规则才会包含在测试套件中。请注意,这并不意味着对被滤除测试的依赖项进行的错误检查会被跳过;跳过的测试的依赖项仍然需要合法(例如,没有因为可见性限制而被阻止)。
在处理涉及通配符目标模式的调用时,
请注意,对于测试,
如果您需要一个 |
tests
|
此处接受任何
如果 |