ชวาและบาเซล

หน้านี้มีแหล่งข้อมูลที่จะช่วยให้คุณใช้ Bazel กับโปรเจ็กต์ Java ได้ โดยจะลิงก์ไปยังบทแนะนำ กฎการสร้าง และข้อมูลอื่นๆ ที่เฉพาะเจาะจงสำหรับการสร้างโปรเจ็กต์ Java ด้วย Bazel

การใช้ Bazel

แหล่งข้อมูลต่อไปนี้จะช่วยให้คุณใช้ Bazel กับโปรเจ็กต์ Java ได้

การย้ายข้อมูลไปยัง Bazel

หากปัจจุบันคุณสร้างโปรเจ็กต์ Java ด้วย Maven ให้ทำตามขั้นตอนในคู่มือการย้ายข้อมูลเพื่อเริ่มสร้างโปรเจ็กต์ Maven ด้วย Bazel

เวอร์ชัน Java

Java มี 2 เวอร์ชันที่เกี่ยวข้องซึ่งตั้งค่าด้วยแฟล็กการกำหนดค่า ได้แก่

  • เวอร์ชันของไฟล์ต้นทางในคลังเก็บ
  • เวอร์ชันของ Java Runtime ที่ใช้ในการเรียกใช้โค้ดและทดสอบโค้ด

การกำหนดค่าเวอร์ชันของซอร์สโค้ดในคลังเก็บ

หากไม่มีการกำหนดค่าเพิ่มเติม Bazel จะถือว่าไฟล์ต้นทาง Java ทั้งหมดในคลังเก็บเขียนด้วย Java เวอร์ชันเดียว หากต้องการระบุเวอร์ชันของ แหล่งที่มาในคลังเก็บ ให้เพิ่ม build --java_language_version={ver} ลงใน .bazelrc ไฟล์ โดยที่ {ver} เช่น 11 เจ้าของคลังเก็บ Bazel ควรตั้งค่าแฟล็กนี้เพื่อให้ Bazel และผู้ใช้สามารถอ้างอิงหมายเลขเวอร์ชัน Java ของซอร์สโค้ดได้ ดูรายละเอียดเพิ่มเติมได้ที่ แฟล็กเวอร์ชันภาษา Java

การกำหนดค่า JVM ที่ใช้ในการเรียกใช้และทดสอบโค้ด

Bazel ใช้ JDK หนึ่งรายการสำหรับการคอมไพล์ และใช้ JVM อีกรายการสำหรับการเรียกใช้และทดสอบโค้ด

โดยค่าเริ่มต้น Bazel จะคอมไพล์โค้ดโดยใช้ JDK ที่ดาวน์โหลด และเรียกใช้และทดสอบโค้ดด้วย JVM ที่ติดตั้งในเครื่อง Bazel จะค้นหา JVM โดยใช้ JAVA_HOME หรือเส้นทาง

ไบนารีที่ได้จะเข้ากันได้กับ JVM ที่ติดตั้งในเครื่องในไลบรารีระบบ ซึ่งหมายความว่าไบนารีที่ได้จะขึ้นอยู่กับสิ่งที่ติดตั้งในเครื่อง

หากต้องการกำหนดค่า JVM ที่ใช้สำหรับการเรียกใช้และการทดสอบ ให้ใช้แฟล็ก --java_runtime_version ค่าเริ่มต้นคือ local_jdk

การทดสอบที่แยกต่างหากและการคอมไพล์

หากต้องการสร้างการคอมไพล์ที่แยกต่างหาก คุณสามารถใช้ Flag บรรทัดคำสั่ง --java_runtime_version=remotejdk_11 ระบบจะคอมไพล์ เรียกใช้ และทดสอบโค้ดใน JVM ที่ดาวน์โหลดจากคลังเก็บระยะไกล ดูรายละเอียดเพิ่มเติมได้ที่ แฟล็กเวอร์ชัน Java Runtime

การกำหนดค่าการคอมไพล์และการดำเนินการเครื่องมือบิลด์ใน Java

นอกจากนี้ยังมี JDK และ JVM อีกคู่หนึ่งที่ใช้ในการสร้างและเรียกใช้เครื่องมือ ซึ่งใช้ในกระบวนการบิลด์ แต่ไม่ได้อยู่ในผลลัพธ์การสร้าง คุณสามารถควบคุม JDK และ JVM ดังกล่าวได้โดยใช้ --tool_java_language_version และ --tool_java_runtime_version ค่าเริ่มต้นคือ 11 และ remotejdk_11, ตามลำดับ

การคอมไพล์โดยใช้ JDK ที่ติดตั้งในเครื่อง

โดยค่าเริ่มต้น Bazel จะคอมไพล์โดยใช้ JDK ระยะไกล เนื่องจากมีการลบล้างส่วนประกอบภายในของ JDK ระบบจะกำหนดค่า Toolchain การคอมไพล์โดยใช้ JDK ที่ติดตั้งในเครื่อง แต่ไม่ได้ใช้

หากต้องการคอมไพล์โดยใช้ JDK ที่ติดตั้งในเครื่อง นั่นคือใช้ Toolchain การคอมไพล์สำหรับ JDK ในเครื่อง ให้ใช้แฟล็กเพิ่มเติม --extra_toolchains=@local_jdk//:all แต่โปรดทราบว่าแฟล็กนี้อาจใช้ไม่ได้กับ JDK ของผู้ให้บริการรายอื่นๆ

ดูรายละเอียดเพิ่มเติมได้ที่ การกำหนดค่า Java Toolchain

แนวทางปฏิบัติแนะนำ

นอกเหนือจากแนวทางปฏิบัติแนะนำทั่วไปของ Bazel แล้ว ด้านล่างนี้คือ แนวทางปฏิบัติแนะนำที่เฉพาะเจาะจงสำหรับโปรเจ็กต์ Java

โครงสร้างไดเรกทอรี

ควรใช้เลย์เอาต์ไดเรกทอรีมาตรฐานของ Maven (แหล่งที่มาใน src/main/java และการทดสอบใน src/test/java)

ไฟล์ BUILD

ปฏิบัติตามหลักเกณฑ์ต่อไปนี้เมื่อสร้างไฟล์ BUILD

  • ใช้ไฟล์ BUILD 1 ไฟล์ต่อไดเรกทอรีที่มีแหล่งที่มาของ Java เนื่องจากวิธีนี้จะช่วยปรับปรุงประสิทธิภาพการสร้าง

  • ไฟล์ BUILD ทุกไฟล์ควรมีกฎ java_library 1 ข้อที่มีลักษณะดังนี้

    java_library(
        name = "directory-name",
        srcs = glob(["*.java"]),
        deps = [...],
    )
    
  • ชื่อไลบรารีควรเป็นชื่อของไดเรกทอรีที่มีไฟล์ BUILD วิธีนี้จะทำให้ป้ายกำกับของไลบรารีสั้นลง เช่น ใช้ "//package" แทน "//package:package"

  • แหล่งที่มาควรเป็น glob แบบไม่เกิดซ้ำของ ไฟล์ Java ทั้งหมดในไดเรกทอรี

  • การทดสอบควรอยู่ในไดเรกทอรีที่ตรงกันใน src/test และขึ้นอยู่กับไลบรารีนี้

การสร้างกฎใหม่สำหรับการสร้าง Java ขั้นสูง

หมายเหตุ: การสร้างกฎใหม่เหมาะสำหรับสถานการณ์การสร้างและการทดสอบขั้นสูง คุณไม่จำเป็นต้องสร้างกฎใหม่เมื่อเริ่มต้นใช้งาน Bazel

โมดูล ส่วนการกำหนดค่า และผู้ให้บริการต่อไปนี้จะช่วยคุณ ขยายขีดความสามารถของ Bazel เมื่อสร้างโปรเจ็กต์ Java

การกำหนดค่า Java Toolchain

Bazel ใช้ Java Toolchain 2 ประเภท ได้แก่ - การเรียกใช้ ซึ่งใช้ในการเรียกใช้และทดสอบไบนารี Java และควบคุมด้วย --java_runtime_version แฟล็ก - การคอมไพล์ ซึ่งใช้ในการคอมไพล์แหล่งที่มาของ Java และควบคุมด้วย --java_language_version แฟล็ก

การกำหนดค่า Toolchain การเรียกใช้เพิ่มเติม

Toolchain การดำเนินการคือ JVM ไม่ว่าจะเป็นในเครื่องหรือจากคลังเก็บ พร้อมข้อมูลเพิ่มเติมเกี่ยวกับเวอร์ชัน ระบบปฏิบัติการ และสถาปัตยกรรม CPU

คุณสามารถเพิ่ม Java Toolchain การเรียกใช้ได้โดยใช้กฎ 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 = ...
)

การกำหนดค่า Toolchain การคอมไพล์เพิ่มเติม

Toolchain การคอมไพล์ประกอบด้วย JDK และเครื่องมือหลายรายการที่ Bazel ใช้ระหว่างการคอมไพล์ และมีฟีเจอร์เพิ่มเติม เช่น Error Prone, ทรัพยากร Dependency ของ Java แบบเข้มงวด, การคอมไพล์ส่วนหัว, กระบวนการ Desugaring ของ Android, การวัดคุม และการจัดการ genclass สำหรับ IDE

JavaBuilder เป็นเครื่องมือที่มาพร้อมกับ Bazel ซึ่งทำการคอมไพล์และมีฟีเจอร์ที่กล่าวถึงข้างต้น การคอมไพล์จริงจะดำเนินการโดยใช้คอมไพเลอร์ภายในของ JDK JDK ที่ใช้สำหรับการคอมไพล์จะระบุโดยแอตทริบิวต์ java_runtime ของ Toolchain

Bazel จะลบล้างส่วนประกอบภายในบางส่วนของ JDK ในกรณีที่ JDK เวอร์ชัน > 9 ระบบจะแพตช์โมดูล java.compiler และ jdk.compiler โดยใช้แฟล็ก --patch_module ของ JDK ในกรณีที่ JDK เวอร์ชัน 8 ระบบจะแพตช์คอมไพเลอร์ Java โดยใช้แฟล็ก -Xbootclasspath

VanillaJavaBuilder เป็นการใช้งาน JavaBuilder ครั้งที่ 2 ซึ่งไม่แก้ไขคอมไพเลอร์ภายในของ JDK และไม่มีฟีเจอร์เพิ่มเติม Toolchain ที่มาพร้อมเครื่องจะไม่ใช้ VanillaJavaBuilder

นอกจาก JavaBuilder แล้ว Bazel ยังใช้เครื่องมืออื่นๆ อีกหลายรายการระหว่างการคอมไพล์

เครื่องมือ ijar จะประมวลผลไฟล์ jar เพื่อนำทุกอย่างออก ยกเว้นลายเซ็นการเรียก ไฟล์ Jar ที่ได้จะเรียกว่า Header Jar ซึ่งใช้เพื่อปรับปรุงการคอมไพล์แบบเพิ่มส่วนประกอบโดยการคอมไพล์ซ้ำเฉพาะส่วนประกอบที่ขึ้นต่อกันเมื่อมีการเปลี่ยนแปลงเนื้อหาของฟังก์ชัน

เครื่องมือ singlejar จะแพ็กไฟล์ jar หลายไฟล์รวมกันเป็นไฟล์เดียว

เครื่องมือ genclass จะประมวลผลเอาต์พุตของการคอมไพล์ Java ภายหลัง และสร้างไฟล์ jar ที่มีเฉพาะไฟล์คลาสสำหรับแหล่งที่มาที่สร้างโดยโปรเซสเซอร์คำอธิบายประกอบ

เครื่องมือ JacocoRunner จะเรียกใช้ Jacoco ในไฟล์ที่วัดประสิทธิภาพการทำงานของโค้ด และแสดงผลลัพธ์ในรูปแบบ LCOV

เครื่องมือ TestRunner จะเรียกใช้การทดสอบ JUnit 4 ในสภาพแวดล้อมที่มีการควบคุม

คุณสามารถกำหนดค่าการคอมไพล์ใหม่ได้โดยเพิ่ม default_java_toolchain มาโครลงใน ไฟล์ BUILD และลงทะเบียนโดยเพิ่มกฎ register_toolchains ลงใน ไฟล์ WORKSPACE หรือใช้ --extra_toolchains แฟล็ก

ระบบจะใช้ Toolchain ก็ต่อเมื่อแอตทริบิวต์ source_version ตรงกับค่าที่ระบุโดยแฟล็ก --java_language_version

ตัวอย่างการกำหนดค่า Toolchain

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: เหมือนกับค่าเริ่มต้น แต่เครื่องมือทั้งหมดสร้างจากแหล่งที่มา (ตัวเลือกนี้อาจมีประโยชน์ในระบบปฏิบัติการที่มี libc ต่างกัน)

การกำหนดค่าแฟล็ก JVM และคอมไพเลอร์ Java

คุณสามารถกำหนดค่าแฟล็ก JVM และ javac ได้โดยใช้แฟล็กหรือแอตทริบิวต์ default_java_toolchain

แฟล็กที่เกี่ยวข้องคือ --jvmopt, --host_jvmopt, --javacopt, และ --host_javacopt

แอตทริบิวต์ default_java_toolchain ที่เกี่ยวข้องคือ javacopts, jvm_opts, javabuilder_jvm_opts และ turbine_jvm_opts

การกำหนดค่าแฟล็กคอมไพเลอร์ Java เฉพาะแพ็กเกจ

คุณสามารถกำหนดค่าแฟล็กคอมไพเลอร์ 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