このページには、Java プロジェクトで Bazel を使用する場合に役立つリソースが記載されています。チュートリアル、ビルドルール、Bazel を使用した Java プロジェクトのビルドに固有の情報へのリンクが含まれています。
Bazel の使用
Java プロジェクトで Bazel を使用する際に役立つリソースは次のとおりです。
Bazel への移行
現在 Maven で Java プロジェクトをビルドしている場合は、移行ガイドの手順に沿って、Bazel で Maven プロジェクトのビルドを開始します。
Java のバージョン
構成フラグで設定される、関連する Java のバージョンは 2 つあります。
- リポジトリ内のソースファイルのバージョン
- コードの実行とテストに使用される Java ランタイムのバージョン
リポジトリ内のソースコードのバージョンを構成する
追加の構成を行わない場合、Bazel はリポジトリ内のすべての Java ソースファイルが単一の Java バージョンで記述されていることを前提とします。リポジトリ内のソースのバージョンを指定するには、build --java_language_version={ver}
を .bazelrc
ファイルに追加します。ここで、{ver}
は 11
などになります。Bazel リポジトリのオーナーは、Bazel とそのユーザーがソースコードの Java バージョン番号を参照できるように、このフラグを設定する必要があります。詳細については、Java 言語バージョン フラグをご覧ください。
コードの実行とテストに使用する JVM の構成
Bazel は、コンパイルに JDK を使用し、コードの実行とテストに別の JVM を使用します。
デフォルトでは、Bazel はダウンロードした JDK を使用してコードをコンパイルし、ローカルマシンにインストールされている JVM を使用してコードを実行してテストします。Bazel は、JAVA_HOME
またはパスを使用して JVM を検索します。
生成されたバイナリは、システム ライブラリにローカルにインストールされた JVM と互換性があります。つまり、生成されたバイナリはマシンにインストールされているものに依存します。
実行とテストに使用する JVM を構成するには、--java_runtime_version
フラグを使用します。デフォルト値は local_jdk
です。
密閉型テストとコンパイル
密閉コンパイルを作成するには、コマンドライン フラグ --java_runtime_version=remotejdk_11
を使用します。コードは、リモート リポジトリからダウンロードされた JVM 用にコンパイルされ、実行され、テストされます。詳細については、Java ランタイム バージョン フラグをご覧ください。
Java でのビルドツールのコンパイルと実行の設定
ツールのビルドと実行に使用される JDK と JVM の 2 つ目のペアがあります。これはビルドプロセスで使用されますが、ビルド結果には含まれません。この 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 の標準ディレクトリ レイアウト(src/main/java
の下にソース、src/test/java
の下にテスト)を使用する。
BUILD ファイル
BUILD
ファイルを作成する際のガイドラインは次のとおりです。
Java ソースを含むディレクトリごとに 1 つの
BUILD
ファイルを使用すると、ビルドのパフォーマンスが向上します。すべての
BUILD
ファイルには、次のような 1 つのjava_library
ルールを含める必要があります。java_library( name = "directory-name", srcs = glob(["*.java"]), deps = [...], )
ライブラリの名前は、
BUILD
ファイルを含むディレクトリの名前にする必要があります。これにより、ライブラリのラベルが短くなります。つまり、"//package:package"
ではなく"//package"
が使用されます。ソースは、ディレクトリ内のすべての Java ファイルの非再帰
glob
である必要があります。テストは
src/test
の下の一致するディレクトリに配置し、このライブラリに依存する必要があります。
高度な Java ビルド用の新しいルールの作成
注: 新しいルールの作成は、高度なビルドとテストのシナリオを対象としています。Bazel の使用を開始する場合は不要です。
以下のモジュール、構成フラグメント、プロバイダは、Java プロジェクトのビルド時に Bazel の機能を拡張するのに役立ちます。
- メインの Java モジュール:
java_common
- メインの Java プロバイダ:
JavaInfo
- 構成フラグメント:
java
その他のモジュール:
Java ツールチェーンの構成
Bazel では、次の 2 種類の Java ツールチェーンを使用します。
- 実行(Java バイナリの実行とテストに使用され、--java_runtime_version
フラグで制御)
- コンパイル(Java ソースのコンパイルに使用され、
--java_language_version
フラグで制御)
追加の実行ツールチェーンの構成
実行ツールチェーンはローカルまたはリポジトリの JVM であり、そのバージョン、オペレーティング システム、CPU アーキテクチャに関する追加情報があります。
Java 実行ツールチェーンは、WORKSPACE
ファイルで local_java_repository
ルールまたは remote_java_repository
ルールを使用して追加できます。ルールを追加すると、フラグを使用して 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 がコンパイル中に使用する複数のツールで構成されています。これらのツールは、Error Prone、厳格な Java 依存関係、ヘッダーのコンパイル、Android デシュガーリング、カバレッジ計測、IDE 用の genclass 処理などの追加機能を提供します。
JavaBuilder は、コンパイルを実行し、前述の機能を提供する Bazel バンドルのツールです。実際のコンパイルは、JDK の内部コンパイラを使用して実行されます。コンパイルに使用される JDK は、ツールチェーンの java_runtime
属性で指定します。
Bazel は一部の JDK 内部をオーバーライドします。JDK バージョンが 9 より大きい場合、java.compiler
モジュールと jdk.compiler
モジュールは JDK のフラグ --patch_module
を使用してパッチが適用されます。JDK バージョン 8 の場合、Java コンパイラは -Xbootclasspath
フラグを使用してパッチが適用されます。
VanillaJavaBuilder は JavaBuilder の 2 番目の実装です。JDK の内部コンパイラを変更せず、追加機能も備えていません。VanillaJavaBuilder は、組み込みツールチェーンでは使用されません。
Bazel は、JavaBuilder 以外にもコンパイル時に複数のツールを使用します。
ijar
ツールは jar
ファイルを処理して、呼び出しシグネチャ以外のすべてを削除します。生成される JAR はヘッダー JAR と呼ばれます。これらは、関数の本体が変更された場合にのみダウンストリームの依存関係を再コンパイルすることで、コンパイルの増分性を向上させるために使用されます。
singlejar
ツールは、複数の jar
ファイルを 1 つにまとめます。
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
: すべての機能、9 以上の JDK バージョンをサポート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 コンパイラ フラグの構成
default_java_toolchain
の package_configuration
属性を使用して、特定のソースファイルに異なる Java コンパイラ フラグを構成できます。以下の例を参照してください。
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
],
)
1 つのリポジトリ内に複数のバージョンの Java ソースコード
Bazel は、ビルド内で単一バージョンの Java ソースのコンパイルのみをサポートしています。つまり、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
)。