Bazel 查询参考

报告问题 查看源代码 每夜 build · 7.4 . 7.3 · 7.2 · 7.1敬上 · 7.0 · 6.5

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

如需了解实用用例,请参阅 Bazel 查询操作方法

其他查询参考

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

操作图查询

操作图查询 (aquery) 会对分析后的配置目标图进行操作,并公开有关操作工件及其关系的信息。如果您对从配置的目标图生成的操作/工件的属性感兴趣,aquery 会很有用。例如,实际运行的命令及其输入、输出和助记符。

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

可配置的查询

传统的 Bazel 查询在加载后阶段的目标图上运行,因此不存在配置及其相关概念。值得注意的是,它无法正确解析 select 语句,而是会返回所有可能的 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、句点、 连字符、下划线、冒号、美元符号、波浪号、左方括号、右方括号 大括号)。但是,不带英文引号的字词不得以连字符 - 或星号 * 开头 即使相对的目标名称 这些字符。

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

    在编写用于构建 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.
    

    请注意,除了 shell 可能要求的任何引号之外,您还需要使用此引号,例如:

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

    带引号的关键字和运算符会被视为普通字词。例如,some 是关键字,但“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 文件中明确定义的构建依赖项之外,Bazel 还会向规则添加其他隐式依赖项。例如 每个 Java 规则都隐式依赖于 JavaBuilder。使用以 $ 开头的属性建立隐式依赖项,并且无法在 BUILD 文件中替换这些依赖项。

默认情况下,bazel query 会考虑隐式依赖项 。您可以使用 --[no]implicit_deps 选项更改此行为。请注意,由于查询不会考虑 配置,则绝不会考虑可能的工具链。

健全性

Bazel 查询语言表达式对构建依赖项图进行操作,该图由所有 BUILD 文件中的所有规则声明隐式定义。您有必要了解 这张图表有点抽象, 有关如何执行构建的所有步骤的完整说明。如需执行 build,还需要配置;如需了解详情,请参阅用户指南的配置部分。

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

关于图表顺序的保留

运算会保留从其子表达式继承的任何排序约束条件。您可以将其视为“部分有序的守恒定律”。举个例子:如果您发出查询来确定特定目标的依赖项的传递闭包,则生成的集合会按依赖项图排序。如果您过滤出设置为 仅包含 file 种类的目标, 传递部分排序关系 与在生成的子集中的目标对准,即使其中没有任何一个 实际上,这些对在原始图中是直接关联的。 (构建依赖关系图中没有文件到文件的边)。

不过,虽然所有运算符都会保留顺序,但某些运算(例如集合运算)不会引入任何自己的排序约束条件。请考虑以下表达式:

deps(x) union y

最终结果集的顺序保证会保留其子表达式的所有排序约束条件,即 x 的所有传递依赖项彼此之间具有正确的排序。不过,查询并不保证 y 中目标的顺序,也不考虑 deps(x)中各定位条件相对于 y(不包括位于 y 也位于 deps(x) 中)。

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

Sky 查询

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

仅在 SkyQuery 中提供的特殊函数

Sky Query 模式提供额外的查询函数 allrdepsrbuildfiles。这些函数在整个“宇宙”范围内运作(因此它们不适用于常规查询)。

指定“宇宙”范围

通过传递以下两个标志来启用 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 的行为符合您的预期时使用 --infer_universe_scope

与默认查询相比,Sky 查询有一些优点和缺点。主要缺点是,它无法按图表顺序对输出进行排序,因此禁止使用某些输出格式。它的优势在于,它提供了两个默认查询中不提供的运算符(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) 的求值结果为 //foo 的传递闭包中直接依赖于 //common 的所有节点。(这些 数字对应于 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) 个运算符计算 两组目标之间的路径。这两个查询都接受两个参数,一个是起点集 S,另一个是终点集 Esomepath 会返回从 S 中的目标到 E 中的目标的某个任意路径上的节点图;allpaths 会返回从 S 中的任意目标到 E 中的任意目标的所有路径上的节点图。

生成的图表会按依赖关系排序。如需了解详情,请参阅图表顺序部分。

索道
somepath(S1 + S2, E),一个可能的结果。
Somepath
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/...) 会评估为 foo 下的所有 cc_librarycc_binary 等规则目标的集合,而 kind("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/...

不过,此语句需要解析 bar 树中的所有 BUILD 文件,这会很慢,并且容易在无关的 BUILD 文件中出错。另一种方法是:

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

该命令会先计算一组 //foo 依赖项,然后仅过滤与所提供模式匹配的目标,也就是说,名称中包含 //bar 作为子字符串的目标。

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

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

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

规则属性过滤:attr

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 的成员,并且对于 predicate 中的所有目标 yxy 可见。例如:

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: tests

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 目标,以及加载 //bar:file.bzl 的任何其他 BUILD 文件的目标

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

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

软件包定义文件:loadfile

expr ::= loadfiles(expr)

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

输出格式

bazel query 会生成图表。 您可以使用 --output 命令行选项指定 bazel query 呈现此图表的内容、格式和排序。

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

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

关于结果的排序

虽然查询表达式始终遵循“图表有序性守恒定律”,但呈现结果可以按依赖项顺序或无序方式进行。这不会影响结果集中的目标或查询的计算方式。它只会 会影响将结果输出到 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 proto

将查询输出作为 QueryResult 协议缓冲区。

--output streamed_proto

输出 以长度分隔 数据流 Target 协议缓冲区这对于(i)在目标过多而无法放入单个 QueryResult 时规避协议缓冲区大小限制,或者(ii)在 Bazel 仍在输出时开始处理非常有用。

--output textproto

--output proto 类似, QueryResult 但位于 文本格式

--output streamed_jsonproto

--output streamed_proto 类似,它会输出以下内容的流: Target 协议缓冲区,但采用 ndjson 格式。

--output minrank --output maxrank

label 一样,minrankmaxrank 输出格式会输出生成图中每个目标的标签,但这些标签不是按拓扑顺序显示,而是按排名顺序显示,并在前面加上排名编号。它们不受结果排序的影响 --[no]order_results 标记(请参阅关于以下内容的说明: 结果的顺序)。

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

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

一个周期中的所有节点都被视为具有相同的等级。(大多数图表都是无环的,但循环确实会发生,只因 BUILD 文件包含错误的循环。)

这些输出格式有助于了解图的深度。如果用于 deps(x)rdeps(x)allpaths 查询的结果,则排名编号等于从 x 到该排名中的某个节点的最短路径(使用 minrank)或最长路径(使用 maxrank)的长度。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 或 vi)的工具也可以使用查询输出来逐个查看一系列匹配项,从而允许将 Bazel 查询工具用作感知依赖项图的“用于 BUILD 文件的 grep”。

位置信息因目标类型而异(请参阅 kind 运算符)。对于规则,系统会输出规则声明在 BUILD 文件中的位置。对于源文件,实际文件第 1 行的位置是 。对于生成的文件,系统会输出生成该文件的规则的位置。(查询工具没有足够的信息来查找生成文件的实际位置,并且在任何情况下,如果尚未执行 build,该文件都可能不存在。)

--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 属性是后向依赖项(使用方)。

如果指定了 --noimplicit_deps,系统会抑制隐式依赖项rule-input 元素。

  <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

使用外部代码库进行查询

如果 build 依赖于外部代码库中的规则(在 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