Aller au contenu

Bazel

Compilez, testez et formatez Java et Kotlin dans Bazel avec rules_elide, remplacez le builder de rules_kotlin, ou appelez elide javac et elide kotlinc comme workers persistants depuis vos propres règles.

Sur cette page

rules_elide est un module Bazel dont les règles Java et Kotlin compilent via elide javac et elide kotlinc, exécutés comme workers persistants. Il télécharge Elide lui-même ; aucun JDK ni chaîne d’outils Kotlin n’est nécessaire.

Prérequis

Version
Bazel8 ou 9, avec Bzlmod
rules_elide0.7.0
Elide1.6.0-rc.2 (par défaut)
PlateformesLinux x86_64 et arm64, macOS arm64

Installation

# 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() télécharge la version d’Elide pour l’hôte et la vérifie avec un hash épinglé ; version doit faire partie de celles que liste le module. Pour utiliser un Elide installé par vos soins :

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

Règles

Chargez-les depuis @rules_elide//elide:defs.bzl.

RègleRôle
elide_java_libraryCompile des sources .java en un JAR
elide_java_binaryBibliothèque plus un lanceur (bazel run)
elide_java_testBibliothèque plus un lanceur JUnit Platform (bazel test)
elide_kotlin_libraryCompile des sources .kt et mixtes .kt/.java
elide_kotlin_binary, elide_kotlin_testComme les variantes Java, pour Kotlin
elide_formatCible bazel run qui formate les sources sur place (Java ou Kotlin, un langage par cible)
elide_native_imageBinaire natif à partir de cibles JVM

Chaque règle de compilation renvoie un JavaInfo : les cibles java_library, kt_jvm_library et rules_jvm_external se mélangent librement dans deps. Les règles de test ont besoin de org.junit.platform:junit-platform-console-standalone dans runtime_deps.

Référence complète des attributs : documentation de rules_elide.

Exemple

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.

Workers persistants

Les règles de compilation lancent elide javac --persistent_worker et elide kotlinc --persistent_worker : un seul processus chaud par outil sert toutes les actions de compilation, accepte des requêtes concurrentes et les compile une par une. bazel shutdown les arrête.

Pour compiler chaque cible dans un nouveau processus (par exemple en exécution distante) :

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

Workers depuis vos propres règles

Sans rules_elide, n’importe quelle règle peut exécuter Elide comme worker. Bazel ajoute lui-même --persistent_worker ; la règle passe les arguments dans un fichier de paramètres :

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

Pour javac, passez ["javac", "--classpath-cache", args] afin de réutiliser d’une requête à l’autre les JAR du classpath déjà analysés. Une règle kotlinc a la même forme, sans --classpath-cache.

Garder les cibles kt_jvm_*

register_elide_kotlin_toolchain de @rules_elide//elide/kotlin:toolchain.bzl remplace le builder d’une chaîne d’outils rules_kotlin : les cibles kt_jvm_library, kt_jvm_binary et kt_jvm_test existantes compilent avec Elide sans modifier les fichiers BUILD. Les cibles avec des processeurs d’annotations reviennent au builder standard de rules_kotlin. Mise en place : shim KotlinBuilder.

OpenRewrite et requêtes de dépendances

Pour les projets dotés d’un elide.pkl, voir OpenRewrite et Index du code des dépendances. Ces commandes ne lisent ni le JavaInfo de Bazel ni son graphe de cibles, et les règles ci-dessus n’ajoutent pas de cible de réécriture ou d’index de code. Lisez la limite de la configuration du projet avant de les utiliser à côté de Bazel.

Limites

  • Windows n’est pas pris en charge.
  • elide.install n’accepte que les versions listées dans le module ; utilisez elide.use pour les autres.
  • Les plugins du compilateur Kotlin issus de JAR externes (l’attribut plugins des règles elide_kotlin_*) autres que all-open, no-arg, sam-with-receiver, assignment et Lombok échouent avec une erreur du compilateur.

Cette page vous a-t-elle aidé ?