Now we'll start to add Bazel configuration for the first-party code in our repository.
By the end of this section, you'll be able to run
bazel query to explore Bazel's dependency and action graphs for at least the language you picked.
If you weren't able to get things working in the previous section, you can advance your codelabs
repo to the
dependencies branch, e.g. with
git reset --hard dependencies
The schema folder has our protobuf definition, and you'll want to depend on that from other folders.
Since we use Aspect CLI, you can just run
bazel configure to get a BUILD file generated for our
Next, for the language you've chosen, try creating the
Since our examples are simple and only have a single source file or folder of source files,
you'll only need one for each language.
ts_project was already created.
We can create a
http_server_binary for the
http-server npm package and call it using
java_grpc_library isn't available under bzlmod yet,
so we've just stashed the resulting generated code next to the sources.
bazel configure or Gazelle should work 100%.
A gazelle extension is available from rules_python, but a three-line
py_binary is enough to make the CLI work.
A gazelle extension for Swift source files is available in
When preparing your workspace in a previous step, you defined a target called
Running this target will generate
BUILD.bazel files with the appropriate Swift rules in packages where it finds Swift source files (e.g.
Due to the way that Swift iOS applications are typically generated, we need to tell the gazelle extension where to create the
ios/LoggingClient/App/BUILD.bazel and add the following comment to the file:
# gazelle:swift_default_module_name LoggingClientApp.
% echo "# gazelle:swift_default_module_name LoggingClientApp" \
These are used to configure gazelle and its extensions.
Now, run the
//:update_build_files target to generate your
% bazel run //:update_build_files
Machine-editing BUILD files
You can use
to script around printing and modifying BUILD file content, which is an essential skill for doing
Buildozer is purely syntactic, operating on the starlark Abstract Syntax Tree (AST). This can be convenient if you want to see what the user typed, before loading and macro expansion occur. It's also guaranteed to be fast, while loading might take a long time.
There's a dedicated 'print' command to make this feature easier to access:
bazel print //some:target
The Dependency Graph
In the Loading phase, Bazel loads all of the
BUILD.bazel files needed for whatever target(s) or target patterns you request.
These targets form a Directed Acyclic Graph (DAG) called the "dependency graph".
cquery means "configured query" which is typically what you want.
The unconfigured query command is just bare
Unfortunately the shorter name is taken by the less-useful command.
Here are some things you can try:
- What are all the binary targets in the repo?
- Draw a diagram like the one above for the language you're working with.
- Why does your binary depend on a particular third-party library?
When Bazel needs to transform inputs to outputs, it does it by spawning an Action, which is just a subprocess invoking some tool.
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) and the edges are files and Providers which are output by one action and needed as inputs to another.
The graphs are NOT one-to-one!
For example, a
ts_project rule with a custom transpiler produces several actions.
Bazel doesn't actually have a command called
It's spelled "build --nobuild" instead.
This command is rarely useful.
You might use it if you're making a big, breaking refactoring, so that you can resolve all the analysis failures first before attempting to build anything.
You could also use it to reason about what is the slow step in your CI pipeline.
bazel build --nobuild //...
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.
- 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)