ชวาและบาเซล

รายงานปัญหา ดูแหล่งที่มา Nightly · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

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

การทำงานกับ Bazel

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

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

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

เวอร์ชัน Java

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

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

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

หากไม่มีการกำหนดค่าเพิ่มเติม 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

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

นอกจากนี้ ยังมี JDK และ JVM อีกคู่หนึ่งที่ใช้ในการสร้างและเรียกใช้เครื่องมือ ซึ่งจะ ใช้ในกระบวนการบิลด์ แต่ไม่ได้อยู่ในผลลัพธ์การบิลด์ 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 ของผู้ให้บริการรายใดก็ได้

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

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

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

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

โปรดใช้รูปแบบไดเรกทอรีมาตรฐานของ Maven (แหล่งที่มาใน src/main/java, การทดสอบ ใน src/test/java)

ไฟล์ BUILD

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

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

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

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

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

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

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

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

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

การกำหนดค่า Toolchain ของ Java

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

การกำหนดค่าเครื่องมือเชนการดำเนินการเพิ่มเติม

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

คุณอาจเพิ่มเครื่องมือเชนการดำเนินการของ Java โดยใช้กฎ local_java_repository หรือ remote_java_repository repo ในส่วนขยายโมดูล การเพิ่มกฎจะทำให้ JVM พร้อมใช้งานโดยใช้แฟล็ก เมื่อมีการกำหนดหลายรายการสำหรับระบบปฏิบัติการและสถาปัตยกรรม CPU เดียวกัน ระบบจะใช้รายการแรก

ตัวอย่างการกำหนดค่า JVM ในเครื่อง

load("@rules_java//toolchains: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("@rules_java//toolchains: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 ใช้ ระหว่างการคอมไพล์ และมีฟีเจอร์เพิ่มเติม เช่น Error Prone, การอ้างอิง Java ที่เข้มงวด, การคอมไพล์ส่วนหัว, การยกเลิกการเพิ่มความซับซ้อนของ Android, การวัดความครอบคลุม และการจัดการ genclass สำหรับ IDE

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

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

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

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

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

singlejar เครื่องมือจะรวมไฟล์ jar หลายไฟล์ไว้ในไฟล์เดียว

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

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

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

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

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

ตัวอย่างการกำหนดค่าเครื่องมือ

load(
  "@rules_java//toolchains: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 = "@rules_java//toolchains: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("@rules_java//toolchains: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=local_jdk_8
build:java11 --java_language_version=11
build:java11 --java_runtime_version=remotejdk_11

คุณใช้การกำหนดค่าเหล่านี้กับแฟล็ก --config ได้ เช่น bazel test --config=java11 //:java11_test