There are times where you are working on a Bazel project that is pulling in dependencies via rules_jvm_external
and you may want to override a jar with a locally built one. This is useful when you want to test a change in a dependency that is not yet published.
Let’s see this in action. The code for this example can be found here.
This post assumes you already have a Bazel project set up with rules_jvm_external
.
Querying the Original Target
For the sake of this example, we will be replacing the guava
jar with our own jar. Let’s query for the original guava target. Output trimmed for brevity. This will show the target that is being generated by rules_jvm_external
, and we will use it in a subsequent step.
> bazel query @maven//... | grep guava
@maven//:com_google_guava_guava
> bazel query @maven//:com_google_guava_guava --output=build
jvm_import(
name = "com_google_guava_guava",
visibility = ["//visibility:public"],
tags = ["maven_coordinates=com.google.guava:guava:32.0.1-jre", "maven_repository=https://repo1.maven.org/maven2", "maven_sha256=bd7fa227591fb8509677d0d1122cf95158f3b8a9f45653f58281d879f6dc48c5", "maven_url=https://repo1.maven.org/maven2/com/google/guava/guava/32.0.1-jre/guava-32.0.1-jre.jar"],
jar = "@maven//:com/google/guava/guava/32.0.1-jre/guava-32.0.1-jre.jar",
deps = ["@maven//:com_google_code_findbugs_jsr305", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_failureaccess", "@maven//:com_google_guava_listenablefuture", "@maven//:com_google_j2objc_j2objc_annotations", "@maven//:org_checkerframework_checker_qual"],
maven_coordinates = "com.google.guava:guava:32.0.1-jre",
maven_url = "https://repo1.maven.org/maven2/com/google/guava/guava/32.0.1-jre/guava-32.0.1-jre.jar",
)
Creating the Override Target
Start by adding a maven.override
to your MODULE.bazel
file. This is telling rules_jvm_external
to override whatever is in the maven_install.json
file with the target specified.
I am using a target called my_guava
in the override
directory. You can name this whatever you want, but it should be a target that is not already in use.
# MODULE.bazel
maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
maven.install(
artifacts = [
"com.google.guava:guava:31.0.1-jre",
],
lock_file = "//:maven_install.json",
)
maven.override(
coordinates = "com.google.guava:guava",
target = "@//override:my_guava",
)
Now we are going to create the my_guava
target. To make this simple, we will just copy the jvm_import
rule that we queried for earlier and just change the jar
attribute to point to a local jar.
The local jar can be copied from a remote maven repository, built from a java_library
target, copied from your ~/.m2
directory, or whatever you want. In this example, I am just using an empty jar file.
# override/BUILD.bazel
load("@rules_jvm_external//private/rules:jvm_import.bzl", "jvm_import")
jvm_import(
name = "my_guava",
# This is a jar copied into the workspace
jar = ":empty.jar",
# This is a generated jar
# jar = ":empty_bin_deploy.jar",
# This is the original jar
# jar = "@maven//:com/google/guava/guava/32.0.1-jre/guava-32.0.1-jre.jar",
maven_coordinates = "com.google.guava:guava:32.0.1-jre",
maven_url = "https://repo1.maven.org/maven2/com/google/guava/guava/32.0.1-jre/guava-32.0.1-jre.jar",
tags = [
"maven_coordinates=com.google.guava:guava:32.0.1-jre",
"maven_repository=https://repo1.maven.org/maven2",
"maven_sha256=bd7fa227591fb8509677d0d1122cf95158f3b8a9f45653f58281d879f6dc48c5",
"maven_url=https://repo1.maven.org/maven2/com/google/guava/guava/32.0.1-jre/guava-32.0.1-jre.jar",
],
visibility = ["//visibility:public"],
deps = [
"@maven//:com_google_code_findbugs_jsr305",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_failureaccess",
"@maven//:com_google_guava_listenablefuture",
"@maven//:com_google_j2objc_j2objc_annotations",
"@maven//:org_checkerframework_checker_qual",
],
)
Okay, now let’s query the target and see if it’s being overridden. Output trimmed for brevity.
> bazel query @maven//:com_google_guava_guava --output=build
alias(
name = "com_google_guava_guava",
visibility = ["//visibility:public"],
actual = "//override:my_guava",
)
Success! Now, anywhere in your project where you are using @maven//:com_google_guava_guava
, it will be replaced with the jar at //override:my_guava
.
WORKSPACE
If you are still using WORKSPACE
, overriding the targets is mostly the same.
The only difference is that instead of using maven.override
in the MODULE.bazel
file, you will use the override_targets
attribute on the maven_install
rule in your WORKSPACE
file.
maven_install(
name = "maven",
artifacts = [
"com.google.guava:guava:31.0.1-jre",
],
repositories = [
"https://repo.maven.apache.org/maven2",
],
override_targets = {
"com.google.guava:guava": "//override:my_guava",
},
)
The full bzlmod and WORKSPACE examples can be found here.