标签

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。
报告问题 查看源代码

所有目标都只属于一个软件包。目标的名称称为标签。每个标签都唯一标识一个目标。规范形式的典型标签如下所示:

@myrepo//my/app/main:app_binary

标签的第一部分是代码库名称 @myrepo//。通常情况下,如果标签引用的是哪个代码库,则代码库标识符可以缩写为 //。因此,在 @myrepo 中,此标签通常写为

//my/app/main:app_binary

标签的第二部分是非限定软件包名称 my/app/main,这是相对于代码库根目录的软件包路径。代码库名称和非限定软件包名称共同构成完全限定软件包名称 @myrepo//my/app/main。如果标签引用的是其使用的同一软件包,则可以省略软件包名称(还可以选择添加冒号)。因此,在 @myrepo//my/app/main 内,可通过以下任一方式编写此标签:

app_binary
:app_binary

按照惯例,文件会忽略冒号,但规则会保留冒号,但冒号不重要。

冒号后面的标签部分是 app_binary,它是非限定目标名称。当与软件包路径的最后一个组件匹配时,可以省略它和冒号。因此,这两个标签是等效的:

//my/app/lib
//my/app/lib:lib

软件包子目录中的文件目标名称是文件相对于软件包根目录(包含 BUILD 文件的目录)的路径。因此,此文件位于代码库的 my/app/main/testdata 子目录中:

//my/app/main:testdata/input.txt

//my/app@some_repo//my/app 等字符串具有两种含义,具体取决于其使用时的上下文:当 Bazel 需要标签时,它们分别表示 //my/app:app@some_repo//my/app:app。但是,当 Bazel 需要一个软件包时(例如在 package_group 规范中),它们会引用包含该标签的软件包。

BUILD 文件中的常见错误是:使用 //my/app 引用软件包,或引用软件包中的所有目标,但事实并非如此。请注意,它相当于 //my/app:app,因此它会在当前代码库的 my/app 软件包中命名 app 目标。

不过,在指定 package_group.bzl 文件时,建议使用 //my/app 引用软件包,因为它清楚地表明软件包名称是绝对名称,并且位于工作区的顶级目录中。

相对标签不能用于引用其他软件包中的目标;在这种情况下,必须始终指定代码库标识符和软件包名称。例如,如果源代码树同时包含 my/app 软件包和 my/app/testdata 软件包(这两个目录各有自己的 BUILD 文件),则后者包含一个名为 testdepot.zip 的文件。您可以通过以下两种方式(一种错误,一种正确)在 //my/app:BUILD 中引用此文件:

错误 - testdata 是一个不同的软件包,因此您无法使用相对路径

testdata/testdepot.zip

正确 - 引用 testdata 及其完整路径

//my/app/testdata:testdepot.zip

@// 开头的标签是对主代码库的引用,即使从外部代码库访问,这些标签仍然有效。因此,从外部代码库中引用时,@//a/b/c//a/b/c 不同。 前者引用主代码库,而后者在外部代码库中查找 //a/b/c。在主代码库中编写引用主代码库中的目标的规则(从外部代码库中使用)时,尤其要注意这一点。

如需了解引用目标的不同方法,请参阅目标模式

标签的词典规范

标签语法不建议使用对 shell 具有特殊含义的元字符。这有助于避免意外引用问题,并且可让您更轻松地构建操作标签的工具和脚本,例如 Bazel 查询语言

允许使用的目标名称的确切详情如下。

目标名称 - package-name:target-name

target-name 是软件包中目标的名称,规则的名称是 BUILD 文件中规则声明中的 name 属性的值;文件名是其相对于包含 BUILD 文件的目录的路径名。

目标名称必须完全由 a-zA-Z0-9 集合中的字符和标点符号 !%-@^_"#$&'()*-+,;<=>?[]{|}~/. 组成。

文件名必须是普通形式的相对路径名,这意味着它们不得以斜杠开头或结尾(例如,/foofoo/ 禁止使用),也不得包含多个连续斜杠作为路径分隔符(例如 foo//bar)。同样,我们也禁止使用高级引用 (..) 和当前目录引用 (./)。

错误 - 请勿使用“.”引用其他软件包中的文件

正确 - 请使用 `//package-name:filename`

虽然在文件目标的名称中使用 / 的情况很常见,但应避免在规则名称中使用 /。尤其是在使用标签的简写形式时,这可能会让读者感到困惑。标签 //foo/bar/wiz 始终是 //foo/bar/wiz:wiz 的简写形式,即使没有此类软件包 foo/bar/wiz,该标签也绝不会引用 //foo:bar/wiz,即使该目标存在也是如此。

不过,在某些情况下,使用斜杠非常方便,甚至有时是必需的。例如,某些规则的名称必须与其主源文件保持一致,后者可能位于软件包的子目录中。

软件包名称 - //package-name:target-name

软件包的名称是包含相应 BUILD 文件的目录的名称(相对于包含的代码库的顶级目录)。例如:my/app

软件包名称必须完全由从 A-Za-z09、“/”、“-”、“.”、“@”和“_”集中提取的字符组成,并且不能以斜杠开头。

对于目录结构对其模块系统非常重要的语言(例如 Java),请务必选择在该语言中是有效标识符的目录名称。

虽然 Bazel 支持工作区的根软件包(例如 //:foo)中的目标,但最好将该软件包留空,这样所有有意义的软件包都具有描述性名称。

软件包名称不得包含子字符串 //,也不得以斜杠结尾。

规则

规则可指定输入和输出之间的关系,以及构建输出的步骤。规则可以是多种不同种类(有时称为“规则类”)中的一种,该类会生成经过编译的可执行文件和库、测试可执行文件和其他受支持的输出(如构建百科全书中所述)。

BUILD 文件通过调用规则来声明目标。

在下面的示例中,我们可以看到使用 cc_binary 规则的目标 my_app 的声明。

cc_binary(
    name = "my_app",
    srcs = ["my_app.cc"],
    deps = [
        "//absl/base",
        "//absl/strings",
    ],
)

每个规则调用都有一个 name 属性(该属性必须是有效的目标名称),用于声明 BUILD 文件包中的目标。

每条规则都有一组属性;给定规则的适用属性以及每个属性的重要性和语义是相应规则种类的函数;如需查看规则及其对应属性的列表,请参阅构建百科全书每个特性都具有名称和类型。属性的一些常见类型包括整数、标签、标签列表、字符串、字符串列表、输出标签、输出标签列表。并非所有规则都需要指定所有属性。因此,属性构成了从键(名称)到可选输入值字典。

许多规则中存在的 srcs 特性具有“标签列表”类型;其值(如果存在)是一个标签列表,每个标签都是一个规则名称。

在某些情况下,规则种类的名称具有任意性,更吸引人的是规则生成的文件的名称,genrule 也是如此。如需了解详情,请参阅一般规则:genrule

在其他情况下,名称是有意义的:例如,对于 *_binary*_test 规则,规则名称决定了 build 生成的可执行文件的名称。

这种面向目标的有向无环图称为目标图或构建依赖项图,它也是 Bazel 查询工具操作的网域。

目标 构建文件