Skip to main content
Goal: Understand how rule implementations lower the Dependency graph to the Action graph and how the commands query , cquery , and aquery allow you to inspect these graphs.

The Dependency Graph

In the Loading phase, Bazel loads all of the BUILD.bazel files needed for whatever targets or target patterns you request. These targets form a Directed Acyclic Graph (DAG) called the “dependency graph”. Each node is a target, and the edges are dependencies. The edges have different types, which are often:
  • srcs are source files in version control
  • deps are other targets that produce some outputs
  • data files, which should be propagated to any binary or test that transitively depends on this, is better thought of as “runtime_deps”

Exercise: bazel query

Perform some queries in the examples repo. For example:
  • Which binary targets can be run?
  • Which tests are short timeouts?
  • Which target depends on a proto_library and why?

Configuration and Transitions

Take this example:
This graph may differ based on configuration, for example the select function can change the deps of a target depending on the target platform. The “Configured dependency graph” includes a hash of the configuration. When a node in the Configured Dependency Graph has a different configuration than its child, this is called a “transition”. For example, this graph in the examples repo transitions between a configuration for building Java test code (with hash 8201991) and another configuration for the rest (with hash db7e569) java_query.svg

Exercise: bazel cquery

cquery means “configured query” which is typically what you want, as it is faster.
The Bazel query guide and cquery documentation are quite good. Here are some queries you can try in the logger folder now to get started.
  • What are all the binary targets in the repository?
  • What are all the binary targets in the logger project?
  • Draw a diagram of all the dependencies of a target.
  • Why does your binary depend on a particular third-party library?

The Action Graph

In the Analysis phase, the dependency graph is “lowered” to an action graph. In the action graph, each node is a subprocess to spawn (invoking some tool) with the arguments, environment, and so on for invoking it. The edges are Providers which are output by one action and needed as inputs to another. As a special case, the “DefaultInfo” provider gives the default output files of the action. The graphs are NOT one-to-one! For example, a ts_project rule with a custom transpiler produces several actions.

Querying the action graph

This is a valuable skill when debugging a failure of some rule, especially when required inputs aren’t declared. You can run arbitrary starlark programs on the action graph with --output=starlark which is a powerful tool.

Exercise: bazel aquery

  • What are the declared input files to the compile action for a library target you’ve created?
  • What providers are produced by the library target? (You’ll need a tiny Starlark program)

Summary