Aquery (Action Graph Query)

Overview

Caution: The aquery command is still experimental and its API will change.

The aquery command allows you to query for actions in your build graph. It operates on the post-analysis Configured Target Graph and exposes information about Actions, Artifacts and their relationships.

aquery is useful when we are interested in the properties of the Actions/Artifacts generated from the Configured Target Graph. For example, the actual commands run and their inputs/outputs/mnemonics.

The tool accepts several command-line options. Notably, the aquery command runs on top of a regular Bazel build and inherits the set of options available during a build.

It supports the same set of functions that is also available to traditional query but siblings, buildfiles and tests.

An example aquery output (without specific details):

$ bazel aquery 'deps(//some:label)'
action 'Writing file some_file_name'
  Mnemonic: ...
  Owner: ...
  Configuration: ...
  ActionKey: ...
  Inputs: [...]
  Outputs: [...]

Basic Syntax

A simple example of the syntax for aquery is as follows:

bazel aquery "aquery_function(function(//target))"

The query expression (in quotes) consists of the following:

  • aquery_function(...): functions specific to aquery. More details below.
  • function(...): the standard functions as traditional query.
  • //target is the label to the interested 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 Functions

There are currently 3 aquery functions:

  • inputs: filter actions by inputs.
  • outputs: filter actions by outputs
  • mnemonic: filter actions by mnemonic

expr ::= inputs(word, expr)

The inputs operator returns the actions generated from building expr, whose input filenames match the regex provided by word.

$ bazel aquery 'inputs(".*cpp", deps(//src/target_a))'

outputs and mnemonic functions share a similar syntax.

You can also combine functions to achieve the AND operation. For example:

  $ bazel aquery 'mnemonic("Cpp.*", (inputs(".*cpp", inputs("foo.*", //src/target_a))))'

The above command would find all actions involved in building //src/target_a, whose mnemonics match "Cpp.*" and inputs match the patterns ".*cpp" and "foo.*".

Important: aquery functions can't be nested inside non-aquery functions

  • Conceptually this makes sense since the output of aquery functions is Actions, not Configured Targets.
  • An example of the syntax error produced:
            $ 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))
          

Options

Build Options

aquery runs on top of a regular Bazel build and thus inherits the set of options available during a build.

Aquery options

--output=(text|proto|textproto), default=text

The default output format (text) is human-readable, use proto or textproto for machine-readable format.

--include_commandline, default=true

Includes the content of the action command lines in the output (potentially large).

--include_aspects, default=false

Whether to include Aspect-generated actions in the output.

--include_param_files, default=false

Include the content of the param files used in the command (potentially large). Warning: Enabling this flag will automatically enable the --include_commandline flag.

Miscellaneous

Aspect-on-Aspect

It is possible for Aspects to be applied on top of each other. The aquery output of the action generated by these Aspects would then include the Aspect path, which is the sequence of Aspects applied to the target which generated the action.

An example of Aspect-on-Aspect:

  t0
  ^
  | <- a1
  t1
  ^
  | <- a2
  t2

Let ti be a target of rule ri, which applies an Aspect ai to its dependencies.

Assume that a2 generates an action X when applied to target t0. The text output of bazel aquery --include_aspects 'deps(//t2)' for action X would be:

  action ...
  Mnemonic: ...
  Target: //my_pkg:t0
  Configuration: ...
  AspectDescriptors: [//my_pkg:rule.bzl%a2(foo=...)
    -> //my_pkg:rule.bzl%a1(bar=...)]
  ...

This means that action X was generated by Aspect a2 applied onto a1(t0), where a1(t0) is the result of Aspect a1 applied onto target t0.

Each AspectDescriptor has the following format:

  AspectClass([param=value,...])

AspectClass could be the name of the Aspect class (for native Aspects) or bzl_file%aspect_name (for Starlark Aspects). AspectDescriptor are sorted in topological order of the dependency graph.

Known Issues

The list of aquery issues/planned features can be found on GitHub.

Updates

Aquery is a work in progress, and its API might change in the future. Please contact twerth@google.com and leba@google.com for any issue/feature request.