rules_jvm_external icon indicating copy to clipboard operation
rules_jvm_external copied to clipboard

[bzlmod] Cross-module artifact resolution (single-version policy)

Open SanjayVas opened this issue 1 year ago • 3 comments

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":

  1. B -> A
  2. C -> B -> A
  3. 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.

SanjayVas avatar Nov 21 '23 00:11 SanjayVas

Another way to phrase this would be "how to enforce a single-version policy for all Maven artifacts"

SanjayVas avatar Nov 22 '23 20:11 SanjayVas

Concrete example of this causing build headaches yesterday:

  • A has a java_library target with a dep from Maven that transitively depends on com.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.

SanjayVas avatar Dec 21 '23 19:12 SanjayVas

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 loading 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.

shs96c avatar Mar 01 '24 11:03 shs96c