מעבר מ-Maven ל-Bazel

במאמר הזה נסביר איך לעבור מ-Maven אל Bazel, כולל הדרישות המוקדמות ושלבי ההתקנה. הוא מתאר את ההבדלים בין Maven לבין Bazel ומספק דוגמה להעברה באמצעות פרויקט Guaba.

בזמן המעבר מכל כלי build ל-Bazel, עדיף להפעיל את שני הכלים המקבילים בו-זמנית עד שצוות הפיתוח, מערכת ה-CI וכל מערכת רלוונטית אחרת תעברו ביניהם. אתם יכולים להריץ את Maven ואת Bazel באותו מאגר.

לפני שמתחילים

  • התקנת Bazel אם היא עדיין לא מותקנת.
  • אם אין לכם ניסיון קודם ב-Bazel, קראו את המדריך Bazel: Build Java לפני שתתחילו את ההעברה. המדריך מסביר את התפיסות, המבנה והסינונים של התוויות של בזל.

הבדלים בין Maven לבין Bazel

  • Maven משתמש ב-pom.xml קבצים ברמה העליונה. מאחר ש-Bazel תומכת במספר קובצי build ויעדים מרובים לכל קובץ ב-BUILD, כך שגרסאות build הן מצטברות יותר מ-Maven&#39.
  • Maven אחראי על השלבים של תהליך הפריסה. Bazel לא מבצעת אוטומציה של הפריסה.
  • Bazel מאפשרת לך להביע תלות בין שפות.
  • כשמוסיפים קטעים חדשים לפרויקט, עם Bazel ייתכן שתצטרכו להוסיף קובצי BUILD חדשים. השיטה המומלצת היא להוסיף קובץ BUILD לכל חבילת Java חדשה.

מעבר מ-Maven ל-Bazel

השלבים הבאים מתארים כיצד להעביר את הפרויקט שלך ל-Bazel:

  1. יצירת קובץ WORKSPACE
  2. יצירת קובץ BUILD אחד
  3. יצירה של קובצי BUILD נוספים
  4. יצירה באמצעות Bazel

הדוגמאות הבאות נובעות מהעברה של פרויקט גויאבה מ- Maven ל-Bazel. פרויקט גויאבה שבו נעשה שימוש הוא גרסה v31.1. הדוגמאות לשימוש בגוואבה לא מפורטות בכל שלב בתהליך ההעברה, אבל הן מציגות את הקבצים ואת התוכן שנוצרו או נוספו באופן ידני בהעברה.

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

1. יצירת קובץ WORKSPACE

יוצרים קובץ בשם WORKSPACE (root) של הפרויקט. אם לפרויקט אין תלויות חיצוניות, קובץ Workspace לא יכול להיות ריק.

אם הפרויקט תלוי בקבצים או בחבילות שלא נכללות באחת מהספריות של הפרויקט, יש לציין את התלות החיצוניות החיצוניות בקובץ Workspace. כדי להגדיר באופן אוטומטי תלויות חיצוניות לקובץ Workspace, משתמשים ב-rules_jvm_external. להוראות על השימוש בערכת כללים זו, קראו את README.

דוגמה לפרויקט פרויקט גויאבה: יחסי תלות חיצוניים

אפשר לציין את יחסי התלות החיצוניים של פרויקט גויאבה באמצעות הכלל rules_jvm_external.

יש להוסיף את קטע הקוד הבא לקובץ WORKSPACE:

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

RULES_JVM_EXTERNAL_TAG = "4.3"
RULES_JVM_EXTERNAL_SHA = "6274687f6fc5783b589f56a2f1ed60de3ce1f99bc4e8f9edef3de43bdf7c6e74"

http_archive(
    name = "rules_jvm_external",
    sha256 = RULES_JVM_EXTERNAL_SHA,
    strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG,
    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: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",
    ],
)

2. יצירת קובץ BUILD אחד

עכשיו, אחרי שסביבת העבודה שלכם מוגדרת ותלויות חיצוניות (אם רלוונטי), אתם צריכים ליצור BUILD קבצים כדי לתאר את אופן הבנייה של הפרויקט. בניגוד ל-Maven עם קובץ pom.xml יחיד, בזל יכולה להשתמש בקבצים רבים של BUILD כדי לבנות פרויקט. הקבצים האלה מציינים כמה יעדים לבנייה, כך ש-Bazel יכולה ליצור גרסאות מצטברות.

הוספת BUILD קבצים בשלבים. תוכלו להתחיל להוסיף קובץ BUILD לרמה הבסיסית (root) של הפרויקט ולהשתמש בו כדי ליצור גרסת build ראשונית באמצעות Bazel. לאחר מכן אפשר לצמצם את ה-build על ידי הוספה של עוד BUILD קבצים עם יעדים מפורטים יותר.

  1. באותה ספרייה של קובץ ה-WORKSPACE, תוכלו ליצור קובץ טקסט ולתת לו שם BUILD.

  2. בקובץ BUILD הזה השתמשו בכלל המתאים כדי ליצור יעד אחד כדי לבנות את הפרויקט. ריכזנו בשבילכם כמה טיפים:

    • משתמשים בכלל המתאים:

      • כדי ליצור פרויקטים עם מודול Maven יחיד, יש להשתמש בכלל java_library באופן הבא:

        java_library(
            name = "everything",
            srcs = glob(["src/main/java/**/*.java"]),
            resources = glob(["src/main/resources/**"]),
            deps = ["//:all-external-targets"],
        )
        
      • כדי ליצור פרויקטים עם מספר מודולים של Maven, יש להשתמש בכלל java_library באופן הבא:

        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"],
        )
        
      • כדי ליצור קבצים בינאריים, יש להשתמש בכלל 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"
        )
        
    • מציינים את המאפיינים:

      • name: נותנים ליעד שם משמעותי. בדוגמאות שלמעלה, היעד נקרא "everyinging."
      • srcs: משתמשים בגלובוסים כדי לרשום את כל קובצי ה-Java בפרויקט.
      • resources: באמצעות כדור הארץ כדי לפרט את כל המשאבים בפרויקט.
      • deps: צריך לקבוע אלו יחסי תלות חיצוניים צריכים להיות בפרויקט שלכם. לדוגמה, אם יצרתם רשימה של יחסי תלות חיצוניים באמצעות הכלי generate_workspace, התלויות עבור java_library הן הספריות המפורטות במאקרו generated_java_libraries.
    • בדוגמה הבאה ניתן לראות את קובץ ה-BUILD ברמה העליונה שהועבר מהפרויקט בגואבה.

  3. עכשיו יש לכם קובץ BUILD ברמה הבסיסית (root) של הפרויקט, ובנו את הפרויקט כדי לוודא שהוא פועל. בשורת הפקודה, מספריית העבודה שלך, השתמשו ב-bazel build //:everything כדי לבנות את הפרויקט שלכם עם Bazel.

    הפרויקט נבנה בהצלחה עם Bazel. יהיה עליך להוסיף עוד BUILD קבצים כדי לאפשר גרסאות מצטברות של הפרויקט.

דוגמה לפרויקט גויאבה: התחלה עם קובץ BUILD אחד

בעת העברת פרויקט הגואבה לבזאל, תחילה נעשה שימוש בקובץ BUILD אחד לבניית הפרויקט כולו. אלו התכנים של קובץ BUILD הראשוני הזה בספריית Workspace:

java_library(
    name = "everything",
    srcs = glob([
        "guava/src/**/*.java",
        "futures/failureaccess/src/**/*.java",
    ]),
    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. יצירת קובצי BUILD נוספים (אופציונלי)

מאחר ש-Bazel פועלת רק עם BUILD file אחת, כפי שראיתם אחרי שסיימתם את הבנייה הראשונה. כדאי לשקול לפצל את המבנה לחלקים קטנים יותר על ידי הוספה של עוד BUILD קבצים עם יעדים מפורטים.

קובצי BUILD מרובים עם יעדים מרובים מגדילים את רמת הפירוט, מה שמאפשר:

  • מספר גרסאות מצטברות של הפרויקט,
  • הרצה מקבילה של ה-build,
  • ניהול שוטף של ה-build עבור משתמשים עתידיים
  • שליטה על החשיפה של יעדים בין חבילות, שעלולה למנוע בעיות כגון ספריות המכילות פרטי יישום שדלפות לממשקי API ציבוריים.

טיפים להוספת BUILD קבצים:

  • אפשר להתחיל על ידי הוספת קובץ BUILD לכל חבילת Java. התחילו עם חבילות Java שיש להן את התלות הנמוכה ביותר ועובדות עד לחבילות התלויות ביותר.
  • כשמוסיפים BUILD קבצים ומציינים יעדים, יש להוסיף את היעדים החדשים לקטעים מתוך deps יעדים שתלויים בהם. חשוב לשים לב שהפונקציה glob() לא חוצה גבולות של חבילה, ולכן מספר החבילות מתרחב – glob() יתכווץ.
  • בכל פעם שמוסיפים קובץ BUILD לספרייה main, יש להוסיף קובץ BUILD לספרייה המתאימה ב-test.
  • יש להקפיד להגביל את החשיפה בצורה נכונה בין חבילות.
  • כדי לפשט את הבעיות בפתרון בעיות בהגדרת הקבצים של BUILD, צריך לוודא שהפרויקט ממשיך לפעול ב-Bazel בזמן ההוספה של כל קובץ build. מומלץ להפעיל את bazel build //... כדי לוודא שכל היעדים עדיין נוצרים.

4. בונים באמצעות Bazel

בונים באמצעות Bazel בזמן שמוסיפים BUILD קבצים לאימות ההגדרה של ה-build.

אם יש לכם BUILD קבצים ברמת הפירוט הרצויה, תוכלו להשתמש ב-Bazel כדי ליצור את כל גרסאות ה-build.