En esta página, se incluyen recursos que te ayudan a usar Bazel con proyectos de Java. Se vincula a un instructivo, reglas de compilación y otra información específica para compilar proyectos de Java con Bazel.
Trabaja con Bazel
Los siguientes recursos te ayudarán a trabajar con Bazel en proyectos de Java:
Migración a Bazel
Si actualmente compilas tus proyectos de Java con Maven, sigue los pasos de la guía de migración para comenzar a compilar tus proyectos de Maven con Bazel:
Versiones de Java
Existen dos versiones relevantes de Java que se establecen con marcas de configuración:
- La versión de los archivos fuente en el repositorio
- La versión del entorno de ejecución de Java que se usa para ejecutar el código y probarlo
Cómo configurar la versión del código fuente en tu repositorio
Sin una configuración adicional, Bazel supone que todos los archivos fuente de Java del repositorio están escritos en una sola versión de Java. Para especificar la versión de las fuentes en el repositorio, agrega build --java_language_version={ver}
al archivo .bazelrc
, donde {ver}
es, por ejemplo, 11
. Los propietarios de repositorios de Bazel deben establecer esta marca para que Bazel y sus usuarios puedan hacer referencia al número de versión de Java del código fuente. Para obtener más detalles, consulta Marca de versión del lenguaje Java.
Cómo configurar la JVM que se usa para ejecutar y probar el código
Bazel usa un JDK para la compilación y otra JVM para ejecutar y probar el código.
De forma predeterminada, Bazel compila el código con un JDK que descarga y ejecuta y prueba el código con la JVM instalada en la máquina local. Bazel busca la JVM con JAVA_HOME
o la ruta.
Los archivos binarios resultantes son compatibles con la JVM instalada de forma local en las bibliotecas del sistema, lo que significa que dependen de lo que esté instalado en la máquina.
Para configurar la JVM que se usa para la ejecución y las pruebas, usa la marca --java_runtime_version
. El valor predeterminado es local_jdk
.
Compilación y pruebas herméticas
Para crear una compilación hermética, puedes usar la marca de línea de comandos --java_runtime_version=remotejdk_11
. El código se compila, ejecuta y prueba en la JVM descargada desde un repositorio remoto. Para obtener más detalles, consulta Marca de versión del entorno de ejecución de Java.
Configura la compilación y la ejecución de herramientas de compilación en Java
Hay un segundo par de JDK y JVM que se usan para compilar y ejecutar herramientas, que se utilizan en el proceso de compilación, pero no en los resultados de la compilación. Ese JDK y esa JVM se controlan con --tool_java_language_version
y --tool_java_runtime_version
. Los valores predeterminados son 11
y remotejdk_11
, respectivamente.
Compilación con el JDK instalado de forma local
De forma predeterminada, Bazel compila con el JDK remoto, ya que anula los elementos internos del JDK. Los conjuntos de herramientas de compilación que usan el JDK instalado de forma local están configurados, pero no se usan.
Para compilar con el JDK instalado localmente, es decir, usar las cadenas de herramientas de compilación para el JDK local, usa la marca adicional --extra_toolchains=@local_jdk//:all
. Sin embargo, ten en cuenta que esto podría no funcionar en JDK de proveedores arbitrarios.
Para obtener más detalles, consulta cómo configurar cadenas de herramientas de Java.
Prácticas recomendadas
Además de las prácticas recomendadas generales de Bazel, a continuación se incluyen las prácticas recomendadas específicas para proyectos de Java.
Estructura del directorio
Prefiere el diseño de directorio estándar de Maven (fuentes en src/main/java
, pruebas en src/test/java
).
Archivos BUILD
Sigue estos lineamientos cuando crees tus archivos BUILD
:
Usa un archivo
BUILD
por directorio que contenga fuentes de Java, ya que esto mejora el rendimiento de la compilación.Cada archivo
BUILD
debe contener una reglajava_library
que se vea de la siguiente manera:java_library( name = "directory-name", srcs = glob(["*.java"]), deps = [...], )
El nombre de la biblioteca debe ser el nombre del directorio que contiene el archivo
BUILD
. Esto hace que la etiqueta de la biblioteca sea más corta, es decir, que se use"//package"
en lugar de"//package:package"
.Las fuentes deben ser un
glob
no recursivo de todos los archivos Java del directorio.Las pruebas deben estar en un directorio coincidente en
src/test
y depender de esta biblioteca.
Cómo crear reglas nuevas para compilaciones avanzadas de Java
Nota: La creación de reglas nuevas es para situaciones avanzadas de compilación y prueba. No lo necesitas para comenzar a usar Bazel.
Los siguientes módulos, fragmentos de configuración y proveedores te ayudarán a extender las capacidades de Bazel cuando compiles tus proyectos de Java:
- Módulo principal de Java:
java_common
- Proveedor principal de Java:
JavaInfo
- Fragmento de configuración:
java
Otros módulos:
Configura las cadenas de herramientas de Java
Bazel usa dos tipos de cadenas de herramientas de Java:
- Ejecución: Se usa para ejecutar y probar archivos binarios de Java. Se controla con la marca --java_runtime_version
.
- Compilación: Se usa para compilar fuentes de Java. Se controla con la marca --java_language_version
.
Configura cadenas de herramientas de ejecución adicionales
La cadena de herramientas de ejecución es la JVM, ya sea local o de un repositorio, con información adicional sobre su versión, sistema operativo y arquitectura de CPU.
Las cadenas de herramientas de ejecución de Java se pueden agregar con las reglas de repositorios local_java_repository
o remote_java_repository
en una extensión de módulo. Agregar la regla hace que la JVM esté disponible con una marca. Cuando se proporcionan varias definiciones para el mismo sistema operativo y la misma arquitectura de CPU, se usa la primera.
Ejemplo de configuración de JVM local:
load("@rules_java//toolchains:local_java_repository.bzl", "local_java_repository")
local_java_repository(
name = "additionaljdk", # Can be used with --java_runtime_version=additionaljdk, --java_runtime_version=11 or --java_runtime_version=additionaljdk_11
version = 11, # Optional, if not set it is autodetected
java_home = "/usr/lib/jdk-15/", # Path to directory containing bin/java
)
Ejemplo de configuración de JVM remota:
load("@rules_java//toolchains:remote_java_repository.bzl", "remote_java_repository")
remote_java_repository(
name = "openjdk_canary_linux_arm",
prefix = "openjdk_canary", # Can be used with --java_runtime_version=openjdk_canary_11
version = "11", # or --java_runtime_version=11
target_compatible_with = [ # Specifies constraints this JVM is compatible with
"@platforms//cpu:arm",
"@platforms//os:linux",
],
urls = ..., # Other parameters are from http_repository rule.
sha256 = ...,
strip_prefix = ...
)
Cómo configurar cadenas de herramientas de compilación adicionales
La cadena de herramientas de compilación se compone del JDK y de varias herramientas que Bazel usa durante la compilación y que proporcionan funciones adicionales, como Error Prone, dependencias estrictas de Java, compilación de encabezados, desazucarado de Android, instrumentación de cobertura y control de genclass para IDEs.
JavaBuilder es una herramienta incluida en Bazel que ejecuta la compilación y proporciona las funciones mencionadas anteriormente. La compilación real se ejecuta con el compilador interno del JDK. El JDK que se usa para la compilación se especifica con el atributo java_runtime
de la cadena de herramientas.
Bazel anula algunos elementos internos del JDK. En el caso de las versiones de JDK superiores a 9, los módulos java.compiler
y jdk.compiler
se parchean con la marca --patch_module
del JDK. En el caso de la versión 8 del JDK, el compilador de Java se parchea con la marca -Xbootclasspath
.
VanillaJavaBuilder es una segunda implementación de JavaBuilder que no modifica el compilador interno del JDK y no tiene ninguna de las funciones adicionales. Ninguna de las cadenas de herramientas integradas usa VanillaJavaBuilder.
Además de JavaBuilder, Bazel usa varias otras herramientas durante la compilación.
La herramienta ijar
procesa archivos jar
para quitar todo, excepto las firmas de llamadas. Los archivos .jar resultantes se denominan archivos .jar de encabezado. Se utilizan para mejorar la incrementalidad de la compilación, ya que solo se vuelven a compilar los elementos dependientes posteriores cuando cambia el cuerpo de una función.
La herramienta singlejar
empaqueta varios archivos jar
en uno solo.
La herramienta genclass
posprocesa el resultado de una compilación de Java y produce un jar
que contiene solo los archivos de clase para las fuentes que generaron los procesadores de anotaciones.
La herramienta JacocoRunner
ejecuta Jacoco en archivos instrumentados y genera resultados en formato LCOV.
La herramienta TestRunner
ejecuta pruebas de JUnit 4 en un entorno controlado.
Puedes reconfigurar la compilación agregando la macro default_java_toolchain
a un archivo BUILD
y registrándola agregando la regla register_toolchains
al archivo MODULE.bazel
o usando la marca --extra_toolchains
.
La cadena de herramientas solo se usa cuando el atributo source_version
coincide con el valor especificado por la marca --java_language_version
.
Ejemplo de configuración de la cadena de herramientas:
load(
"@rules_java//toolchains:default_java_toolchain.bzl",
"default_java_toolchain", "DEFAULT_TOOLCHAIN_CONFIGURATION", "BASE_JDK9_JVM_OPTS", "DEFAULT_JAVACOPTS"
)
default_java_toolchain(
name = "repository_default_toolchain",
configuration = DEFAULT_TOOLCHAIN_CONFIGURATION, # One of predefined configurations
# Other parameters are from java_toolchain rule:
java_runtime = "@rules_java//toolchains:remote_jdk11", # JDK to use for compilation and toolchain's tools execution
jvm_opts = BASE_JDK9_JVM_OPTS + ["--enable_preview"], # Additional JDK options
javacopts = DEFAULT_JAVACOPTS + ["--enable_preview"], # Additional javac options
source_version = "9",
)
que se puede usar con --extra_toolchains=//:repository_default_toolchain_definition
o agregando register_toolchains("//:repository_default_toolchain_definition")
al espacio de trabajo.
Configuraciones predefinidas:
DEFAULT_TOOLCHAIN_CONFIGURATION
: Todas las funciones, admite versiones de JDK >= 9VANILLA_TOOLCHAIN_CONFIGURATION
: No hay funciones adicionales y admite JDK de proveedores arbitrarios.PREBUILT_TOOLCHAIN_CONFIGURATION
: Igual que el valor predeterminado, pero solo usa herramientas prediseñadas (ijar
,singlejar
)NONPREBUILT_TOOLCHAIN_CONFIGURATION
: Es igual que el valor predeterminado, pero todas las herramientas se compilan a partir de fuentes (esto puede ser útil en sistemas operativos con libc diferente).
Cómo configurar marcas de JVM y del compilador de Java
Puedes configurar las marcas de JVM y javac con marcas o con atributos default_java_toolchain
.
Las marcas relevantes son --jvmopt
, --host_jvmopt
, --javacopt
y --host_javacopt
.
Los atributos default_java_toolchain
relevantes son javacopts
, jvm_opts
, javabuilder_jvm_opts
y turbine_jvm_opts
.
Configuración de marcas del compilador de Java específicas del paquete
Puedes configurar diferentes marcas del compilador de Java para archivos fuente específicos con el atributo package_configuration
de default_java_toolchain
.
Consulta el siguiente ejemplo.
load("@rules_java//toolchains:default_java_toolchain.bzl", "default_java_toolchain")
# This is a convenience macro that inherits values from Bazel's default java_toolchain
default_java_toolchain(
name = "toolchain",
package_configuration = [
":error_prone",
],
visibility = ["//visibility:public"],
)
# This associates a set of javac flags with a set of packages
java_package_configuration(
name = "error_prone",
javacopts = [
"-Xep:MissingOverride:ERROR",
],
packages = ["error_prone_packages"],
)
# This is a regular package_group, which is used to specify a set of packages to apply flags to
package_group(
name = "error_prone_packages",
packages = [
"//foo/...",
"-//foo/bar/...", # this is an exclusion
],
)
Varias versiones del código fuente de Java en un solo repositorio
Bazel solo admite la compilación de una sola versión de las fuentes de Java en una compilación. Esto significa que, cuando se compila una prueba o una aplicación en Java, todas las dependencias se compilan con la misma versión de Java.
Sin embargo, se pueden ejecutar compilaciones separadas con diferentes marcas.
Para facilitar el uso de diferentes marcas, los conjuntos de marcas para una versión específica se pueden agrupar con las configuraciones de .bazelrc
:
build:java8 --java_language_version=8
build:java8 --java_runtime_version=local_jdk_8
build:java11 --java_language_version=11
build:java11 --java_runtime_version=remotejdk_11
Estas configuraciones se pueden usar con la marca --config
, por ejemplo, bazel test --config=java11 //:java11_test
.