Migra de Maven a Bazel

Informar un problema Ver fuente Nightly · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

En esta página, se describe cómo migrar de Maven a Bazel, incluidos los requisitos previos y los pasos de instalación. Describe las diferencias entre Maven y Bazel, y proporciona un ejemplo de migración con el proyecto de Guava.

Cuando migres de cualquier herramienta de compilación a Bazel, lo mejor es que ambas herramientas se ejecuten en paralelo hasta que hayas migrado por completo tu equipo de desarrollo, tu sistema de CI y cualquier otro sistema pertinente. Puedes ejecutar Maven y Bazel en el mismo repositorio.

Antes de comenzar

  • Instala Bazel si aún no lo hiciste.
  • Si es la primera vez que usas Bazel, consulta el instructivo Introducción a Bazel: Compila Java antes de comenzar la migración. En el instructivo, se explican los conceptos, la estructura y la sintaxis de etiquetas de Bazel.

Diferencias entre Maven y Bazel

  • Maven usa archivos pom.xml de nivel superior. Bazel admite varios archivos de compilación y varios destinos por archivo BUILD, lo que permite compilaciones más incrementales que las de Maven.
  • Maven se encarga de los pasos del proceso de implementación. Bazel no automatiza la implementación.
  • Bazel te permite expresar dependencias entre idiomas.
  • A medida que agregues secciones nuevas al proyecto, es posible que debas agregar archivos BUILD nuevos con Bazel. Se recomienda agregar un archivo BUILD a cada paquete de Java nuevo.

Migra de Maven a Bazel

En los siguientes pasos, se describe cómo migrar tu proyecto a Bazel:

  1. Crea el archivo MODULE.bazel
  2. Crea un archivo BUILD
  3. Crea más archivos BUILD
  4. Compila con Bazel

Los siguientes ejemplos provienen de una migración del proyecto Guava de Maven a Bazel. El proyecto de Guava que se usa es la versión v31.1. Los ejemplos que usan Guava no explican cada paso de la migración, pero sí muestran los archivos y el contenido que se generan o agregan manualmente para la migración.

$ git clone https://github.com/google/guava.git && cd guava
$ git checkout v31.1

1. Crea el archivo MODULE.bazel

Crea un archivo llamado MODULE.bazel en la raíz de tu proyecto. Si tu proyecto no tiene dependencias externas, este archivo puede estar vacío.

Si tu proyecto depende de archivos o paquetes que no se encuentran en uno de los directorios del proyecto, especifica estas dependencias externas en el archivo MODULE.bazel. Puedes usar rules_jvm_external para administrar dependencias desde Maven. Para obtener instrucciones sobre cómo usar este conjunto de reglas, consulta el README.

Ejemplo de proyecto de Guava: dependencias externas

Puedes enumerar las dependencias externas del proyecto Guava con el conjunto de reglas rules_jvm_external.

Agrega el siguiente fragmento al archivo MODULE.bazel:

bazel_dep(name = "rules_jvm_external", version = "6.2")
maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
maven.install(
    artifacts = [
        "com.google.code.findbugs:jsr305:3.0.2",
        "com.google.errorprone:error_prone_annotations:2.11.0",
        "com.google.j2objc:j2objc-annotations:1.3",
        "org.codehaus.mojo:animal-sniffer-annotations:1.20",
        "org.checkerframework:checker-qual:3.12.0",
    ],
    repositories = [
        "https://repo1.maven.org/maven2",
    ],
)
use_repo(maven, "maven")

2. Crea un archivo BUILD

Ahora que definiste tu espacio de trabajo y enumeraste las dependencias externas (si corresponde), debes crear archivos BUILD para describir cómo se debe compilar tu proyecto. A diferencia de Maven, que usa un solo archivo pom.xml, Bazel puede usar muchos archivos BUILD para compilar un proyecto. Estos archivos especifican varios destinos de compilación, lo que permite que Bazel produzca compilaciones incrementales.

Agrega archivos BUILD por etapas. Comienza por agregar un archivo BUILD en la raíz de tu proyecto y úsalo para realizar una compilación inicial con Bazel. Luego, agrega más archivos BUILD con objetivos más específicos para definir mejor tu compilación.

  1. En el mismo directorio que tu archivo MODULE.bazel, crea un archivo de texto y nómbralo BUILD.

  2. En este archivo BUILD, usa la regla adecuada para crear un destino para compilar tu proyecto. A continuación, se incluyen algunas sugerencias:

    • Usa la regla adecuada:

      • Para compilar proyectos con un solo módulo de Maven, usa la regla java_library de la siguiente manera:

        java_library(
           name = "everything",
           srcs = glob(["src/main/java/**/*.java"]),
           resources = glob(["src/main/resources/**"]),
           deps = ["//:all-external-targets"],
        )
        
      • Para compilar proyectos con varios módulos de Maven, usa la regla java_library de la siguiente manera:

        java_library(
           name = "everything",
           srcs = glob([
                 "Module1/src/main/java/**/*.java",
                 "Module2/src/main/java/**/*.java",
                 ...
           ]),
           resources = glob([
                 "Module1/src/main/resources/**",
                 "Module2/src/main/resources/**",
                 ...
           ]),
           deps = ["//:all-external-targets"],
        )
        
      • Para compilar archivos binarios, usa la regla java_binary:

        java_binary(
           name = "everything",
           srcs = glob(["src/main/java/**/*.java"]),
           resources = glob(["src/main/resources/**"]),
           deps = ["//:all-external-targets"],
           main_class = "com.example.Main"
        )
        
      • Especifica los atributos:

        • name: Asigna un nombre significativo al destino. En los ejemplos anteriores, el destino se llama "todo".
        • srcs: Usa la expansión con comodines para enumerar todos los archivos .java de tu proyecto.
        • resources: Usa la expansión con comodines para enumerar todos los recursos de tu proyecto.
        • deps: Debes determinar qué dependencias externas necesita tu proyecto.
      • Consulta el siguiente ejemplo de este archivo BUILD de nivel superior de la migración del proyecto de Guava.

  3. Ahora que tienes un archivo BUILD en la raíz de tu proyecto, compílalo para asegurarte de que funcione. En la línea de comandos, desde el directorio de tu espacio de trabajo, usa bazel build //:everything para compilar tu proyecto con Bazel.

    El proyecto ahora se compiló correctamente con Bazel. Deberás agregar más archivos BUILD para permitir compilaciones incrementales del proyecto.

Ejemplo del proyecto de Guava: Comienza con un archivo BUILD

Cuando se migra el proyecto de Guava a Bazel, inicialmente se usa un archivo BUILD para compilar todo el proyecto. Este es el contenido del archivo BUILD inicial en el directorio del espacio de trabajo:

java_library(
    name = "everything",
    srcs = glob([
        "guava/src/**/*.java",
        "futures/failureaccess/src/**/*.java",
    ]),
    javacopts = ["-XepDisableAllChecks"],
    deps = [
        "@maven//:com_google_code_findbugs_jsr305",
        "@maven//:com_google_errorprone_error_prone_annotations",
        "@maven//:com_google_j2objc_j2objc_annotations",
        "@maven//:org_checkerframework_checker_qual",
        "@maven//:org_codehaus_mojo_animal_sniffer_annotations",
    ],
)

3. Crea más archivos BUILD (opcional)

Bazel funciona con un solo BUILD file, como viste después de completar tu primera compilación. Sin embargo, debes considerar dividir la compilación en partes más pequeñas agregando más archivos BUILD con objetivos detallados.

Varios archivos BUILD con varios destinos le darán a la compilación una mayor granularidad, lo que permitirá lo siguiente:

  • Aumento de las compilaciones incrementales del proyecto
  • mayor ejecución paralela de la compilación
  • mejor mantenimiento de la compilación para futuros usuarios
  • Control sobre la visibilidad de los destinos entre paquetes, lo que puede evitar problemas como que las bibliotecas que contienen detalles de implementación se filtren en las APIs públicas.

Sugerencias para agregar más archivos BUILD:

  • Puedes comenzar por agregar un archivo BUILD a cada paquete de Java. Comienza con los paquetes de Java que tienen la menor cantidad de dependencias y avanza hasta los paquetes con la mayor cantidad de dependencias.
  • A medida que agregues archivos BUILD y especifiques destinos, agrega estos destinos nuevos a las secciones deps de los destinos que dependen de ellos. Ten en cuenta que la función glob() no cruza los límites de los paquetes, por lo que, a medida que aumenta la cantidad de paquetes, se reduce la cantidad de archivos que coinciden con glob().
  • Cada vez que agregues un archivo BUILD a un directorio main, asegúrate de agregar un archivo BUILD al directorio test correspondiente.
  • Ten cuidado de limitar la visibilidad correctamente entre los paquetes.
  • Para simplificar la solución de errores en la configuración de los archivos BUILD, asegúrate de que el proyecto se siga compilando con Bazel a medida que agregas cada archivo de compilación. Ejecuta bazel build //... para asegurarte de que todos tus destinos se sigan compilando.

4. Compila con Bazel

Has estado compilando con Bazel a medida que agregas archivos BUILD para validar la configuración de la compilación.

Cuando tengas archivos BUILD con la granularidad deseada, puedes usar Bazel para generar todas tus compilaciones.