rules_jvm_external
rules_jvm_external copied to clipboard
[bzlmod] Cross-module artifact resolution (single-version policy)
Can some documentation be included on the right way to use the module extension when rules_jvm_external is used by multiple dependencies or by a dependency and the root module?
Example dependency graphs, where "->" indicates "depends on":
- B -> A
- C -> B -> A
- C -> A and C -> B
Supposing each of A, B, and C above use the module extension to include Maven artifacts. What is the right way to configure the modules such that they share Maven artifact resolution (i.e. if both A and B include some Maven artifact X we only get one copy/version of X)?
In WORKSPACE mode, we handle this by having each project expose its list of artifacts and only having the root WORKSPACE call maven_install
.
Another way to phrase this would be "how to enforce a single-version policy for all Maven artifacts"
Concrete example of this causing build headaches yesterday:
- A has a
java_library
target with a dep from Maven that transitively depends oncom.google.guava:guava
. Dependency resolution picked up the Android version since it wasn't explicitly specified. - B depends on that library target from A and also directly depends on
com.google.guava:guava
. It uses functions that aren't available in the Android version, so it explicitly specifies the jre version.
The only workaround I've found is to ensure that all of my projects that use rules_jvm_external use the same repo name in the Maven extension. This of course results in lots of warnings, and is also only possible if I don't end up with two module deps I don't control that use different names.
The way to share artifacts is to use the same name
attribute in the tags (eg. install
and artifact
). By default, this is set to maven
, so you may not have a name
attribute on any of your tags at the moment.
When run, we aggregate all the artifacts from tags with the same name (that is, module A can contribute to dependencies that module B can use). This is needed because MODULE.bazel
files do not allow load
ing of constants, and so there's no other way to share which dependencies should be added. As you've noticed, we print a warning when we find the same name
being used in multiple repos. This is done to facilitate debugging the "where did this dep come from?" issue.
For lock files, if the root module specifies a lock file, that is the one that is used.