查询指南

报告问题 查看源代码

本页面介绍了如何开始使用 Bazel 的查询语言跟踪代码中的依赖项。

如需了解语言详细信息和 --output 标志详细信息,请参阅参考文档、Bazel 查询参考文档Bazel 查询参考文档。您可以通过在命令行中输入 bazel help querybazel help cquery 获取帮助。

如需在执行查询时忽略错误(例如缺少目标),请使用 --keep_going 标志。

查找规则的依赖关系

如需查看 //foo 的依赖项,请在 bazel 查询中使用 deps 函数:

$ bazel query "deps(//foo)"
//foo:foo
//foo:foo-dep
...

这是构建 //foo 所需的所有目标的集合。

跟踪两个软件包之间的依赖关系链

//third_party/zlib:zlibonly 不在 //foo 的 BUILD 文件中,但它是一个间接依赖项。我们如何跟踪此依赖项路径?其中有两个实用函数:allpathssomepath。如果您仅关心所构建的工件中包含的内容,而不关心每个可能的作业,那么您可能还需要使用 --notool_deps 排除工具依赖项。

如需直观呈现所有依赖项的图表,请通过 dot 命令行工具使用 bazel 查询输出流水线:

$ bazel query "allpaths(//foo, third_party/...)" --notool_deps --output graph | dot -Tsvg > /tmp/deps.svg

当依赖关系图庞大而复杂时,从一条路径开始会很有帮助:

$ bazel query "somepath(//foo:foo, third_party/zlib:zlibonly)"
//foo:foo
//translations/tools:translator
//translations/base:base
//third_party/py/MySQL:MySQL
//third_party/py/MySQL:_MySQL.so
//third_party/mysql:mysql
//third_party/zlib:zlibonly

如果不通过 allpaths 指定 --output graph,您将获得依赖关系图的扁平化列表。

$ bazel query "allpaths(//foo, third_party/...)"
  ...many errors detected in BUILD files...
//foo:foo
//translations/tools:translator
//translations/tools:aggregator
//translations/base:base
//tools/pkg:pex
//tools/pkg:pex_phase_one
//tools/pkg:pex_lib
//third_party/python:python_lib
//translations/tools:messages
//third_party/py/xml:xml
//third_party/py/xml:utils/boolean.so
//third_party/py/xml:parsers/sgmlop.so
//third_party/py/xml:parsers/pyexpat.so
//third_party/py/MySQL:MySQL
//third_party/py/MySQL:_MySQL.so
//third_party/mysql:mysql
//third_party/openssl:openssl
//third_party/zlib:zlibonly
//third_party/zlib:zlibonly_v1_2_3
//third_party/python:headers
//third_party/openssl:crypto

延伸阅读:隐式依赖项

//foo 的 BUILD 文件从不引用 //translations/tools:aggregator。那么,直接依赖项在哪里?

某些规则包括对其他库或工具的隐式依赖项。例如,如需构建 genproto 规则,您需要先构建 Protocol Compiler,因此每条 genproto 规则都对协议编译器具有隐式依赖项。这些依赖项未在 build 文件中提及,而是由构建工具添加。整套隐式依赖项目前尚未记录。使用 --noimplicit_deps 可让您从查询结果中过滤掉这些依赖项。对于 cquery,这将包括已解析的工具链。

反向依赖项

您可能想了解依赖于某个目标的一组目标。例如,如果您要更改一些代码,可能想知道即将破坏的其他代码。在 u 的传递闭包内,您可以使用 rdeps(u, x) 查找 x 中目标的反向依赖项。

Bazel 的 Sky Query 支持 allrdeps 函数,该函数允许您查询指定的宇宙中的反向依赖项。

其他用途

您可以使用 bazel query 分析许多依赖关系。

现有内容 ...

foo 下存在哪些软件包?

bazel query 'foo/...' --output package

foo 软件包中定义了哪些规则?

bazel query 'kind(rule, foo:*)' --output label_kind

foo 软件包中的规则会生成哪些文件?

bazel query 'kind("generated file", //foo:*)'

Starlark 宏 foo 会生成哪些目标?

bazel query 'attr(generator_function, foo, //path/to/search/...)'

构建 //foo 所需的 BUILD 文件集是什么?

bazel query 'buildfiles(deps(//foo))' | cut -f1 -d:

test_suite 会扩展为哪些具体测试?

bazel query 'tests(//foo:smoke_tests)'

下列哪些是 C++ 测试?

bazel query 'kind(cc_.*, tests(//foo:smoke_tests))'

哪些是小型的?适中?大型?

bazel query 'attr(size, small, tests(//foo:smoke_tests))'

bazel query 'attr(size, medium, tests(//foo:smoke_tests))'

bazel query 'attr(size, large, tests(//foo:smoke_tests))'

foo 下与模式匹配的测试有哪些?

bazel query 'filter("pa?t", kind(".*_test rule", //foo/...))'

该模式是一个正则表达式,并且会应用于规则的全名。这类似于

bazel query 'kind(".*_test rule", //foo/...)' | grep -E 'pa?t'

哪个软件包包含文件 path/to/file/bar.java

 bazel query path/to/file/bar.java --output=package

path/to/file/bar.java? 的 build 标签是什么

bazel query path/to/file/bar.java

哪些规则目标包含“path/to/file/bar.java”文件作为来源?

fullname=$(bazel query path/to/file/bar.java)
bazel query "attr('srcs', $fullname, ${fullname//:*/}:*)"

存在哪些软件包依赖项 ...

foo 依赖于哪些软件包?(构建 foo 需要检查哪些内容)

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

foo 树依赖于哪些软件包(foo/contrib 除外)?

bazel query 'deps(foo/... except foo/contrib/...)' --output package

存在哪些关联规则 ...

Bar 依赖于什么 genproto 规则?

bazel query 'kind(genproto, deps(bar/...))'

查找 servlet 树中的 Java 二进制规则传递性依赖的 JNI (C++) 库的定义。

bazel query 'some(kind(cc_.*library, deps(kind(java_binary, //java/com/example/frontend/...))))' --output location
...现在,请查找依赖于它们的所有 Java 二进制文件的定义
bazel query 'let jbs = kind(java_binary, //java/com/example/frontend/...) in
  let cls = kind(cc_.*library, deps($jbs)) in
    $jbs intersect allpaths($jbs, $cls)'

存在哪些文件依赖关系 ...

构建 foo 所需的一整套 Java 源文件是什么?

源文件:

bazel query 'kind("source file", deps(//path/to/target/foo/...))' | grep java$

生成的文件:

bazel query 'kind("generated file", deps(//path/to/target/foo/...))' | grep java$

构建 QUX 的测试所需的一整套 Java 源文件是什么?

源文件:

bazel query 'kind("source file", deps(kind(".*_test rule", javatests/com/example/qux/...)))' | grep java$

生成的文件:

bazel query 'kind("generated file", deps(kind(".*_test rule", javatests/com/example/qux/...)))' | grep java$

X 和 Y 之间的依赖关系存在哪些差异 ...

//foo 不依赖 //foo:foolib 的哪些目标?

bazel query 'deps(//foo) except deps(//foo:foolib)'

foo 测试所依赖的 //foo 正式版二进制文件不依赖于哪些 C++ 库?

bazel query 'kind("cc_library", deps(kind(".*test rule", foo/...)) except deps(//foo))'

为什么存在此依赖项 ...

为什么 bar 依赖于 groups2

bazel query 'somepath(bar/...,groups2/...:*)'

获得此查询的结果后,您经常会发现,单个目标明显是非预期、严重且不必要的 bar 依赖项。然后,该查询可以进一步优化,以便:

显示从 docker/updater:updater_systest (py_test) 到其依赖的某个 cc_library 的路径:

bazel query 'let cc = kind(cc_library, deps(docker/updater:updater_systest)) in
  somepath(docker/updater:updater_systest, $cc)'

为什么库 //photos/frontend:lib 依赖于同一个库 //third_party/jpeglib//third_party/jpeg 的两个变体?

此查询可归结为:“显示依赖于两个库的 //photos/frontend:lib 子图”。按拓扑顺序显示时,结果的最后一个元素是最可能引发问题的元素。

bazel query 'allpaths(//photos/frontend:lib, //third_party/jpeglib)
                intersect
               allpaths(//photos/frontend:lib, //third_party/jpeg)'
//photos/frontend:lib
//photos/frontend:lib_impl
//photos/frontend:lib_dispatcher
//photos/frontend:icons
//photos/frontend/modules/gadgets:gadget_icon
//photos/thumbnailer:thumbnail_lib
//third_party/jpeg/img:renderer

取决于以下因素 ...

柱形下哪些规则取决于 Y?

bazel query 'bar/... intersect allpaths(bar/..., Y)'

哪些目标直接依赖于 T 软件包中的 T?

bazel query 'same_pkg_direct_rdeps(T)'

如何解除依赖关系 ...

我需要中断哪些依赖项路径才能使 bar 不再依赖于 X?

如需将图表输出到 svg 文件,请执行以下操作:

bazel query 'allpaths(bar/...,X)' --output graph | dot -Tsvg > /tmp/dep.svg

其他

//foo-tests build 中有多少个连续步骤?

遗憾的是,查询语言目前无法提供从 x 到 y 的最长路径,但它可以找到从起点起(也就是 aa)最远的节点,或者向您显示从 x 到其所依赖的每个 y 的最长路径的长度。a使用 maxrank

bazel query 'deps(//foo-tests)' --output maxrank | tail -1
85 //third_party/zlib:zutil.c

结果表明,此 build 中存在必须按顺序发生的长度为 85 的路径。