Bazel 查询参考

报告问题 查看来源 每晚 · 7.2。 · 7.1敬上 · 7.0 · 6.5 条 · 6.4

本页面是适用于 Bazel 查询语言的参考手册, (当您使用 bazel query 分析 build 依赖项时)。它还 描述了 bazel query 支持的输出格式。

对于实际用例,请参阅 Bazel 查询操作方法

其他查询参考文档

除了在加载后阶段目标图上运行的 query 之外, Bazel 包含操作图查询可配置的查询

操作图查询

操作图查询 (aquery) 对已配置的分析后数据运行 目标图,并显示有关操作工件和 关系。如果您对aquery 从已配置的目标图表生成的操作/工件的属性。 例如,实际运行的命令及其输入、输出和助记符。

如需了解详情,请参阅 aquery 参考文档

可配置的查询

传统的 Bazel 查询在加载后阶段目标图上运行,并且 因此没有配置的概念及其相关概念。值得注意的是, 它无法正确解析 select 语句 而是返回选择的所有可能分辨率不过, 可配置的查询环境 cquery 可正确处理配置,但 并不提供此原始查询的所有功能。

如需了解详情,请参阅 cquery 参考文档

示例

用户如何使用 bazel query?以下是典型示例:

为什么 //foo 树依赖于 //bar/baz? 显示路径:

somepath(foo/..., //bar/baz:all)

所有 foo 测试都依赖于 C++ 库执行哪些操作 而foo_bin目标则不然?

kind("cc_library", deps(kind(".*test rule", foo/...)) except deps(//foo:foo_bin))

词法单元:词法语法

查询语言中的表达式由以下部分组成 令牌数:

  • 关键字,例如 let。关键字是 下面分别对其进行了介绍整套 为:

  • 字词,例如“foo/...”或“.*test rule”或“//bar/baz:all”。如果 字符序列是“带引号”(以单引号 ' 或 以双引号 " 开头和结尾),表示一个单词。如果字符序列 ,它仍可能被解析为一个字词。不带英文引号的字词是序列 代表字母字符 A-Za-z、数字 0-9、 和特殊字符*/@.-_:$~[](星号、正斜线、at、句点、 连字符、下划线、冒号、美元符号、波浪号、左方括号、右方括号 大括号)。但是,不带英文引号的字词不得以连字符 - 或星号 * 开头 尽管相对 [目标名称][(/concepts/labels#target-names) 这些字符。

    不带英文引号的字词也不得包含加号 + 或等号字符 符号 =,即使目标名称中允许使用这些字符也是如此。时间 编写生成查询表达式的代码时,应给目标名称加引号。

    在编写用于构建 Bazel 查询的脚本时,必须加上引号 由用户提供的值生成的表达式。

     //foo:bar+wiz    # WRONG: scanned as //foo:bar + wiz.
     //foo:bar=wiz    # WRONG: scanned as //foo:bar = wiz.
     "//foo:bar+wiz"  # OK.
     "//foo:bar=wiz"  # OK.
    

    请注意,此引用是对发布商可能要求的任何引用的补充。 例如:

    bazel query ' "//foo:bar=wiz" '   # single-quotes for shell, double-quotes for Bazel.
    

    使用引号时,系统会将关键字视为普通字词。例如,some 是 关键字,但包含“部分”是一个单词。foo 和“foo”都是单词。

    不过,在目标名称中使用单引号或双引号时要小心。时间 引用一个或多个目标名称时,请仅使用一种引号(即所有 单引号或全双引号)。

    以下是 Java 查询字符串的示例:

      'a"'a'         # WRONG: Error message: unclosed quotation.
      "a'"a"         # WRONG: Error message: unclosed quotation.
      '"a" + 'a''    # WRONG: Error message: unexpected token 'a' after query expression '"a" + '
      "'a' + "a""    # WRONG: Error message: unexpected token 'a' after query expression ''a' + '
      "a'a"          # OK.
      'a"a'          # OK.
      '"a" + "a"'    # OK
      "'a' + 'a'"    # OK
    

    我们之所以选择此语法,是为了让大多数情况下都不需要引号。通过 (不同寻常)".*test rule" 示例需要引号:以英文句点开头, 包含空格。引用 "cc_library" 没有必要,但无害。

  • 标点,如圆括号 ()、句点 . 和逗号 ,。字词 包含标点符号(上文列出的例外情况除外)时必须加引号。

引号内的字词外的空格字符会被忽略。

Bazel 查询语言概念

Bazel 查询语言是一种表达式语言。每个 表达式的计算结果为一组部分排序的目标, 即目标的图 (DAG)。这是唯一一个 数据类型。

集和图指的是同一数据类型,但要强调不同 例如:

  • 设置:不需要注意目标的部分顺序。
  • 图表:目标的部分顺序很重要。

依赖关系图中的循环

build 依赖关系图应该是无环的。

查询语言使用的算法适用于 无环图,但能够可靠地适应循环。关于如何 未指定任何周期,因此不应予以依赖。

隐式依赖项

除了在 BUILD 文件中明确定义的 build 依赖项之外, Bazel 会向规则添加其他隐式依赖项。例如 每个 Java 规则都隐式依赖于 JavaBuilder。隐式依赖项 使用以 $ 开头的属性确定, 无法在BUILD文件中替换。

默认情况下,bazel query 会考虑隐式依赖项 。可通过 --[no]implicit_deps 选项。请注意,由于查询不会考虑 配置,则绝不会考虑可能的工具链。

可靠性

对 build 运行 Bazel 查询语言表达式 依赖关系图,即由 所有 BUILD 文件中的规则声明。您有必要了解 这张图表有点抽象, 有关如何执行构建的所有步骤的完整说明。在 为了执行构建,也需要进行配置; 请参阅配置 部分。

使用 Bazel 查询语言评估表达式的结果 “true”,这意味着 一种保守的过度估计,并非精确的。如果您 使用查询工具计算需要的所有源文件 可能会报告超出实际需要的数量 例如,查询工具将包含所有文件 需要支持邮件翻译,即使您不打算 以便在构建中使用该功能

关于保留图表顺序

操作保留所有排序 子表达式继承的限制条件。您可以把 “部分秩序守恒定律”。考虑采用一种 例如:如果发出查询以确定 特定目标的依赖项,生成的集将按顺序 根据依赖关系图进行绘制。如果您过滤出设置为 仅包含 file 种类的目标, 传递部分排序关系 与在生成的子集中的目标对准,即使其中没有任何一个 实际上,这些对在原始图中是直接关联的。 (构建依赖关系图中没有文件-文件边缘)。

不过,虽然所有运算符都保留顺序,但有些运算符 运算,例如 set 运算引入任何自己的排序限制。 请参考以下表达式:

deps(x) union y

最终结果集的顺序一定会保留所有 其子表达式的排序约束条件,也就是说, x 的传递依赖项使用 相互尊重。不过,查询并不保证 y 中目标的顺序,也不考虑 deps(x)中各定位条件相对于 y(不包括位于 y 也位于 deps(x) 中)。

引入排序约束的运算符包括: allpathsdepsrdepssomepath 和目标模式通配符 package:*dir/...

Sky 查询

星空查询是一种对指定的宇宙范围执行的查询模式。

仅适用于 SkyQuery 的特殊函数

Sky Query 模式提供额外的查询函数 allrdepsrbuildfiles。这些函数在整个 全局范围(这就是它们对普通查询没有意义的原因)。

指定 Universe 范围

通过传递以下两个标志可启用 Sky Query 模式: (--universe_scope--infer_universe_scope)和 --order_output=no--universe_scope=<target_pattern1>,...,<target_patternN> 会告知查询 预加载目标模式指定的目标模式的传递闭包, 可加可减。然后,系统会在此“范围”中评估所有查询。具体来说, allrdepsrbuildfiles 运算符仅返回此范围的结果。 --infer_universe_scope 告知 Bazel 推断 --universe_scope 的值 。此推断值是 但这可能不是您想要的结果。例如:

bazel query --infer_universe_scope --order_output=no "allrdeps(//my:target)"

此查询表达式中的唯一目标模式列表为 ["//my:target"],因此 Bazel 会以相同的方式处理调用:

bazel query --universe_scope=//my:target --order_output=no "allrdeps(//my:target)"

但使用 --universe_scope 的查询结果只有 //my:target//my:target的反向依赖项在宇宙中都不存在, 施工!另一方面,请考虑:

bazel query --infer_universe_scope --order_output=no "tests(//a/... + b/...) intersect allrdeps(siblings(rbuildfiles(my/starlark/file.bzl)))"

这是一个有意义的查询调用,旨在计算 tests 扩展了某些 传递依赖于其定义使用某个 .bzl 文件的目标。在这里, --infer_universe_scope 非常方便,尤其是在 否则,--universe_scope 会要求您自行解析查询表达式。

因此,对于使用宇宙范围运算符(如 allrdepsrbuildfiles,请务必使用 仅当其行为符合您的预期时,才使用 --infer_universe_scope

与默认查询相比,Sky Query 有一些优点和缺点。主要 其缺点是无法根据图表顺序对输出进行排序, 不允许使用输出格式。它的优点是 两个运算符(allrdepsrbuildfiles)。 此外,Sky Query 通过内省 Skyframe 图表上,而不是创建新的 这是默认实现所具有的功能因此,在某些情况下 运行速度更快且占用的内存更少

表达式:语法和语义

以下是 Bazel 查询语言的语法,以 EBNF 表示法表示:

expr ::= word
       | let name = expr in expr
       | (expr)
       | expr intersect expr
       | expr ^ expr
       | expr union expr
       | expr + expr
       | expr except expr
       | expr - expr
       | set(word *)
       | word '(' int | word | expr ... ')'

以下部分按顺序描述了此语法的各个产生式。

目标模式

expr ::= word

从语法上讲,“目标模式”只是一个词。它被解释为 (无序)目标集。最简单的目标模式是标签, 用于标识单个目标(文件或规则)。例如,目标模式 //foo:bar 求得的是一个集,其中包含一个元素(目标 bar) 规则。

目标模式会泛化标签,以在软件包和 目标。例如,foo/...:all(或仅仅是 foo/...)就是目标模式 该方法以递归方式求得的计算结果为包含每个软件包中所有规则的集合 (位于 foo 目录下);bar/baz:all 是用于评估 一个集合,其中包含 bar/baz 软件包中的所有规则,但不包含其 子软件包。

同样,foo/...:* 是一种目标模式,其求值结果为包含 每个软件包中的所有目标(规则和文件)都以递归方式在 foo 目录;bar/baz:* 的求值结果是一个集合,其中包含 bar/baz 软件包,而不是其子软件包。

由于 :* 通配符与文件和规则匹配,因此通常比 比 :all 更适用于查询。反之,:all 通配符( 目标模式(例如 foo/...)通常对 build 更有用。

bazel query 目标模式的运作方式与 bazel build 构建目标相同。 如需了解详情,请参阅目标模式,或 类型 bazel help target-syntax

目标模式的评估结果可能是单例集(如果是标签), 该集合包含许多元素(例如 foo/...,它有数千个元素 元素)或空集(如果目标模式与任何目标都不匹配)。

目标模式表达式的结果中的所有节点都会正确排序 相互之间的依赖关系。因此, foo:* 不仅是软件包 foo 中的目标集,还是 图表。(无法保证相对顺序 结果节点相对于其他节点的结果。)有关详情,请参阅 图顺序部分。

变量

expr ::= let name = expr1 in expr2
       | $name

Bazel 查询语言允许定义和引用 变量。let 表达式的计算结果与 expr2 的结果,所有免费出现次数 已将变量name替换为 expr1.

例如,let v = foo/... in allpaths($v, //common) intersect $v 是 等同于 allpaths(foo/...,//common) intersect foo/...

变量引用 name 出现,不包括 封闭的 let name = ... 表达式是 错误。换言之,顶级查询表达式不能包含 变量。

在上面的语法产生式中,name 与“word”类似,但带有 附加约束条件:在 C 编程中,它必须是合法标识符 语言。对变量的引用必须在前面加上“$”字符。

每个 let 表达式仅定义一个变量,但您可以嵌套它们。

目标模式和变量引用都包含 单个词元、一个单词,就造成了语法歧义。不过 因为合法变量字词的子集 字词与作为合法目标模式的字词子集没有交集。

从技术上讲,let 表达式不会增加 查询语言的表现力: 即使不使用这些词汇,也能表达其语言。不过, 可以提高许多查询的简洁性,还可能导致 高效地查询评估。

带圆括号的表达式

expr ::= (expr)

圆括号通过关联子表达式来强制限定计算顺序。 带圆括号的表达式的计算结果为其实参的值。

代数集运算:交集、并集、集差

expr ::= expr intersect expr
       | expr ^ expr
       | expr union expr
       | expr + expr
       | expr except expr
       | expr - expr

这三个运算符会根据其参数计算常见的集合运算。 每个运算符都有两种形式:标称形式(例如 intersect)和 符号形式,例如 ^。这两种形式是等效的;这些符号形式 因此您可以加快输入速度(为清楚起见,本页的其余部分均使用标称形式。)

例如,

foo/... except foo/bar/...

计算结果为与 foo/... 匹配但与 foo/bar/... 不匹配的目标集。

您可以编写与以下内容相同的查询:

foo/... - foo/bar/...

intersect (^) 和 union (+) 操作是交换(对称)操作; except (-) 是不对称的。解析器将所有三个运算符都视为 左关联和相同优先级,因此您可能需要使用括号。对于 例如,这些表达式的前两个是等效的,但第三个不是:

x intersect y union z
(x intersect y) union z
x intersect (y union z)

从外部来源读取目标:set

expr ::= set(word *)

set(a b c ...) 运算符计算一组零或多个零值或多个值的并集, 目标格式,用空格分隔(无逗号)。

与 Bourne shell 的 $(...) 功能结合使用,set() 提供了一个 一种将一个查询的结果保存在常规文本文件中的方法,通过 使用其他程序(如标准 UNIX shell 工具)将该文本文件 将结果作为值返回查询工具 处理。例如:

bazel query deps(//my:target) --output=label | grep ... | sed ... | awk ... > foo
bazel query "kind(cc_binary, set($(<foo)))"

在下一个示例中,kind(cc_library, deps(//some_dir/foo:main, 5)) 是 通过使用 awk 程序对 maxrank 值进行过滤计算得出。

bazel query 'deps(//some_dir/foo:main)' --output maxrank | awk '($1 < 5) { print $2;} ' > foo
bazel query "kind(cc_library, set($(<foo)))"

在这些示例中,$(<foo)$(cat foo) 的简写形式,但 shell cat 以外的命令,例如之前的 awk 命令。

函数

expr ::= word '(' int | word | expr ... ')'

查询语言定义了几个函数。函数的名称 确定需要的参数数量和类型。以下 函数:

依赖项的传递性闭包:deps

expr ::= deps(expr)
       | deps(expr, depth)

deps(x) 运算符根据所形成的图求值 由其参数集的依赖项的传递闭包决定 x。例如,deps(//foo) 的值为 根位于单个节点 foo 的依赖关系图,包括其 依赖项deps(foo/...) 的值是依存关系图,其根 是 foo 目录下每个软件包中的所有规则。在这种情况下 “依赖项”表示仅规则和文件目标,因此 BUILD 和 此处未包含创建这些目标所需的 Starlark 文件。为此 您应使用 buildfiles 运算符。

生成的图根据依赖关系进行排序。有关 如需了解详情,请参阅图表顺序部分。

deps 运算符接受可选的第二个参数,该参数是一个整数 指定搜索深度上限的字面量。因此 deps(foo:*, 0) 会返回 foo 软件包中的所有目标,而 deps(foo:*, 1) 进一步包含任何目标在 foo 软件包,deps(foo:*, 2) 进一步包含节点 可从 deps(foo:*, 1) 中的节点访问,依此类推。(这些数字 对应于 minrank 输出格式中显示的排名。) 如果省略 depth 参数,则搜索 无界限:计算先决条件的自反传递闭合。

反向依赖项的传递闭包:rdeps

expr ::= rdeps(expr, expr)
       | rdeps(expr, expr, depth)

rdeps(u, x) 运算符求值为参数集的反向依赖关系 宇宙集内传递闭合中的 x u

生成的图根据依赖关系进行排序。请参阅 部分(请参阅图表顺序)。

rdeps 运算符接受可选的第三个参数,该参数是一个整数 指定搜索深度上限的字面量。生成的 图表仅包含距离 节点。因此,rdeps(//foo, //common, 1) 会计算所有节点 直接依赖于 //common//foo 的传递闭包中。(这些 数字对应于 minrank 输出中显示的排名 format.)如果省略 depth 参数, 搜索是无界限的

所有反向依赖项的传递性闭包:allrdeps

expr ::= allrdeps(expr)
       | allrdeps(expr, depth)

allrdeps 运算符的行为类似于 rdeps 运算符,但“universe set”为任意 --universe_scope 标志 求值,而不是单独指定。因此,如果 通过了 --universe_scope=//foo/...,之后又通过了 allrdeps(//bar) 相当于 rdeps(//foo/..., //bar)

同一软件包中的直接反向依赖项:same_pkg_direct_rdeps

expr ::= same_pkg_direct_rdeps(expr)

same_pkg_direct_rdeps(x) 运算符针对全部目标求值 与参数集中的目标位于同一软件包中,并且直接依赖于它。

处理目标的软件包:同级

expr ::= siblings(expr)

siblings(x)运算符评估的是 与参数集中的目标相同的软件包。

任意选择:部分

expr ::= some(expr)
       | some(expr, count )

some(x, k) 运算符 从其所含数据中随机选择至多 k 个目标 参数集“x”,其求值结果包含 这些定位条件参数 k 是可选的;如果 则结果将是仅包含一个目标的单例集 任意选择。如果参数集 x 的大小为 小于 k,则整个参数集 系统将返回 x

例如,表达式 some(//foo:main union //bar:baz) 的求值结果为 包含 //foo:main//bar:baz 的单例集。 有一个未定义表达式 some(//foo:main union //bar:baz, 2)some(//foo:main union //bar:baz, 3) 同时返回 //foo:main//bar:baz

如果实参是单例,则 some 计算恒等式函数:some(//foo:main) 为 相当于 //foo:main

如果指定的参数集为空,则会发生错误,如 表达式 some(//foo:main intersect //bar:baz)

路径运算符:somepath、allpath

expr ::= somepath(expr, expr)
       | allpaths(expr, expr)

somepath(S, E)allpaths(S, E) 个运算符计算 两组目标之间的路径。两个查询都接受 参数、起点的 SE 的终点。somepath 会返回 从某个目标的某个任意路径上的节点图 SE 中的目标;allpaths 返回来自任意目标的所有路径上的节点图 将S更改为E中的任何目标。

生成的图表将根据依赖关系进行排序。 如需了解详情,请参阅图表顺序部分。

<ph type="x-smartling-placeholder">
</ph> 索道
somepath(S1 + S2, E),一种可能的结果。
<ph type="x-smartling-placeholder">
</ph> 索道
somepath(S1 + S2, E),另一种可能的结果。
所有路径
allpaths(S1 + S2, E)

目标种类过滤:kind

expr ::= kind(word, expr)

kind(pattern, input) 运算符将过滤条件应用到一组目标,并舍弃这些目标 不属于预期类型pattern 参数指定要匹配的目标类型。

例如,BUILD 文件定义的四个目标的种类 如下表所示(对于软件包 p):

代码 目标 种类
        genrule(
            name = "a",
            srcs = ["a.in"],
            outs = ["a.out"],
            cmd = "...",
        )
      
//p:a Genrule 规则
//p:a.in 源文件
//p:a.out 生成的文件
//p:BUILD 源文件

因此,kind("cc_.* rule", foo/...) 的求值结果为: (共 cc_librarycc_binary 等), fookind("source file", deps(//foo)) 下的规则目标 求值为传递闭包中所有源文件的集合 //foo 目标的依赖项。

通常需要为 pattern 参数添加引号 因为如果没有它,解析器就不会将许多正则表达式(例如 source file.*_test)视为字词。

当与 package group 匹配时,以 :all 可能不会产生任何结果。请改用 :all-targets

目标名称过滤:过滤条件

expr ::= filter(word, expr)

filter(pattern, input) 运算符将过滤条件应用于一组目标,并舍弃 标签(绝对形式)与模式不匹配;它 求出其输入的子集。

第一个参数 pattern 是包含 对目标名称进行正则表达式处理。filter 表达式 求值结果为包含所有目标的集合 (x), x 是集合 input 的成员,并且 标签(绝对形式,例如 //foo:bar) 的 x 包含(非锚定)匹配项 为正则表达式 pattern 指定的值。由于所有 目标名称以 // 开头,可以作为替代名称, 添加到 ^ 正则表达式锚中。

这个运算符通常会比 intersect 运算符。例如,要查看 //foo:foo 目标的 bar 依赖项,可以 评估

deps(//foo) intersect //bar/...

不过,此语句将需要解析所有 BUILD 文件, bar树,这样的树将运行缓慢且容易出错 不相关的 BUILD 文件。另一种方法是:

filter(//bar, deps(//foo))

该函数会先计算一组 //foo 依赖项, 则仅过滤与提供的模式匹配的目标 字词,名称中包含 //bar 作为子字符串的目标。

filter(pattern, expr) 运算符的另一个常见用途是按文件中的 名称或扩展名。例如,

filter("\.cc$", deps(//foo))

将提供用于构建 //foo 的所有 .cc 文件的列表。

规则属性过滤:属性

expr ::= attr(word, word, expr)

通过 attr(name, pattern, input) 运算符将过滤条件应用于一组目标,并舍弃 规则、没有属性 name 的规则目标 定义的规则目标,其中属性值与提供的 正则表达式 pattern;它会评估 一部分。

第一个参数 name 是规则的名称 属性,应与所提供的 正则表达式格式。第二个参数 pattern 是属性上的正则表达式 值。attr 表达式的求值结果为包含所有目标的集合 x,使 x 成为 集 input 的成员后,该规则是具有 属性 name,且属性值包含 正则表达式的(非锚定)匹配 pattern。如果 name 是 可选属性和规则未明确指定,则默认指定 属性值进行比较。例如,

attr(linkshared, 0, deps(//foo))

将选择所有 //foo 个可以 链接共享属性(例如 cc_binary 规则),并将其设置为 明确设置为 0 或根本不设置,但默认值为 0(例如 cc_binary 规则)。

列表类型的属性(如 srcsdata 等)为 转换为 [value<sub>1</sub>, ..., value<sub>n</sub>] 形式的字符串, 以中括号 [ 开头,以 ] 中括号结尾 并使用“,”(逗号、空格)分隔多个值。 标签通过使用 标签。例如,属性 deps=[":foo", "//otherpkg:bar", "wiz"] 会转换为 字符串 [//thispkg:foo, //otherpkg:bar, //thispkg:wiz]。 方括号始终存在,因此空列表将使用字符串值 [] 以便进行匹配例如,

attr("srcs", "\[\]", deps(//foo))

将从 //foo 个符合以下条件的依赖项中选择所有规则 srcs 属性为空,而

attr("data", ".{3,}", deps(//foo))

将从 //foo 个依赖项中选择指定 data 属性中至少包含一个值(每个标签至少 由于 //: 的原因,长度为 3 个字符)。

如需选择 //foo 依赖项中具有特定 value 的所有规则,请执行以下操作: list-type 属性,使用

attr("tags", "[\[ ]value[,\]]", deps(//foo))

这样做之所以行得通,是因为 value 前面的字符是 [ 或空格,并且 value 后面的字符将是英文逗号或 ]

规则公开范围过滤:可见

expr ::= visible(expr, expr)

visible(predicate, input) 运算符 将过滤条件应用于一组目标,并舍弃 所需的可见性。

第一个参数 predicate 是一组目标,所有目标 输出中的文件必须对所有人可见。visible 表达式 求得的值为包含所有目标的集合 x,则 x 属于集合 input,并且对于所有目标 yy可以看到predicatex。例如:

visible(//foo, //bar:*)

将选择软件包 //bar//foo的所有目标 可以依赖的硬件或设备,而不违反可见性限制。

评估标签类型的规则属性:标签

expr ::= labels(word, expr)

labels(attr_name, inputs) 运算符返回指定的一组目标, 类型为“label”的属性 attr_name或“标签列表”在 集“inputs”中的某一条规则。

例如,labels(srcs, //foo) 会返回 目标出现在以下对象的 srcs 属性中: //foo 规则。如果有多条规则 使用 inputs 集中的 srcs 属性, 其 srcs 的并集。

展开并过滤 test_suites:测试

expr ::= tests(expr)

tests(x) 运算符返回所有测试的集合 规则集 x 中的规则,将任何 test_suite 规则扩展为 它们引用的一组测试,并按 tagsize

默认情况下,查询评估 忽略所有 test_suite 规则中的任何非测试目标。可以是 --strict_test_suite 选项已更改为错误。

例如,查询 kind(test, foo:*) 会列出所有 *_testtest_suite 规则 (位于 foo 软件包中)。所有结果均为 定义)是 foo 软件包的成员。相比之下, 查询 tests(foo:*) 将返回所有 将由 bazel test foo:* 执行的各个测试:这可能包括属于其他软件包的测试, 直接或间接引用的 通过 test_suite 规则。

软件包定义文件:buildfile

expr ::= buildfiles(expr)

buildfiles(x) 运算符返回集 定义每个目标软件包的 设置 x;也就是说,对于每个软件包,都是其 BUILD 文件, 及其通过 load 引用的任何 .bzl 文件。请注意, 还会返回包含这些项的软件包的 BUILD 文件 load 个文件。

该运算符通常用于确定 需要软件包才能构建指定目标,这通常与 --output package 选项)。例如,

bazel query 'buildfiles(deps(//foo))' --output package

返回 //foo 以传递方式依赖的所有软件包的集合。

软件包定义文件:rbuildfiles

expr ::= rbuildfiles(word, ...)

rbuildfiles 运算符接受以英文逗号分隔的路径片段列表,并返回 以传递方式依赖于这些路径 fragment 的 BUILD 文件集。例如,如果 //foo 是一个软件包,则 rbuildfiles(foo/BUILD) 将返回 //foo:BUILD 目标。如果 foo/BUILD 文件包含 load('//bar:file.bzl'...,则 rbuildfiles(bar/file.bzl) 会 会返回 //foo:BUILD 目标以及BUILD 加载 //bar:file.bzl

rbuildfilesrbuildfiles 运算符的范围是由 --universe_scope 标志。与 BUILD 文件和 .bzl 不直接对应的文件 文件不会影响结果。例如,源文件(如 foo.cc)会被忽略, 即使 BUILD 文件中明确提及,也是如此。不过系统支持符号链接 如果 foo/BUILDbar/BUILD 的符号链接,则 rbuildfiles(bar/BUILD) 的结果中将包含 //foo:BUILD

在道德上,rbuildfiles 运算符几乎与 buildfiles 运算符。然而,这种道德反转 更强地在单向传递:rbuildfiles 的输出就像 buildfiles 的输入;前者在软件包中仅包含 BUILD 文件目标, 而后者可能包含此类目标。反之,对应关系则更弱。通过 buildfiles 运算符的输出是与所有软件包和 相对应的目标。bzl 输出所需的文件数。不过,rbuildfiles 运算符的输入为 而不是这些目标,而是与这些目标对应的路径片段。

软件包定义文件:loadfiles

expr ::= loadfiles(expr)

loadfiles(x) 运算符返回 加载每个目标的软件包所需的 Starlark 文件 设置x。换言之,对于每个软件包,它都会返回 从 BUILD 文件引用的 .bzl 文件。

输出格式

bazel query 会生成图表。 您需要指定内容、格式和 bazel query 会显示此图表 通过 --output 命令行选项指定。

使用 Sky Query 运行时,只有 允许无序输出。具体而言,graphminrank 和 禁止使用 maxrank 输出格式。

某些输出格式接受其他选项。名称 每个输出选项都以其 适用,因此 --graph:factored 仅适用于 当使用 --output=graph 时;调用此命令不会产生任何影响 使用 graph 以外的输出格式。同样, 仅当 --output=xml 时,--xml:line_numbers 才适用 。

关于结果的排序

尽管查询表达式始终遵循 图形顺序的守恒”来呈现结果, 进行有序管理。这不会 影响结果集中的目标或查询的计算方式。它只会 会影响将结果输出到 stdout 的方式。此外, 依赖项顺序的等效项不一定会按字母顺序排序。 --order_output 标志可用于控制此行为。 (--[no]order_results 标志具有 属于 --order_output 标志的一部分,并且已被弃用。)

此标志的默认值为 auto,按字典顺序输出结果 订单。不过,使用 somepath(a,b) 时,结果将以 deps订单。

当此标志为 no--output 为以下之一时 buildlabellabel_kindlocationpackageprotoxml,则输出将按任意顺序输出。这是 通常是最快的选择。但当 --outputgraphminrankmaxrank:采用这些格式时,Bazel 始终会输出结果 按依赖关系顺序或排名排序。

当此标志为 deps 时,Bazel 会输出某种拓扑顺序,即 依赖项但是,按照依赖关系顺序排列的节点 (因为两者之间不存在路径)可以按任意顺序输出。

当此标志为 full 时,Bazel 会按完全确定性(总数)顺序输出节点。 首先,所有节点均按字母顺序排序。然后,列表中的每个节点都将用作 后序深度优先搜索,其中遍历到未访问节点的传出边 子节点的字母顺序。最后,以相反的顺序输出节点 访问它们的位置。

按此顺序输出节点的速度可能会较慢,因此仅当 非常重要。

输出目标在 build 中显示的源代码形式

--output build

使用此选项时,每个目标的表示形式 以 BUILD 语言手写的。所有变量和函数调用 (如 glob、宏)展开,这有助于您查看 各种 Starlark 宏。此外,每条有效规则都会报告 generator_name 和/或 generator_function)值, 指定用于生成有效规则的宏的名称。

虽然输出使用的语法与 BUILD 文件相同,但并不是 保证生成有效的 BUILD 文件。

--output label

如果使用此选项,则每个定位条件的一组名称(或标签) 会输出结果图中的标签,每行一个标签, 拓扑顺序(除非指定了 --noorder_results,请参阅 关于结果排序的注意事项)。 (拓扑排序是指 该节点早于其所有后继节点。)当然有 是图的许多可能的拓扑顺序( postorder 只是一个);并未指定具体选择哪项

输出 somepath 查询的输出时,顺序 节点的打印顺序取决于路径的顺序。

注意:在某些极端情况下,可能会存在两个不同的目标,它们分别是 标签相同;例如,sh_binary 规则及其 可以同时调用唯一的(隐式)srcs 文件 foo.sh。如果查询结果同时包含 这些目标,输出(label 格式)将显示为 包含重复项。使用 label_kind 时(请参阅 格式,那么区别就很明显了:两个定位标准 具有相同的名称,但其中一个具有种类 sh_binary rule 和 其他种类 source file

--output label_kind

label 一样,此输出格式会输出 结果图中的每个目标均按拓扑顺序排列, 此外,还在标签前面附加了目标的种类

--output minrank --output maxrank

labelminrank一样 maxrank 输出格式会输出每个 目标,而不是出现在 它们会按秩序显示,其前面为 。它们不受结果排序的影响 --[no]order_results 标记(请参阅关于以下内容的说明: 结果的顺序)。

此格式有两种变体:minrank 排名 根节点到它的最短路径长度计算每个节点。 “根”节点(没有传入边)的等级为 0, 其后继位次序为 1,依此类推(与往常一样,边缘从 目标:它所依赖的目标。)

maxrank 按节点上最长的距离对每个节点进行排名 从根节点到该节点的路径。同样,“根”其他字词的顺序 一个节点的排名大于所有节点的 其前身。

一个周期中的所有节点都被认为具有相同的排名。(大多数图表 无环的,但会出现循环 只是因为 BUILD 文件包含错误循环。)

这些输出格式有助于探索图的深度。 如果用于 deps(x)rdeps(x) 的结果, 或 allpaths 查询,则排名数字等于 最短(包含 minrank)或最长的长度 (包含 maxrank)从 x 到以下路径中的节点的路径: 排名。maxrank 可用于确定 构建目标所需的最长构建步骤序列。

例如,左侧图表生成右侧输出 当--output minrank--output maxrank时 。

名列前茅
      minrank

      0 //c:c
      1 //b:b
      1 //a:a
      2 //b:b.cc
      2 //a:a.cc
      
      maxrank

      0 //c:c
      1 //b:b
      2 //a:a
      2 //b:b.cc
      3 //a:a.cc
      
--output location

label_kind 一样,此选项会针对每个 即目标的种类和标签,但它是 前缀是一个描述该目标位置的字符串,如 文件名和行号。格式类似于 grep。因此,可以解析后者的工具(如 Emacs) 也可以使用查询输出逐步浏览一系列 匹配,可以将 Bazel 查询工具用作 依赖项图感知型“适用于 BUILD 文件的 grep 命令”。

位置信息因目标种类而异(请参阅 kind 运算符)。对于规则, 系统会输出规则声明在 BUILD 文件中的位置。 对于源文件,实际文件第 1 行的位置是 。对于生成的文件,需要指定规则的位置 输出结果(查询工具不足 找到所生成文件的实际位置,以及 在任何情况下,如果尚未执行构建,该目录可能不存在。)

--output package

此选项会输出 结果集中某个目标。名称会分别输出为 字典顺序;重复。正式地说, 是一个投影从一组标签(软件包、目标)到 软件包

外部代码库中的软件包格式为 @repo//foo/bar,而主代码库中的软件包 格式为 foo/bar

结合 deps(...) 查询时,此输出 此选项可用于查找必须选中的 从而构建一组给定的目标。

显示结果的图表

--output graph

此选项会按照 热门 AT&T GraphViz 格式的图表。通常, 结果会保存到一个文件中,例如 .png.svg。 (如果您的工作站上未安装 dot 程序, 可以使用 sudo apt-get install graphviz 命令进行安装。) 如需查看示例调用,请参阅下面的示例部分。

这种输出格式对 allpaths 特别有用, depsrdeps 查询,其中结果 包含一组路径,当 以线性形式渲染,例如使用 --output label

默认情况下,图表以因式分解形式渲染。也就是说, 拓扑上等效的节点合并为 包含多个标签的节点。这会使图表更紧凑 因为典型的结果图包含高度 重复的模式。例如,java_library 规则 可能依赖于数百个 Java 源文件,所有这些文件都由 相同的 genrule;在因式分解图中,所有这些文件 都由单个节点表示此行为可能会被停用 使用 --nograph:factored 选项。

--graph:node_limit n

此选项用于指定 输出的图表节点。较长的标签将被截断;-1 停用截断。由于图表采用的因式分解形式 节点标签可能会很长。GraphViz 无法 处理超过 1024 个字符(默认值)的标签 部分。除非 --output=graph正在使用中。

--[no]graph:factored

默认情况下,图表以因式分解形式显示,具体如下所述 上方。 当指定 --nograph:factored 时,图表会 输出结果。这使得使用 GraphViz 不切实际,但更简单的格式 例如 grep 命令。此选项无效 除非使用 --output=graph

XML

--output xml

此选项会导致以 XML 格式输出生成的目标 表单。输出以 XML 标头开头,如下所示

  <?xml version="1.0" encoding="UTF-8"?>
  <query version="2">

然后继续为每个目标添加一个 XML 元素 以拓扑顺序排列(除非 无序结果), 然后以

</query>

系统会为 file 种类的目标发出简单条目:

  <source-file name='//foo:foo_main.cc' .../>
  <generated-file name='//foo:libfoo.so' .../>

但对于规则,XML 是结构化的,并且包含所有 规则的属性,包括其值不是 并在规则的 BUILD 文件中明确指定。

此外,结果还包含 rule-inputrule-output 元素,以使 可以重构依赖关系图,而无需知道 例如,srcs 属性的元素为 将依赖项(先决条件)和 outs 属性是后向依赖项(使用方)。

在以下情况下,会抑制隐式依赖项rule-input 元素: 已指定 --noimplicit_deps

  <rule class='cc_binary rule' name='//foo:foo' ...>
    <list name='srcs'>
      <label value='//foo:foo_main.cc'/>
      <label value='//foo:bar.cc'/>
      ...
    </list>
    <list name='deps'>
      <label value='//common:common'/>
      <label value='//collections:collections'/>
      ...
    </list>
    <list name='data'>
      ...
    </list>
    <int name='linkstatic' value='0'/>
    <int name='linkshared' value='0'/>
    <list name='licenses'/>
    <list name='distribs'>
      <distribution value="INTERNAL" />
    </list>
    <rule-input name="//common:common" />
    <rule-input name="//collections:collections" />
    <rule-input name="//foo:foo_main.cc" />
    <rule-input name="//foo:bar.cc" />
    ...
  </rule>

目标的每个 XML 元素都包含一个 name 属性,其值为目标的标签;以及 location 属性,其值是目标的 由 --output location 打印的位置。

--[no]xml:line_numbers

默认情况下,XML 输出中显示的位置包含行号。 指定 --noxml:line_numbers 时,不输出行号。

--[no]xml:default_values

默认情况下,XML 输出不包含值为 是该属性类型的默认值(例如,如果 未在 BUILD 文件中指定,或默认值为 明确提供)。此选项会导致此类属性值 包含在 XML 输出中。

正则表达式

查询语言中的正则表达式使用 Java 正则表达式库,因此您可以使用 完整语法 java.util.regex.Pattern

使用外部代码库进行查询

如果构建依赖于来自外部代码库(如 WORKSPACE 文件),则查询结果将包含这些依赖项。对于 例如,如果 //foo:bar 依赖于 //external:some-lib //external:some-lib 绑定到 @other-repo//baz:lib,则 bazel query 'deps(//foo:bar)'会同时列出@other-repo//baz:lib和 将 //external:some-lib 作为依赖项。

外部代码库本身不是构建的依赖项。也就是说, 在上面的示例中,//external:other-repo 不是依赖项。它 但可以作为 //external 软件包的成员进行查询, 例如:

  # Querying over all members of //external returns the repository.
  bazel query 'kind(http_archive, //external:*)'
  //external:other-repo

  # ...but the repository is not a dependency.
  bazel query 'kind(http_archive, deps(//foo:bar))'
  INFO: Empty results