Diagnostics: Inspecting Build Commands, Actions, etc. Last updated May 4, 2022

The command log

Bazel logs commands; each Bazel command overwrites the output of the previous command. You can discover the location of this log by running $ bazel info or $ bazel info command_log. Of course those are Bazel commands, so they overwrite the command_log. To make it easy to browse the log for the most recent command, you can use a simple alias, e.g. <pre>$ alias "bl=less bazel info command_log`"</pre> You can put this in a file and source it, or add it to your `.bash_profile.

Action Queries

Bazel rules typically generate actions that drive build tools (compilers, linkers, etc.). Bazel also caches aggressively; when you build a target, its target/dependency/action graphs are cached, so if you build it again Bazel will just show you the cached result of the previous build instead of rebuilding (unless its dependencies have changed). If you need to see the command that was used to build it, you can delete its output or run bazel clean to force a rebuild. But that’s inefficient, and Bazel offers a much better way: action graph queries.

Bazel rules may generate multiple actions. For example, if you pass a ppx_executable to an instance of the ocaml_module rule via the ppx attribute, it will generate three actions:

  • the first action writes a shell script responsible for running the ppx_executable;

  • the second action runs the shell script to transform the source file;

  • the third action compiles the output of the transformation.

Bazel may generate additional actions beyond those generated by the rule implementation.
Rules generate actions, but Bazel runs them. That is, rule implementations register actions with Bazel, and Bazel schedules and runs them, based on the dependency graphs.

The aquery command queries the action graph; it will print the list of all actions used to build a target, including the command line, environment variables, all inputs and outputs, and some internal Bazel metadata. It does not execute the actions, so it is quite fast, and you can run it without risk of triggering recompilations.

Usage is simple:

$ bazel aquery //foo/bar:baz

will describe all actions used to build target //foo/bar:baz.

The aquery command, like Bazel’s other query commands (query, cquery), supports much more sophisticated queries, such as filtering by inputs or outputs, combined queries using AND, etc.

Bazel Workspaces (Repositories)