Skip to content

Bazel rules to resolve, fetch and manage 3rdparty JVM dependencies with support for multiple parallel versions of the same dependency. Powered by Coursier.

License

Notifications You must be signed in to change notification settings

twitter/bazel-multiversion

bazel-multiversion

Transitive Maven artifact resolution that supports multiple versions of the same 3rdparty dependency (an alternative to bazelbuild/rules_jvm_external).

Getting started

# Step 1: Clone repo
git clone https://github.com/twitter/bazel-multiversion
cd bazel-multiversion

# Step 2: Build and run code with different versions of Guava
cd multiversion-example/
bazel build tricky/...
bazel run tricky/user/src/main/scala/bincompat:bin-needs-guava24
bazel run tricky/user/src/main/scala/bincompat:bin-needs-guava29

Usage

Download GraalVM native image from https://github.com/twitter/bazel-multiversion/releases, and put multiversion in your PATH.

There are 3 ways to configure the dependencies.

BUILDish DSL

BUILDish DSL allows the configuration of dependencies using BUILD files similar to what is currently done using Pants. See multiversion-example/3rdparty/jvm/ for the examples.

To regenerate the 3rdparty/jvm_deps.bzl file, run the following inside the multiversion-example/ directory:

$ multiversion import-build --output-path=3rdparty/jvm_deps.bzl

multiversion_config

Place this at 3rdparty/jvm/BUILD:

multiversion_config(
  scala_versions = ["2.12.12"],
)

Currently only one Scala version can be specified.

jar_library

Place BUILD files under 3rdparty/jvm/com/google/guava/BUILD where com/google/guava matches the groupid of the external library:

jar_library(
  name = "guava",
  jars = [
    jar(
      org = "com.google.guava",
      name = "guava",
      rev = "29.0-jre",
    )
  ],
)

jar_library(
  name = "guava-24",
  jars = [
    jar(
      org = "com.google.guava",
      name = "guava",
      rev = "24.1.1-jre",
    ),
    jar(
      org = "org.checkerframework",
      name = "checker-compat-qual",
      rev = "2.0.0",
    )
  ],
)

For Scala libraries:

jar_library(
  name = "scalameta",
  jars = [
    scala_jar(
      org = "org.scalameta",
      name = "scalameta",
      rev = "4.0.0",
    )
  ],
)

Next, reference the artifacts in the BUILD file with their label (location of the Guava BUILD + / + name of the "target"):

scala_library(
    name="hello",
    srcs=["Hello.scala"],
    deps=[
        "@maven//:3rdparty/jvm/com/google/guava/guava",
    ],
)

Workspace setup

load("//3rdparty:jvm_deps.bzl", "jvm_deps")
jvm_deps()
load("@maven//:jvm_deps.bzl", "load_jvm_deps")
load_jvm_deps()

YAML or JSON

If you prefer to configure the dependencies in one file, create 3rdparty.yaml at the root of monorepo instead To regenerate the 3rdparty/jvm_deps.bzl file, runt the following inside the multiversion-example/ directory:

$ multiversion export --output-path=3rdparty/jvm_deps.bzl

You can also specify a different path or format for the input configuration using --input-path:

$ multiversion export --input-path=config/3rdparty.json --output-path=3rdparty/jvm_deps.bzl

Pants

$ multiversion pants-export --output-path=3rdparty/jvm_deps.bzl

Publishing to external repositories

See rules_jvm_export.

Building from source

See DEVELOP.

License

Copyright Twitter, Inc.

Licensed under the Apache License, Version 2.0