ג'אווה ובזל

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

עבודה עם Bazel

מקורות המידע הבאים יעזרו לך לעבוד עם Bazel בפרויקטים של Java:

העברה ל-Bazel

אם אתם יוצרים כרגע את הפרויקטים שלכם ב-Java באמצעות Maven, בצעו את השלבים במדריך ההעברה כדי להתחיל לבנות את הפרויקטים של Maven באמצעות Bazel:

גרסאות Java

יש שתי גרסאות רלוונטיות של Java שהוגדרו באמצעות התרעות הגדרה:

  • גרסת קובצי המקור במאגר
  • הגרסה של זמן הריצה של Java המשמשת להפעלת הקוד ולבדיקתו

הגדרת הגרסה של קוד המקור במאגר שלך

ללא תצורה נוספת, Bazel מניחה שכל קובצי המקור של Java במאגר נכתבים בגרסת Java יחידה. כדי לציין את גרסת המקורות במאגר יש להוסיף קובץ build --java_language_version={ver} לקובץ .bazelrc, שבו {ver} הוא לדוגמה 11. לבעלי מאגר ב-Bazel יש להגדיר את הדגל הזה כך ש-Bazel והמשתמשים שלה יוכלו להפנות אל קוד המקור של JavaScript. פרטים נוספים זמינים במאמר סימון גרסה של שפת Java.

הגדרת ה-JVM המשמשת להפעלה ולבדיקה של הקוד

ה-Bazel משתמש ב-JDK אחד לצורך הידור וב-JVM אחר כדי להפעיל ולבדוק את הקוד.

כברירת מחדל, Bazel מפיק את הקוד באמצעות JDK שהורדת, והוא מפעיל ובודק את הקוד באמצעות JVM המותקנת במחשב המקומי. Bazel מחפשת את ה-JVM באמצעות JAVA_HOME או נתיב.

הקבצים הבינאריים המתקבלים תואמים ל-JVM שהותקנו באופן מקומי בספריות המערכת. כלומר, הקבצים הבינאריים המתקבלים תלויים במה שמותקן במכונה.

כדי להגדיר את ה-JVM למטרות ביצוע ובדיקה, יש להשתמש בסימון --java_runtime_version. ערך ברירת המחדל הוא local_jdk.

בדיקות הידור ואוסף

כדי ליצור הידור קומי, אפשר להשתמש בסימון שורת הפקודה --java_runtime_version=remotejdk_11. הקוד מורכב עבור, מתבצעת ונבדק ב-JVM שהורדתם ממאגר מרוחק. פרטים נוספים זמינים במאמר סימון גרסה של זמן ריצה של Java.

הגדרת הידור והפעלה של כלי build ב-Java

יש זוג שני של JDK ו-JVM המשמשים לבניית כלים ולביצועם. הם משמשים בתהליך ה-build, אבל לא מופיעים בתוצאות ה-build. ה-JDK וה-JVM שולטים באמצעות --tool_java_language_version ו---tool_java_runtime_version. ערכי ברירת המחדל הם 11 ו-remotejdk_11, בהתאם.

הידור באמצעות JDK מותקן באופן מקומי

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

כדי להדר בהתאם ל-JDK שמותקנים באופן מקומי, נעשה שימוש בערכות הכלים לאיסוף הידור מקומי (JDK), יש להשתמש בסימון נוסף --extra_toolchains=@local_jdk//:all. עם זאת, חשוב לזכור שייתכן שהשיטה הזו לא תפעל ב-JDK של ספקים שרירותיים.

לפרטים נוספים, אפשר לעיין בהגדרת ארגזי כלים של Java.

שיטות מומלצות

בנוסף לשיטות המומלצות של Bazel, יש שיטות מומלצות לפרויקטים ב-Java.

מבנה הספרייה

העדפת פריסת ספרייה רגילה של Maven&#39 (מקורות מתחת ל-src/main/java, בדיקות בקטע src/test/java).

קובצי BUILD

כשיוצרים את קובצי BUILD, צריך לפעול לפי ההנחיות הבאות:

  • יש להשתמש בקובץ אחד (BUILD) לכל ספרייה שמכילה מקורות Java, כי זה משפר את ביצועי ה-build.

  • כל קובץ BUILD צריך להכיל כלל java_library אחד שנראה כך:

    java_library(
        name = "directory-name",
        srcs = glob(["*.java"]),
        deps = [...],
    )
    
  • שם הספרייה צריך להיות השם של הספרייה שמכילה את קובץ BUILD. כך הספרייה של הספרייה תהיה קצרה יותר, כלומר "//package" במקום "//package:package".

  • המקורות צריכים להיות glob לא חוזרים על כל קובצי Java שבספרייה.

  • הבדיקות צריכות להיות בספרייה תואמת עד src/test, והן תלויות בספרייה הזו.

יצירת כללים חדשים לגרסאות מתקדמות של Java

הערה: יצירת כללים חדשים מיועדת לתרחישים מתקדמים של בנייה ובדיקה. אין צורך בתחילת העבודה עם Bazel.

המודולים, מקטעי התצורה והספקים הבאים יעזרו לך להרחיב את היכולות של Bazel' במהלך הבנייה של פרויקטי ה-Java:

הגדרת ארגזי הכלים של Java

Bazel משתמשת בשני סוגים של ערכות כלים של Java: - הפעלה, משמשת לביצוע ולבדיקה של קבצים בינאריים של Java, בשליטה עם סימון --java_runtime_version, הידור, משמש להדר מקורות Java, בשליטה עם סימון --java_language_version

הגדרת ערכות כלים נוספות להפעלה

כלי הביצוע הוא ה-JVM, מקומי או ממאגר, עם מידע נוסף על הגרסה, מערכת ההפעלה ומבנה המעבד (CPU).

ניתן להוסיף ערכות כלים להפעלת Java באמצעות כללים של local_java_repository או remote_java_repository בקובץ WORKSPACE. הוספת הכלל מאפשרת ל-JVM להשתמש בסימון. כאשר כמה הגדרות עבור אותה מערכת הפעלה וארכיטקטורה של יחידת עיבוד מרכזית (CPU) ניתנות, ייעשה שימוש בהגדרה הראשונה.

הגדרה לדוגמה של JVM מקומית:

load("@bazel_tools//tools/jdk: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
)

הגדרה לדוגמה של JVM מרחוק:

load("@bazel_tools//tools/jdk: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 = ...
)

הגדרת ערכות נוספות של אוספים

אוסף הכלים מורכב מ-JDK ומכלים רבים שבהם משתמשת חברת Bazel במהלך ההידור, ומספקת תכונות נוספות כמו: "שגיאה", "פרוטה", "תלויות ב-Java מחמיר", הידור של כותרת, ניפוי באגים ב-Android, אינסטרומנטת כיסוי וטיפול בדורות כלליים.

JavaBuilder הוא כלי משולב ב-Bazel שמפעיל אוסף, ומספק את התכונות שצוינו. העריכה בפועל מתבצעת באמצעות המהדר הפנימי על ידי JDK. ה-JDK המשמש לאיסוף מצוין באמצעות המאפיין java_runtime של כלי הכלים.

Bazel מבטלת חלק מהשינויים הפנימיים מסוג JDK. במקרה של גרסת JDK > 9, java.compiler ומודולים של jdk.compiler תוקנו באמצעות הסימון JDK' --patch_module. במקרה של JDK גרסה 8, המהדר של Java נמחק באמצעות התכונה הניסיונית -Xbootclasspath.

VanillaJavaBuilder הוא הטמעה שנייה של JavaBuilder, שאינה משנה את המהדר הפנימי של JDK' ואינה כוללת תכונות נוספות. לא ניתן להשתמש ב-VanillaJavaBuilder בכל שרשרת של כלים.

בנוסף ל-JavaBuilder, Bazel משתמשת במספר כלים נוספים במהלך ההידור.

הכלי ijar מעבד jar קבצים כדי להסיר הכול, למעט החתימות של השיחות. הצנצנות המתקבלות נקראות צנצנות כותרת. הם משמשים לשיפור ההצטברות של הידור על ידי קיבוץ מחדש של התלויים במורד הזרם רק כאשר גוף הפונקציה משתנה.

הכלי singlejar משלב מספר קבצים של jar בקובץ אחד.

הכלי genclass מעבד לאחר העיבוד את הפלט של אוסף Java, ומייצר jar שמכיל רק את קובצי הכיתה עבור מקורות שנוצרו על ידי מעבדי הערות.

הכלי JacocoRunner מריץ את Jacoco על הקבצים האינסטרומנטליים והפלט המתקבלים בפורמט LCOV.

הכלי TestRunner מבצע בדיקות JUNIT 4 בסביבה מבוקרת.

אפשר להגדיר מחדש את האוסף על ידי הוספת מאקרו default_java_toolchain לקובץ BUILD ורישום שלו על ידי הוספת כלל register_toolchains לקובץ WORKSPACE או שימוש בסימון --extra_toolchains.

משתמשים בכלי הכלים רק כאשר המאפיין source_version תואם לערך שצוין בסימון --java_language_version.

דוגמה לתצורה של ערכת כלים:

load(
  "@bazel_tools//tools/jdk: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 = "@bazel_tools//tools/jdk: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",
)

אפשר להשתמש ב---extra_toolchains=//:repository_default_toolchain_definition או בהוספת register_toolchains("//:repository_default_toolchain_definition") לסביבת העבודה.

תצורות מוגדרות מראש:

  • DEFAULT_TOOLCHAIN_CONFIGURATION: כל התכונות, תמיכה בגרסאות JDK > 9
  • VANILLA_TOOLCHAIN_CONFIGURATION: אין תכונות נוספות, שתומכות ב-JDK של ספקים שרירותיים.
  • PREBUILT_TOOLCHAIN_CONFIGURATION: זהה כברירת המחדל, אבל משתמשים רק בכלים שנבנו מראש (ijar, singlejar)
  • NONPREBUILT_TOOLCHAIN_CONFIGURATION: זהה לברירת המחדל, אבל כל הכלים בנויים ממקורות שונים (פעולה זו יכולה להיות שימושית במערכת הפעלה עם רישיון אחר)

הגדרת התרעות של מהדר JVM ו-Java

אפשר להגדיר התרעות מסוג JVM ו-JavaScript עם סימונים או באמצעות מאפיינים של default_java_toolchain.

הסימונים הרלוונטיים הם --jvmopt, --host_jvmopt, --javacopt וגם --host_javacopt.

המאפיינים הרלוונטיים של default_java_toolchain הם javacopts, jvm_opts, javabuilder_jvm_opts וגם turbine_jvm_opts.

הגדרת מהדר

ניתן להגדיר סימונים שונים של מהדר Java עבור קובצי מקור ספציפיים באמצעות מאפיין package_configuration של default_java_toolchain. לדוגמה:

load("@bazel_tools//tools/jdk: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
    ],
)

גרסאות מרובות של קוד המקור של Java במאגר יחיד

Bazel תומך בהרכבת גרסה יחידה של מקורות Java ב-build. המשמעות היא שכאשר בונים בדיקת Java או אפליקציה, כל התלות שלהם בנויות נגד אותה גרסת Java.

עם זאת, אפשר לבנות גרסאות נפרדות באמצעות סימונים שונים.

כדי שיהיה קל יותר להשתמש בסימונים שונים, ייתכן שקבוצות של סימונים לגרסה מסוימת יקובצו עם .bazelrc תצורות ומירכאות:

build:java8 --java_language_version=8
build:java8 --java_runtime_version=localjdk_8
build:java11 --java_language_version=11
build:java11 --java_runtime_version=remotejdk_11

ניתן להשתמש בהגדרות האלה עם הדגל --config, לדוגמה bazel test --config=java11 //:java11_test.