您可以使用 aquery
命令查询构建图中的操作。
它在分析后配置目标图上运行,并显示
有关操作、工件及其关系的信息。
当您对操作/工件的属性感兴趣时,aquery
非常有用
根据已配置的目标图表生成的图片。例如,实际的命令运行
及其输入/输出/助记符。
该工具接受多个命令行选项。 值得注意的是,aquery 命令运行在常规 Bazel 构建之上,并且继承了 构建期间可用的一组选项。
它支持的一系列功能与传统
query
,但 siblings
、buildfiles
和
tests
。
aquery
输出示例(无具体详情):
$ bazel aquery 'deps(//some:label)' action 'Writing file some_file_name' Mnemonic: ... Target: ... Configuration: ... ActionKey: ... Inputs: [...] Outputs: [...]
基本语法
aquery
的语法的简单示例如下所示:
bazel aquery "aquery_function(function(//target))"
查询表达式(带引号)包含以下内容:
aquery_function(...)
:特定于aquery
的函数。 如需了解更多详情,请参阅下文。function(...)
:标准函数 与传统的query
相同。//target
是相关目标的标签。
# aquery examples: # Get the action graph generated while building //src/target_a $ bazel aquery '//src/target_a' # Get the action graph generated while building all dependencies of //src/target_a $ bazel aquery 'deps(//src/target_a)' # Get the action graph generated while building all dependencies of //src/target_a # whose inputs filenames match the regex ".*cpp". $ bazel aquery 'inputs(".*cpp", deps(//src/target_a))'
使用 aquery 函数
aquery
函数有三个:
inputs
:按输入过滤操作。outputs
:按输出过滤操作mnemonic
:按助记符过滤操作
expr ::= inputs(word, expr)
inputs
运算符返回在构建 expr
时生成的操作,
其输入文件名与 word
提供的正则表达式匹配。
$ bazel aquery 'inputs(".*cpp", deps(//src/target_a))'
outputs
和 mnemonic
函数的语法类似。
您还可以组合函数来实现 AND 运算。例如:
$ bazel aquery 'mnemonic("Cpp.*", (inputs(".*cpp", inputs("foo.*", //src/target_a))))'
上面的命令会查找构建 //src/target_a
中涉及的所有操作,
其助记符与 "Cpp.*"
匹配,且输入内容与模式匹配
".*cpp"
和"foo.*"
。
产生的语法错误示例如下:
$ bazel aquery 'deps(inputs(".*cpp", //src/target_a))' ERROR: aquery filter functions (inputs, outputs, mnemonic) produce actions, and therefore can't be the input of other function types: deps deps(inputs(".*cpp", //src/target_a))
选项
构建选项
aquery
在常规 Bazel build 之上运行,因此继承了
选项
在构建期间可用
Aquery 选项
--output=(text|summary|proto|jsonproto|textproto), default=text
默认输出格式 (text
) 直观易读,
使用 proto
、textproto
或 jsonproto
作为机器可读格式。
proto 消息为 analysis.ActionGraphContainer
。
--include_commandline, default=true
在输出(可能较大)中包含操作命令行的内容。
--include_artifacts, default=true
包括输出中操作输入和输出的名称(可能较大)。
--include_aspects, default=true
是否在输出中包含切面生成的操作。
--include_param_files, default=false
添加命令中使用的参数文件(可能较大)的内容。
--include_file_write_contents, default=false
添加 actions.write()
操作的文件内容以及
SourceSymlinkManifest
操作的清单文件
在 file_contents
字段中返回 --output=
xxxproto
。
使用 --output=text
时,输出结果如下:
FileWriteContents: [<base64-encoded file contents>]
行
--skyframe_state, default=false
在不执行额外分析的情况下,从 Skyframe 转储操作图。
其他工具和功能
查询 Skyframe 状态
Skyframe 是评估方法, 增量模型在 Bazel 服务器的每个实例上,Skyframe 都会存储依赖关系图 分析阶段。
在某些情况下,查询 Skyframe 上的操作图表会很有用。 示例用例如下:
- 运行
bazel build //target_a
- 运行
bazel build //target_b
- 已生成文件“
foo.out
”。
作为一名 Bazel 用户,我想确定 foo.out
是否是通过构建
//target_a
或 //target_b
。
一个可以运行 bazel aquery 'outputs("foo.out", //target_a)'
,
bazel aquery 'outputs("foo.out", //target_b)'
找出
用于创建 foo.out
,进而创建目标。不过,
之前构建的目标可以大于 2,这会导致运行多个 aquery
会很麻烦
作为替代方案,您可以使用 --skyframe_state
标志:
# List all actions on Skyframe's action graph $ bazel aquery --output=proto --skyframe_state # or # List all actions on Skyframe's action graph, whose output matches "foo.out" $ bazel aquery --output=proto --skyframe_state 'outputs("foo.out")'
在 --skyframe_state
模式下,aquery
会获取操作图的内容
Skyframe 将 Bazel 实例保留,并(可选)对其执行过滤
输出内容,而无需重新运行分析阶段。
特别注意事项
输出格式
--skyframe_state
目前仅适用于 --output=proto
和--output=textproto
查询表达式中未包含目标标签
目前,--skyframe_state
会查询 Skyframe 上存在的整个操作图,
无论目标是什么将查询中指定的目标标签与
--skyframe_state
会被视为语法错误:
# WRONG: Target Included $ bazel aquery --output=proto --skyframe_state **//target_a** ERROR: Error while parsing '//target_a)': Specifying build target(s) [//target_a] with --skyframe_state is currently not supported. # WRONG: Target Included $ bazel aquery --output=proto --skyframe_state 'inputs(".*.java", **//target_a**)' ERROR: Error while parsing '//target_a)': Specifying build target(s) [//target_a] with --skyframe_state is currently not supported. # CORRECT: Without Target $ bazel aquery --output=proto --skyframe_state $ bazel aquery --output=proto --skyframe_state 'inputs(".*.java")'
比较 aquery 输出
您可以使用 aquery_differ
工具比较两个不同 aquery 调用的输出。
例如,如果您对规则定义进行了一些更改,并希望验证
正在运行的命令行未更改。aquery_differ
是实现此目的的工具。
该工具在 bazelbuild/bazel 代码库中提供。 如需使用它,请将代码库克隆到本地机器。用法示例:
$ bazel run //tools/aquery_differ -- \ --before=/path/to/before.proto \ --after=/path/to/after.proto \ --input_type=proto \ --attrs=cmdline \ --attrs=inputs
上述命令会返回 before
和 after
查询输出之间的差异:
哪些操作分别存在,哪些操作各不相同
命令行/输入...)。运行以上命令的结果为:
Aquery output 'after' change contains an action that generates the following outputs that aquery output 'before' change doesn't: ... /list of output files/ ... [cmdline] Difference in the action that generates the following output(s): /path/to/abc.out --- /path/to/before.proto +++ /path/to/after.proto @@ -1,3 +1,3 @@ ... /cmdline diff, in unified diff format/ ...
命令选项
--before, --after
:要比较的 aquery 输出文件
--input_type=(proto|text_proto), default=proto
:输入的格式
文件。支持 proto
和 textproto
aquery 输出。
--attrs=(cmdline|inputs), default=cmdline
:操作的属性
进行比较。
纵横比
切面 相互叠加。由 API 生成的操作的 aquery 输出 然后,这些切面将包含切面路径,这是 应用于生成操作的定位条件的切面。
Aspect-on-Aspect 示例:
t0 ^ | <- a1 t1 ^ | <- a2 t2
让 ti 为规则 ri 的目标,此规则会应用切面 ai 与其依赖项相关联
假设 a2 在应用于目标 t0 时生成操作 X。文本输出的
操作 X 的 bazel aquery --include_aspects 'deps(//t2)'
为:
action ... Mnemonic: ... Target: //my_pkg:t0 Configuration: ... AspectDescriptors: [//my_pkg:rule.bzl%**a2**(foo=...) -> //my_pkg:rule.bzl%**a1**(bar=...)] ...
这意味着操作 X
是由应用于切面 a2
的
a1(t0)
,其中 a1(t0)
是应用切面 a1
的结果
目标t0
。
每个 AspectDescriptor
都采用以下格式:
AspectClass([param=value,...])
AspectClass
可以是 Aspect 类的名称(适用于原生 Aspect)或
bzl_file%aspect_name
(适用于 Starlark Aspects)。AspectDescriptor
是
的拓扑顺序
依赖关系图。
使用 JSON 配置文件进行链接
虽然 aquery 提供了在 build 中运行的操作的相关信息(运行这些操作的原因, 其输入/输出)、JSON 配置文件 告诉我们它们执行的时间和持续时间。 您可以通过一个共同分母(操作的主要输出)将这 2 组信息结合起来。
包括操作输出到 JSON 配置文件中,然后使用以下代码
--experimental_include_primary_output --noexperimental_slim_json_profile
。
精简配置文件与包含主要输出不兼容。操作的主要输出
默认包含在 aquery 中
我们目前尚未提供整合这两种数据源的规范工具,但您应 能够使用上述信息构建您自己的脚本。
已知问题
处理共享操作
有时,操作 共享了 配置目标之间的空间。
在执行阶段,这些共享操作
简单视为一次,且仅执行一次。
不过,查询在执行前分析后操作图上运行,因此会将这些
就像单独的操作,其输出制品具有完全相同的 execPath
。因此
等效的软件制品似乎重复。
有关搜索查询问题/计划推出的功能的列表,请访问 GitHub
常见问题解答
即使输入文件的内容发生更改,ActionKey 也保持不变。
在查询的上下文中,ActionKey
是指 String
从
ActionAnalysisMetadata#getKey:
Returns a string encoding all of the significant behaviour of this Action that might affect the output. The general contract of `getKey` is this: if the work to be performed by the execution of this action changes, the key must change. ... Examples of changes that should affect the key are: - Changes to the BUILD file that materially affect the rule which gave rise to this Action. - Changes to the command-line options, environment, or other global configuration resources which affect the behaviour of this kind of Action (other than changes to the names of the input/output files, which are handled externally). - An upgrade to the build tools which changes the program logic of this kind of Action (typically this is achieved by incorporating a UUID into the key, which is changed each time the program logic of this action changes). Note the following exception: for actions that discover inputs, the key must change if any input names change or else action validation may falsely validate.
这会排除对输入文件内容的更改,因此不要与它混淆 RemoteCacheClient#ActionKey。
更新
如有任何问题/功能请求,请在此处提交问题。