When using Bazel you might find that you need to patch one of your external dependencies, be it source code for a third-party library or a Starlark rule set. The simple way to approach this is to fork the dependency, push your changes, and point to your fork instead of the source. While this is simple, I would argue it’s not easy, as you now have to maintain a fork, which has some downsides:
- Updating the dependency takes many more steps than before (e.g. pulling the latest changes, rebasing or merging those with your patches, pushing those, and finally pointing to your new patches)
- If the patches can’t be made public, you might have to use
http_archive, which has worse caching performance
- The fork has to live somewhere outside of the workspace that is applying the patches
Instead of forking your dependency, I recommend using the
patches attribute on the
git_repository rules. The attribute takes a list of labels for the patches to apply, in the order provided.
If you use
git diff or
git format-patch to produce your patches, you’ll also need to supply
Using patches addresses the issues I mentioned above:
- Updating a dependency is the same as without using patches, unless the patch needs to be rebased or updated (I’ll cover how to handle that a later section)
- You don’t have to change the repository rule you are currently using
- The patches live in the workspace that uses them
My preferred way of creating patches involves checking out the dependency locally and using the
--override_repository flag (e.g.
‑‑override_repository=build_bazel_rules_swift=/Users/bj/dev/rules_swift). This allows you to iterate on your patch without having to produce patch files or adjust your
Once your changes are finalized, I recommend committing them to your checked out dependency’s repository. This will make updating the patch in the future easier. You’ll be able to rebase your commits with relative ease and generate new patches.
If you committed your changes, then running
git format-patch --keep-subject --no-stat --zero-commit origin/main will produce a patch file for each commit that differs from
origin/main. Move these into your workspace somewhere and reference them in the
I recommend publishing these commits to a private fork. This allows your teammates to easily update the patches (following the steps in the next section).
If you find yourself editing your external dependencies a lot (e.g. if you are a maintainer of some Starlark rule sets 😬), you can add the
--override_repository flags to your
build:ora --override_repository=build_bazel_rules_apple=/Users/bj/dev/rules_apple build:ors --override_repository=build_bazel_rules_swift=/Users/bj/dev/rules_swift
And then whenever you want to use your locally checked out dependency, just pass the corresponding
$ bazel build --config=ors -- //Foo:Bar
If you committed your patches to your locally checked out dependency, then updating them is as easy as rebasing.
After rebasing, check that your changes work with
--override_repository. Once your commits are in a good state, regenerate your patches, override the ones you already have in your workspace, and update your
WORKSPACE file to point to the commit that you rebased onto.