Migrate to bzlmod
Background: Bazel's dependency story
Historically, Bazel came from Blaze, the monorepo build tool developed within Google's monorepo, "google3".
google3 is fully self-contained, even bootstrapping compilers from source.
It has no "third-party" dependencies, aside from those that engineers lovingly vendor into the third_party
folder.
For this reason, Blaze has no affordances for fetching external packages.
The google3/WORKSPACE
file is short and meaningless to Googlers as there's very little repo-wide configuration.
However when releasing Bazel, it was clear that other users needed external packages. As much as Google is opinionated, asking everyone to vendor their dependencies in every language is a non-starter.
Thus, concepts such as "repository rules" were invented to give the beginning of Bazel's analysis phase the ability to fetch archives over HTTP, and perform post-install steps on the code that was fetched. As evidence of this lineage, note that Bazel's evaluation model doesn't mention the "fetch" phase; this is because Blaze has no such concept.
However, the implementation of the "fetch" phase in the WORKSPACE
file was fatally flawed: it has no dependency resolution step.
In fact it doesn't understand transitive dependencies at all.
To workaround this omission, developers of Bazel rulesets created macros that wrap the repository_rules, such as
my_rules_dependencies()
. Calling this from the end-user's WORKSPACE
file causes those dependencies to fetch.
This doesn't work well because the first fetch wins. If my_rules_dependencies()
brings you rules_python@0.1.0
then you get errors
later in the build about rules_python
not working the way you expect, and it's nearly impossible to discover where version 0.1.0
comes from.
The solution to these problems is to replace most or all of the content of your WORKSPACE
file with a new file introduced for Bazel 6,
MODULE.bazel
. Starting with Bazel 7, the new file is enabled by default, and in Bazel 8 the team plans to disable reading WORKSPACE
unless you
supply an opt-in flag; however that flag will be removed in Bazel 9.
This means every Bazel user is forced to make this migration eventually.
For more background, see our blog post from before Bazel 6 was released.
Common migration path
- Upgrade to latest Bazel first. It's possible to do bzlmod on Bazel 6 and then upgrade Bazel after. However we recommend this order because bzlmod bugfixes have been landing, so the bzlmod-first migration might need extra workarounds.
- At first, disable new Bazel 7 flags. Makes the Bazel 7 upgrade less risky and "do one thing at a time". These include:
- Land
.bazelversion
upgrade and wait a few days to "bake" since there may be developer machines or CD machines that have hard-coded Bazel version. - Remove
--noenable_bzlmod
and try analyzing (bazel build --nobuild //...
). Bazel will create aMODULE.bazel
file. Follow guidance below to make the minimal changes to get this green. - Rinse-and-repeat to burn down the content of WORKSPACE and replace with MODULE.bazel.
Detailed migration instructions and notes
This section is available to Aspect customers only, at https://pro.aspect.build.
If you don't have a login, you can register for Aspect Pro. Email hello@aspect.dev to learn more.