Skip to content

Bazel

Compile, test and format Java and Kotlin in Bazel with rules_elide, swap rules_kotlin's builder, or call elide javac and elide kotlinc as persistent workers from your own rules.

On this page

rules_elide is a Bazel module with Java and Kotlin rules that compile through elide javac and elide kotlinc running as persistent workers. It downloads Elide itself; no JDK or Kotlin toolchain is needed.

Requirements

Version
Bazel8 or 9, with Bzlmod
rules_elide0.7.0
Elide1.6.0-rc.2 (the default)
PlatformsLinux x86_64 and arm64, macOS arm64

Install

# MODULE.bazel
bazel_dep(name = "rules_elide", version = "0.7.0")

elide = use_extension("@rules_elide//elide:extensions.bzl", "elide")
elide.install(version = "1.6.0-rc.2")
use_repo(elide, "elide_toolchains")
register_toolchains("@elide_toolchains//:all")

elide.install() downloads the Elide release for the host and checks it against a pinned hash; version must be one the module lists. To use an Elide you installed yourself:

elide.use(local_path = "/opt/elide")

Rules

Load from @rules_elide//elide:defs.bzl.

RuleDoes
elide_java_libraryCompiles .java sources into a JAR
elide_java_binaryLibrary plus a launcher (bazel run)
elide_java_testLibrary plus a JUnit Platform launcher (bazel test)
elide_kotlin_libraryCompiles .kt and mixed .kt/.java sources
elide_kotlin_binary, elide_kotlin_testAs the Java variants, for Kotlin
elide_formatbazel run target that formats sources in place (Java or Kotlin, one per target)
elide_native_imageNative binary from JVM targets

Every compile rule returns JavaInfo, so java_library, kt_jvm_library and rules_jvm_external targets mix freely in deps. Test rules need org.junit.platform:junit-platform-console-standalone in runtime_deps.

Full attribute reference: rules_elide docs.

Example

MODULE.bazel
BUILD.bazel
src/Greeter.java
src/App.kt
src/GreeterTest.java
# MODULE.bazel
module(name = "hello")

bazel_dep(name = "rules_elide", version = "0.7.0")
bazel_dep(name = "rules_jvm_external", version = "7.1")

elide = use_extension("@rules_elide//elide:extensions.bzl", "elide")
elide.install(version = "1.6.0-rc.2")
use_repo(elide, "elide_toolchains")
register_toolchains("@elide_toolchains//:all")

maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
maven.install(
    artifacts = [
        "org.junit.jupiter:junit-jupiter-api:5.13.4",
        "org.junit.platform:junit-platform-console-standalone:1.13.4",
    ],
)
use_repo(maven, "maven")
# BUILD.bazel
load("@rules_elide//elide:defs.bzl", "elide_java_library", "elide_java_test", "elide_kotlin_binary")

elide_java_library(
    name = "greeter",
    srcs = ["src/Greeter.java"],
)

elide_kotlin_binary(
    name = "app",
    srcs = ["src/App.kt"],
    main_class = "AppKt",
    deps = [":greeter"],
)

elide_java_test(
    name = "greeter_test",
    srcs = ["src/GreeterTest.java"],
    test_class = "GreeterTest",
    runtime_deps = ["@maven//:org_junit_platform_junit_platform_console_standalone"],
    deps = [
        ":greeter",
        "@maven//:org_junit_jupiter_junit_jupiter_api",
    ],
)
bazel build //...
bazel run //:app
bazel test //:greeter_test
INFO: 35 processes: 12 internal, 16 linux-sandbox, 7 worker.
INFO: Build completed successfully, 35 total actions

Hello, Bazel

//:greeter_test                                                 PASSED in 2.0s
Executed 1 out of 1 test: 1 test passes.

Persistent workers

The compile rules run elide javac --persistent_worker and elide kotlinc --persistent_worker: one warm process per tool serves every compile action, accepting concurrent requests and compiling them one at a time. bazel shutdown stops them.

To compile each target in a new process (for example under remote execution):

bazel build --@rules_elide//elide:use_workers=false //...

Workers from your own rules

Without rules_elide, any rule can run Elide as a worker. Bazel adds --persistent_worker itself; the rule passes arguments in a parameter file:

# elide.bzl
def _elide_javac_impl(ctx):
    out = ctx.actions.declare_directory(ctx.label.name + "_classes")
    args = ctx.actions.args()
    args.add("-d", out.path)
    args.add_all(ctx.files.srcs)
    args.use_param_file("@%s", use_always = True)
    args.set_param_file_format("multiline")
    ctx.actions.run(
        executable = ctx.executable._elide,
        arguments = ["javac", args],
        inputs = ctx.files.srcs,
        outputs = [out],
        mnemonic = "ElideJavac",
        execution_requirements = {"supports-workers": "1", "supports-multiplex-workers": "1"},
    )
    return [DefaultInfo(files = depset([out]))]

elide_javac = rule(
    implementation = _elide_javac_impl,
    attrs = {
        "srcs": attr.label_list(allow_files = [".java"]),
        "_elide": attr.label(default = "//tools:elide", executable = True, cfg = "exec", allow_single_file = True),
    },
)
# BUILD.bazel
load(":elide.bzl", "elide_javac")

elide_javac(
    name = "hello",
    srcs = glob(["src/*.java"]),
)
mkdir -p tools && ln -s "$(command -v elide)" tools/elide
echo 'exports_files(["elide"])' > tools/BUILD.bazel
bazel build //:hello
Target //:hello up-to-date:
  bazel-bin/hello_classes
INFO: 2 processes: 1 internal, 1 worker.

For javac, pass ["javac", "--classpath-cache", args] to reuse parsed classpath JARs between requests. A kotlinc rule takes the same form, without --classpath-cache.

Keep kt_jvm_* targets

register_elide_kotlin_toolchain from @rules_elide//elide/kotlin:toolchain.bzl replaces the builder of a rules_kotlin toolchain, so existing kt_jvm_library, kt_jvm_binary and kt_jvm_test targets compile with Elide without BUILD changes. Targets with annotation processors fall back to the stock rules_kotlin builder. Setup: KotlinBuilder shim.

OpenRewrite and dependency queries

For projects with an elide.pkl, see OpenRewrite and Dependency code index. These commands do not consume Bazel’s JavaInfo or its target graph, and the rules listed above do not add a rewrite or code-index target. See the project setup boundary before using them alongside Bazel.

Limits

  • Windows is not supported.
  • elide.install accepts only versions listed in the module; use elide.use for others.
  • Kotlin compiler plugins from external JARs (the plugins attribute of elide_kotlin_* rules) other than all-open, no-arg, sam-with-receiver, assignment and Lombok fail with a compiler error.

Was this page helpful?