What’s new in Bazel 7.0

Posted
Also posted on BuildBuddy Blog

Bazel 7.0 includes over 3,700 changes since 6.0. It’s the latest major release, following the release of 6.0 in December of last year, and it’s Bazel’s fourth LTS release.

Since there were so many changes, many of them quite impactful, I felt I needed to review them all and provide a nice summary for y’all.

While I reviewed every change, I didn’t understand every change 😅. I just wanted to mention that, since this isn’t an exhaustive list of changes, but it is a lot of changes I felt were relevant to a large portion of the community. Also, this year I’ve included changes that appeared in the Bazel 6 minor releases (e.g. Bazel 6.1). While you might already be on a version greater than 6.0, you might not know about all of the neat changes that made it into these “minor” releases.

Similar to Bazel 6.0’s changes, the end result was quite big, so I’ve included a table of contents to allow easy navigation to the changes that interest you the most:

Command-line flag changes

Bazel’s LTS strategy allows for breaking changes between major versions. In particular, it allows for command-line flags to be removed, renamed, made to do nothing, or have their default values changed. In the following sections I collected all such flag changes I could find.

Renamed

Default values changed

Undeprecated

Surprisingly, a flag was undeprecated in Bazel 7.0:

No-op

These flags now do nothing, but still exist to allow for migration off of them:

Removed

Remote

One of Bazel’s most powerful features is its ability to use remote caching and remote execution. Numerous improvements and fixes to Bazel’s remote capabilities made it into Bazel since 6.0.

Below are some changes that weren’t tied to any specific remote feature (e.g. gRPC connections):

Remote caching (RBC)

Using a remote cache is one of the most popular ways of speeding up a Bazel build. Thankfully these changes make using a remote cache both more performant and more reliable:

Remote execution (RBE)

For some projects, using remote execution is the ultimate performance unlock for their Bazel builds. In addition to the remote caching changes covered above, which also apply to remote execution, the following changes improve the remote execution experience:

Dynamic execution

Dynamic execution allows for Bazel to race remote and local execution of actions, potentially allowing you to get the benefit of both modes, without the drawbacks of either. Bazel 7.0 only included a single notable user-facing change to dynamic execution:

Build Event Service (BES)

Using a build event service can give you unparalleled insight into your Bazel builds at scale. There were a couple nice changes to BES support:

Logging

Bazel offers various methods to gain insight into your build. I cover some of the notable changes to those methods below.

Build Event Protocol (BEP)

The build event protocol is used by build event services, so all of these changes could have also been listed in that section as well. The BEP can also be collected locally with --build_event_json_file, --build_event_binary_file, and --build_event_text_file.

The vast majority of changes added additional information to the BEP, though some are fixes and improvements:

Timing profile

The action timing profile, which is enabled by default with --profile, is viewable both locally in Chrome and on build event services. These changes add more detail and clarity to the profile:

Execution log

Bazel logs all of the spawns it executes in the execution log, which is enabled with the --execution_log_json_file or --execution_log_binary_file flags. This feature is relatively stable, with just a few noticeable changes:

Execution graph

The execution graph, which is enabled with the --experimental_enable_execution_graph_log flag, logs all actions executed during a build. It differs from the execution log in that it contains additional information needed to reconstruct the full dependency graph.

Even though there aren’t many changes to the execution graph in Bazel 7.0, I only recently learned about its existence, and wanted to call attention to it:

Other

Execution

Executing build commands is a primary function of Bazel. Some execution related changes can be classified in a particular way, such as remote execution or dynamic execution. For the rest, I’ve collected them here.

Below I summarize some foundational execution related changes, including “local execution” strategies:

Running and testing

In addition to building targets, Bazel can run applications and tests with the run and test commands. Here were some notable changes to that functionality:

Coverage

Bazel can collect code coverage when running tests. Recent changes made the default settings work for more people:

Persistent Workers

Persistent workers improve build performance by sending multiple requests to long-running processes. Here are some notable changes to persistent worker support:

Querying

Here are some changes that were made to the query family of commands, starting with ones that applied to more than one of the commands:

query

cquery

aquery

Dependency management

With Bazel 7.0 external dependencies can be managed either with Bzlmod or the WORKSPACE file. Here are some changes that apply to either method:

Bzlmod

With Bazel 7.0 Bzlmod is enabled by default. While Bzlmod was made non-experimental in Bazel 6.0, the minor releases contained a lot of additional quality-of-life and feature improvements:

Platforms

Platforms are where your build tools run (i.e. execution platforms) or where your built products will run (i.e. target platforms). In previous years I catagorized changes along those lines, but this year I’m not making that distinction.

Android

Apple

Linux

Windows

Languages

While there are lots of programming languages that are supported through standalone Starlark rules, some are still written as “native” rules in Bazel core, or are bundled Starlark rules while Starlarkification is in progress. In the following sections I summarize the notable changes in support of these languages.

Bash

C and C++

Java

Objective-C

Proto

Python

Starlark and Build API

Starlark is the configuration language used to configure your project. It is also the programming language used to define rules. Bazel also has a Build API which defines standard functions, modules, and rules that can be used from Starlark. Here are some notable changes to both:

Aspects

Aspects allow augmenting build dependency graphs with additional information and actions.

Platforms and toolchains API

In Bazel 7.0 the C++, Android, and Apple rules completed their migration to support building with Platforms.

Here are some of the platforms and toolchains related changes which weren’t tied to any of those migrations:

Misc

There were a handful of changes that I couldn’t find a nice home for in the sections above, but I still felt were important or interesting enough to call attention to:

Summary

As you can see, Bazel 7.0 was another massive release (20% larger than last year!). Thankfully, through the rolling releases process, people were able to test, or even actively depend on, these changes well before the first 7.0 release candidate was cut.

Work on Bazel 8.0 is well underway, and I look forward to summarizing its changes next year. Until then, 👋.