Java dan Bazel

Laporkan masalah Lihat sumber Nightly · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

Halaman ini berisi referensi yang membantu Anda menggunakan Bazel dengan project Java. Dokumen ini menautkan ke tutorial, aturan build, dan informasi lain yang khusus untuk membangun project Java dengan Bazel.

Bekerja dengan Bazel

Referensi berikut akan membantu Anda menggunakan Bazel di project Java:

Bermigrasi ke Bazel

Jika saat ini Anda mem-build project Java dengan Maven, ikuti langkah-langkah dalam panduan migrasi untuk mulai mem-build project Maven dengan Bazel:

Versi Java

Ada dua versi Java yang relevan yang ditetapkan dengan tanda konfigurasi:

  • versi file sumber di repositori
  • versi runtime Java yang digunakan untuk mengeksekusi kode dan mengujinya

Mengonfigurasi versi kode sumber di repositori Anda

Tanpa konfigurasi tambahan, Bazel mengasumsikan semua file sumber Java di repositori ditulis dalam satu versi Java. Untuk menentukan versi sumber dalam repositori, tambahkan build --java_language_version={ver} ke file .bazelrc, dengan {ver} misalnya 11. Pemilik repositori Bazel harus menyetel tanda ini agar Bazel dan penggunanya dapat mereferensikan nomor versi Java kode sumber. Untuk mengetahui detail selengkapnya, lihat Flag versi bahasa Java.

Mengonfigurasi JVM yang digunakan untuk mengeksekusi dan menguji kode

Bazel menggunakan satu JDK untuk kompilasi dan JVM lain untuk mengeksekusi dan menguji kode.

Secara default, Bazel mengompilasi kode menggunakan JDK yang didownloadnya, serta menjalankan dan menguji kode dengan JVM yang diinstal di komputer lokal. Bazel menelusuri JVM menggunakan JAVA_HOME atau jalur.

Biner yang dihasilkan kompatibel dengan JVM yang diinstal secara lokal di library sistem, yang berarti biner yang dihasilkan bergantung pada apa yang diinstal di mesin.

Untuk mengonfigurasi JVM yang digunakan untuk eksekusi dan pengujian, gunakan flag --java_runtime_version. Nilai defaultnya adalah local_jdk.

Pengujian dan kompilasi hermetik

Untuk membuat kompilasi hermetik, Anda dapat menggunakan flag command line --java_runtime_version=remotejdk_11. Kode dikompilasi, dieksekusi, dan diuji di JVM yang didownload dari repositori jarak jauh. Untuk mengetahui detail selengkapnya, lihat Flag versi runtime Java.

Mengonfigurasi kompilasi dan eksekusi alat build di Java

Ada pasangan kedua JDK dan JVM yang digunakan untuk membuat dan mengeksekusi alat, yang digunakan dalam proses build, tetapi tidak ada dalam hasil build. JDK dan JVM tersebut dikontrol menggunakan --tool_java_language_version dan --tool_java_runtime_version. Nilai defaultnya adalah 11 dan remotejdk_11, masing-masing.

Mengompilasi menggunakan JDK yang diinstal secara lokal

Secara default, Bazel mengompilasi menggunakan JDK jarak jauh, karena menggantikan internal JDK. Toolchain kompilasi yang menggunakan JDK yang diinstal secara lokal dikonfigurasi, tetapi tidak digunakan.

Untuk mengompilasi menggunakan JDK yang diinstal secara lokal, yaitu menggunakan toolchain kompilasi untuk JDK lokal, gunakan tanda tambahan --extra_toolchains=@local_jdk//:all. Namun, perhatikan bahwa tanda ini mungkin tidak berfungsi di JDK dari vendor arbitrer.

Untuk mengetahui detail selengkapnya, lihat mengonfigurasi toolchain Java.

Praktik terbaik

Selain praktik terbaik Bazel umum, berikut adalah praktik terbaik khusus untuk project Java.

Struktur direktori

Lebih memilih tata letak direktori standar Maven (sumber di bagian src/main/java, pengujian di bagian src/test/java).

File BUILD

Ikuti panduan berikut saat membuat file BUILD:

  • Gunakan satu file BUILD per direktori yang berisi sumber Java, karena hal ini meningkatkan performa build.

  • Setiap file BUILD harus berisi satu aturan java_library yang terlihat seperti ini:

    java_library(
        name = "directory-name",
        srcs = glob(["*.java"]),
        deps = [...],
    )
    
  • Nama library harus berupa nama direktori yang berisi file BUILD. Hal ini membuat label library lebih pendek, yaitu menggunakan "//package", bukan "//package:package".

  • Sumber harus berupa glob non-rekursif dari semua file Java di direktori.

  • Pengujian harus berada di direktori yang cocok di src/test dan bergantung pada library ini.

Membuat aturan baru untuk build Java lanjutan

Catatan: Pembuatan aturan baru ditujukan untuk skenario build dan pengujian lanjutan. Anda tidak memerlukannya saat mulai menggunakan Bazel.

Modul, fragmen konfigurasi, dan penyedia berikut akan membantu Anda memperluas kemampuan Bazel saat membangun project Java:

Mengonfigurasi toolchain Java

Bazel menggunakan dua jenis toolchain Java: - eksekusi, digunakan untuk mengeksekusi dan menguji biner Java, dikontrol dengan flag --java_runtime_version - kompilasi, digunakan untuk mengompilasi sumber Java, dikontrol dengan flag --java_language_version

Mengonfigurasi toolchain eksekusi tambahan

Rangkaian alat eksekusi adalah JVM, baik lokal maupun dari repositori, dengan beberapa informasi tambahan tentang versi, sistem operasi, dan arsitektur CPU-nya.

Toolchain eksekusi Java dapat ditambahkan menggunakan aturan repo local_java_repository atau remote_java_repository dalam ekstensi modul. Menambahkan aturan membuat JVM tersedia menggunakan tanda. Jika beberapa definisi untuk sistem operasi dan arsitektur CPU yang sama diberikan, definisi pertama akan digunakan.

Contoh konfigurasi JVM lokal:

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
)

Contoh konfigurasi JVM jarak jauh:

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 = ...
)

Mengonfigurasi toolchain kompilasi tambahan

Toolchain kompilasi terdiri dari JDK dan beberapa alat yang digunakan Bazel selama kompilasi dan yang menyediakan fitur tambahan, seperti: Error Prone, dependensi Java yang ketat, kompilasi header, penghapusan gula Android, instrumentasi cakupan, dan penanganan genclass untuk IDE.

JavaBuilder adalah alat yang dibundel dengan Bazel yang menjalankan kompilasi, dan menyediakan fitur yang disebutkan di atas. Kompilasi sebenarnya dieksekusi menggunakan compiler internal oleh JDK. JDK yang digunakan untuk kompilasi ditentukan oleh atribut java_runtime toolchain.

Bazel menggantikan beberapa internal JDK. Jika versi JDK > 9, modul java.compiler dan jdk.compiler di-patch menggunakan flag JDK --patch_module. Jika menggunakan JDK versi 8, compiler Java di-patch menggunakan flag -Xbootclasspath.

VanillaJavaBuilder adalah implementasi kedua JavaBuilder, yang tidak mengubah compiler internal JDK dan tidak memiliki fitur tambahan. VanillaJavaBuilder tidak digunakan oleh toolchain bawaan mana pun.

Selain JavaBuilder, Bazel menggunakan beberapa alat lain selama kompilasi.

Alat ijar memproses file jar untuk menghapus semuanya kecuali tanda tangan panggilan. JAR yang dihasilkan disebut JAR header. Fitur ini digunakan untuk meningkatkan inkrementalitas kompilasi dengan hanya mengompilasi ulang dependen hilir saat isi fungsi berubah.

Alat singlejar mengemas beberapa file jar menjadi satu.

Alat genclass memproses output kompilasi Java, dan menghasilkan jar yang hanya berisi file class untuk sumber yang dihasilkan oleh pemroses anotasi.

Alat JacocoRunner menjalankan Jacoco pada file yang diinstrumentasi dan menghasilkan output dalam format LCOV.

Alat TestRunner menjalankan pengujian JUnit 4 dalam lingkungan yang terkontrol.

Anda dapat mengonfigurasi ulang kompilasi dengan menambahkan makro default_java_toolchain ke file BUILD dan mendaftarkannya dengan menambahkan aturan register_toolchains ke file MODULE.bazel atau menggunakan flag --extra_toolchains.

Toolchain hanya digunakan jika atribut source_version cocok dengan nilai yang ditentukan oleh flag --java_language_version.

Contoh konfigurasi toolchain:

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",
)

yang dapat digunakan menggunakan --extra_toolchains=//:repository_default_toolchain_definition atau dengan menambahkan register_toolchains("//:repository_default_toolchain_definition") ke ruang kerja.

Konfigurasi yang telah ditentukan sebelumnya:

  • DEFAULT_TOOLCHAIN_CONFIGURATION: semua fitur, mendukung versi JDK >= 9
  • VANILLA_TOOLCHAIN_CONFIGURATION: tidak ada fitur tambahan, mendukung JDK dari vendor arbitrer.
  • PREBUILT_TOOLCHAIN_CONFIGURATION: sama seperti default, tetapi hanya menggunakan alat bawaan (ijar, singlejar)
  • NONPREBUILT_TOOLCHAIN_CONFIGURATION: sama seperti default, tetapi semua alat dibuat dari sumber (ini mungkin berguna pada sistem operasi dengan libc yang berbeda)

Mengonfigurasi flag compiler JVM dan Java

Anda dapat mengonfigurasi flag JVM dan javac dengan flag atau dengan atribut default_java_toolchain.

Flag yang relevan adalah --jvmopt, --host_jvmopt, --javacopt, dan --host_javacopt.

Atribut default_java_toolchain yang relevan adalah javacopts, jvm_opts, javabuilder_jvm_opts, dan turbine_jvm_opts.

Konfigurasi tanda kompiler Java khusus paket

Anda dapat mengonfigurasi berbagai tanda compiler Java untuk file sumber tertentu menggunakan atribut package_configuration dari default_java_toolchain. Lihat contoh di bawah.

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
    ],
)

Beberapa versi kode sumber Java dalam satu repositori

Bazel hanya mendukung kompilasi satu versi sumber Java dalam build. build. Artinya, saat membuat pengujian atau aplikasi Java, semua dependensi dibuat berdasarkan versi Java yang sama.

Namun, build terpisah dapat dieksekusi menggunakan flag yang berbeda.

Untuk mempermudah tugas penggunaan berbagai tanda, kumpulan tanda untuk versi tertentu dapat dikelompokkan dengan .bazelrc config":

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

Konfigurasi ini dapat digunakan dengan flag --config, misalnya bazel test --config=java11 //:java11_test.