Von Maven zu Bazel migrieren

Auf dieser Seite wird die Migration von Maven zu Bazel beschrieben, einschließlich der Voraussetzungen und Installationsschritte. Es beschreibt die Unterschiede zwischen Maven und Bazel und enthält ein Migrationsbeispiel mit dem Guava-Projekt.

Bei der Migration von einem Build-Tool zu Bazel sollten Sie beide Build-Tools parallel ausführen, bis Sie Ihr Entwicklungsteam, das CI-System und alle anderen relevanten Systeme vollständig migriert haben. Sie können Maven und Bazel im selben Repository ausführen.

Hinweis

Unterschiede zwischen Maven und Bazel

  • Maven verwendet die pom.xml-Datei(en) der obersten Ebene. Bazel unterstützt mehrere Build-Dateien und mehrere Ziele pro BUILD-Datei. Dadurch sind Builds möglich, die mehr sind als Mavens.
  • Maven übernimmt während des Bereitstellungsprozesses verschiedene Schritte. Bazel automatisiert die Bereitstellung nicht.
  • Mit Bazel können Sie Abhängigkeiten zwischen Sprachen ausdrücken.
  • Wenn Sie dem Projekt neue Abschnitte hinzufügen, müssen Sie mit Bazel möglicherweise neue BUILD-Dateien hinzufügen. Es empfiehlt sich, jedem neuen Java-Paket eine BUILD-Datei hinzuzufügen.

Von Maven zu Bazel migrieren

Mit den folgenden Schritten können Sie ein Projekt zu Bazel migrieren:

  1. WORKSPACE-Datei erstellen
  2. Eine BUILD-Datei erstellen
  3. Weitere BUILD-Dateien erstellen
  4. Mit Bazel erstellen

Die folgenden Beispiele stammen aus einer Migration des Guava-Projekts von Maven zu Bazel. Das verwendete Guava-Projekt ist Version 22.0. Die Beispiele mit Guava führen nicht jeden Schritt der Migration durch. Sie zeigen jedoch die Dateien und Inhalte an, die für die Migration manuell erstellt oder hinzugefügt werden.

1. WORKSPACE-Datei erstellen

Erstellen Sie im Stammverzeichnis Ihres Projekts eine Datei mit dem Namen WORKSPACE. Wenn Ihr Projekt keine externen Abhängigkeiten hat, kann die Arbeitsbereichsdatei leer sein.

Wenn Ihr Projekt von Dateien oder Paketen abhängig ist, die sich nicht in einem der Projektverzeichnisse befinden, geben Sie diese externen Abhängigkeiten in der Arbeitsbereichsdatei an. Verwenden Sie rules_jvm_external, um das Auflisten externer Abhängigkeiten für die Arbeitsbereichsdatei zu automatisieren. Eine Anleitung zum Verwenden dieses Regelsatzes finden Sie in der README-Datei.

Beispiel für ein Guava-Projekt: externe Abhängigkeiten

Sie können die externen Abhängigkeiten des Guava-Projekts mit dem Regelsatz rules_jvm_external auflisten.

Fügen Sie der Datei WORKSPACE das folgende Snippet hinzu:

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

RULES_JVM_EXTERNAL_TAG = "2.8"
RULES_JVM_EXTERNAL_SHA = "79c9850690d7614ecdb72d68394f994fef7534b292c4867ce5e7dec0aa7bdfad"

http_archive(
    name = "rules_jvm_external",
    strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG,
    sha256 = RULES_JVM_EXTERNAL_SHA,
    url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG,
)

load("@rules_jvm_external//:defs.bzl", "maven_install")

maven_install(
    artifacts = [
        "com.google.code.findbugs:jsr305:1.3.9",
        "com.google.errorprone:error_prone_annotations:2.0.18",
        "com.google.j2objc:j2objc-annotations:1.1",
    ],
    repositories = [
        "https://repo1.maven.org/maven2",
    ],
)

2. BUILD-Datei erstellen

Nachdem Sie den Arbeitsbereich definiert und externe Abhängigkeiten (falls zutreffend) aufgeführt haben, müssen Sie BUILD-Dateien erstellen, um die Erstellung Ihres Projekts zu beschreiben. Im Gegensatz zu Maven mit einer einzigen pom.xml-Datei kann Bazel viele BUILD-Dateien verwenden, um ein Projekt zu erstellen. In diesen Dateien sind mehrere Build-Ziele angegeben, mit denen Jenkins inkrementelle Builds erstellen kann.

Fügen Sie die BUILD-Dateien stufenweise hinzu. Fügen Sie zuerst eine BUILD-Datei im Stammverzeichnis Ihres Projekts hinzu und verwenden Sie sie zum Erstellen eines ersten Builds mit Bazel. Anschließend optimieren Sie den Build, indem Sie weitere BUILD-Dateien mit detaillierteren Zielen hinzufügen.

  1. Erstellen Sie im selben Verzeichnis wie Ihre Datei WORKSPACE eine Textdatei mit dem Namen BUILD.

  2. Verwenden Sie in dieser Datei BUILD die entsprechende Regel, um ein Ziel für das Projekt zu erstellen. Hier einige Tipps:

    • Verwenden Sie die entsprechende Regel:

      • Verwenden Sie die Regel java_library so, um Projekte mit einem einzelnen Maven-Modul zu erstellen:

        java_library(
            name = "everything",
            srcs = glob(["src/main/java/**/*.java"]),
            resources = glob(["src/main/resources/**"]),
            deps = ["//:all-external-targets"],
        )
        
      • Verwenden Sie die Regel java_library so, um Projekte mit mehreren Maven-Modulen zu erstellen:

        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"],
        )
        
      • Verwenden Sie die Regel java_binary, um Binärdateien zu erstellen:

        java_binary(
            name = "everything",
            srcs = glob(["src/main/java/**/*.java"]),
            resources = glob(["src/main/resources/**"]),
            deps = ["//:all-external-targets"],
            main_class = "com.example.Main"
        )
        
    • Geben Sie die Attribute an:

      • name: Geben Sie dem Ziel einen aussagekräftigen Namen. In den obigen Beispielen wird das Ziel als "alles" bezeichnet.
      • srcs: Verwenden Sie Globbing, um alle Java-Dateien in Ihrem Projekt aufzulisten.
      • resources: Verwenden Sie Globing, um alle Ressourcen in Ihrem Projekt aufzulisten.
      • deps: Sie müssen ermitteln, welche externen Abhängigkeiten Ihr Projekt benötigt. Wenn Sie beispielsweise mit dem Tool generate_workspace eine Liste externer Abhängigkeiten generiert haben, sind die Abhängigkeiten für java_library die Bibliotheken, die im Makro generated_java_libraries aufgeführt sind.
    • Sehen Sie sich das Beispiel dieser BUILD-Datei der obersten Ebene aus der Migration des Guava-Projekts an.

  3. Ihre BUILD-Datei befindet sich im Stammverzeichnis Ihres Projekts. Erstellen Sie daher das Projekt, um zu prüfen, ob es funktioniert. Verwenden Sie in der Befehlszeile aus Ihrem Arbeitsbereichverzeichnis bazel build //:everything, um Ihr Projekt mit Bazel zu erstellen.

    Das Projekt wurde jetzt mit Bazel erstellt. Sie müssen weitere BUILD-Dateien hinzufügen, um inkrementelle Builds des Projekts zuzulassen.

Beispiel für ein Guava-Projekt: mit einer BUILD-Datei beginnen

Bei der Migration des Guava-Projekts zu Bazel wird anfangs eine BUILD-Datei zum Erstellen des gesamten Projekts verwendet. Hier ist der Inhalt dieser ersten BUILD-Datei im Arbeitsbereichsverzeichnis:

java_library(
    name = "everything",
    srcs = glob(["guava/src/**/*.java"]),
    deps = [
      "@maven//:com_google_code_findbugs_jsr305",
      "@maven//:com_google_errorprone_error_prone_annotations",
      "@maven//:com_google_j2objc_j2objc_annotations"
    ],
)

3. Weitere BUILD-Dateien erstellen (optional)

Bazel funktioniert nur mit einer BUILD file, wie Sie gesehen haben, nachdem Ihr erster Build abgeschlossen wurde. Sie können den Build dennoch in kleinere Blöcke aufteilen, indem Sie weitere BUILD-Dateien mit detaillierten Zielen hinzufügen.

Mehrere BUILD-Dateien mit mehreren Zielen erhöhen den Detaillierungsgrad, was Folgendes ermöglicht:

  • erhöhte inkrementelle Builds des Projekts
  • erhöhte parallele Ausführung des Builds
  • Bessere Verwaltbarkeit des Builds für zukünftige Nutzer
  • Kontrolle über die Sichtbarkeit von Zielen zwischen Paketen, die Probleme verhindern können, wie beispielsweise Bibliotheken, die Implementierungsdetails in öffentliche APIs enthalten.

Tipps zum Hinzufügen weiterer BUILD-Dateien:

  • Sie können jedem Java-Paket zuerst eine BUILD-Datei hinzufügen. Beginnen Sie mit Java-Paketen mit den wenigsten Abhängigkeiten und arbeiten Sie bis zu Paketen mit den meisten Abhängigkeiten.
  • Wenn Sie BUILD-Dateien hinzufügen und Ziele angeben, fügen Sie diese neuen Ziele den deps-Abschnitten der Ziele hinzu, die davon abhängen. Die Funktion glob() überschreitet keine Paketgrenzen. Wenn die Anzahl der Pakete zunimmt, werden die mit glob() übereinstimmenden Dateien verkleinert.
  • Achten Sie darauf, dass Sie jedes Mal, wenn Sie eine BUILD-Datei einem main-Verzeichnis hinzufügen, eine BUILD-Datei dem entsprechenden test-Verzeichnis hinzufügen.
  • Sorge dafür, dass die Sichtbarkeit zwischen den Paketen nicht eingeschränkt wird.
  • Achten Sie darauf, dass das Projekt weiterhin mit Bazel erstellt wird, wenn Sie jede Build-Datei hinzufügen, um die Fehlerbehebung bei der Einrichtung von BUILD-Dateien zu vereinfachen. Führen Sie bazel build //... aus, damit alle Ihre Ziele weiterhin erstellt werden.

4. Mit Bazel erstellen

Sie haben mit Bazel erstellt, während Sie BUILD-Dateien hinzufügen, um die Einrichtung des Builds zu validieren.

Wenn Sie BUILD-Dateien mit der gewünschten Granularität haben, können Sie mit Bazel alle Ihre Builds erstellen.