Add Java toolchain tests
- Pass java_language_version to bazel_java_test.sh
This way also the toolchain compiling for Java 14 and 15 are tested and not only if the code compiled with toolchain for Java 8 executes on JDKs 14 and 15.
- Add verifications Java toolchain tests.
Different configurations of toolchains were just tested to build, without checking the configurations give the desired results.
- Add local_java_repository tests and fix problem with implementation.
- Remove unused toolchain_utils.bzl
Closes #12788.
PiperOrigin-RevId: 350752125
diff --git a/src/test/shell/bazel/BUILD b/src/test/shell/bazel/BUILD
index 3d90a81..605c4ac 100644
--- a/src/test/shell/bazel/BUILD
+++ b/src/test/shell/bazel/BUILD
@@ -244,6 +244,8 @@
# java_tools zips to test
"src/java_tools.zip",
"src/java_tools_prebuilt.zip",
+ # --java_language_version value
+ java_version,
# --java_runtime_version value
java_version,
],
@@ -269,6 +271,8 @@
# java_tools zips to test
"$(LOCAL_JAVA_TOOLS_ZIP_URL)",
"$(LOCAL_JAVA_TOOLS_PREBUILT_ZIP_URL)",
+ # --java_language_version value
+ java_version,
# --java_runtime_version value
java_version,
],
diff --git a/src/test/shell/bazel/bazel_java_test.sh b/src/test/shell/bazel/bazel_java_test.sh
index 4601591..8ffeca4 100755
--- a/src/test/shell/bazel/bazel_java_test.sh
+++ b/src/test/shell/bazel/bazel_java_test.sh
@@ -82,6 +82,13 @@
JAVA_TOOLS_PREBUILT_ZIP_FILE_URL=${JAVA_TOOLS_PREBUILT_ZIP_FILE_URL:-}
if [[ $# -gt 0 ]]; then
+ JAVA_LANGUAGE_VERSION="$1"; shift
+ add_to_bazelrc "build --java_language_version=${JAVA_LANGUAGE_VERSION}"
+ add_to_bazelrc "build --tool_java_language_version=${JAVA_LANGUAGE_VERSION}"
+fi
+
+
+if [[ $# -gt 0 ]]; then
JAVA_RUNTIME_VERSION="$1"; shift
add_to_bazelrc "build --java_runtime_version=${JAVA_RUNTIME_VERSION}"
add_to_bazelrc "build --tool_java_runtime_version=${JAVA_RUNTIME_VERSION}"
diff --git a/src/test/shell/bazel/bazel_java_test_defaults.sh b/src/test/shell/bazel/bazel_java_test_defaults.sh
index 980b121..9f88537 100755
--- a/src/test/shell/bazel/bazel_java_test_defaults.sh
+++ b/src/test/shell/bazel/bazel_java_test_defaults.sh
@@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-# Tests the java rules with the default values provided by Bazel.
+# Tests Java toolchains, configured using flags or the default_java_toolchain macro.
#
set -euo pipefail
@@ -133,6 +133,7 @@
expect_log "major version: 59"
}
+# When coverage is requested with no Jacoco configured, an error shall be reported.
function test_tools_jdk_toolchain_nojacocorunner() {
mkdir -p java/main
cat >java/main/BUILD <<EOF
@@ -167,7 +168,7 @@
expect_log "jacocorunner not set in java_toolchain:"
}
-
+# Specific toolchain attributes can be overridden.
function test_default_java_toolchain_manualConfiguration() {
cat > BUILD <<EOF
load("@bazel_tools//tools/jdk:default_java_toolchain.bzl", "default_java_toolchain")
@@ -177,9 +178,15 @@
jvm_opts = [],
)
EOF
+
bazel build //:vanilla || fail "default_java_toolchain target failed to build"
+ bazel cquery --output=build //:vanilla >& $TEST_log || fail "failed to query //:vanilla"
+
+ expect_log 'jvm_opts = \[\]'
+ expect_log 'javabuilder = \["//:VanillaJavaBuilder"\]'
}
+# Specific toolchain attributes - jvm_opts containing location function - can be overridden.
function test_default_java_toolchain_manualConfigurationWithLocation() {
cat > BUILD <<EOF
load("@bazel_tools//tools/jdk:default_java_toolchain.bzl", "default_java_toolchain", "JDK9_JVM_OPTS")
@@ -200,9 +207,15 @@
],
)
EOF
+
bazel build //:toolchain || fail "default_java_toolchain target failed to build"
+ bazel cquery --output=build //:toolchain >& $TEST_log || fail "failed to query //:toolchain"
+
+ expect_log 'jvm_opts = \["-XX:+UseParallelOldGC", "-XX:-CompactStrings", "--patch-module=java.compiler=$(location @remote_java_tools//:java_compiler_jar)", "--patch-module=jdk.compiler=$(location @remote_java_tools//:jdk_compiler_jar)",'
+ expect_log 'tools = \["@remote_java_tools//:java_compiler_jar", "@remote_java_tools//:jdk_compiler_jar"\]'
}
+# JVM8_TOOLCHAIN_CONFIGURATION shall override Java 8 internal compiler classes.
function test_default_java_toolchain_jvm8Toolchain() {
cat > BUILD <<EOF
load("@bazel_tools//tools/jdk:default_java_toolchain.bzl", "default_java_toolchain", "JVM8_TOOLCHAIN_CONFIGURATION")
@@ -212,9 +225,18 @@
java_runtime = "@local_jdk//:jdk",
)
EOF
+
bazel query //:jvm8_toolchain || fail "default_java_toolchain target failed to build"
+ bazel cquery 'deps(//:jvm8_toolchain)' >& $TEST_log || fail "failed to query //:jvm8_toolchain"
+
+ expect_log ":JavaBuilder"
+ expect_log ":javac_jar"
+ expect_not_log ":java_compiler_jar"
+ expect_not_log ":jdk_compiler_jar"
+ expect_not_log ":VanillaJavaBuilder"
}
+# DEFAULT_TOOLCHAIN_CONFIGURATION shall use JavaBuilder and override Java 9+ internal compiler classes.
function test_default_java_toolchain_javabuilderToolchain() {
cat > BUILD <<EOF
load("@bazel_tools//tools/jdk:default_java_toolchain.bzl", "default_java_toolchain", "DEFAULT_TOOLCHAIN_CONFIGURATION")
@@ -223,9 +245,18 @@
configuration = DEFAULT_TOOLCHAIN_CONFIGURATION,
)
EOF
+
bazel build //:javabuilder_toolchain || fail "default_java_toolchain target failed to build"
+ bazel cquery 'deps(//:javabuilder_toolchain)' >& $TEST_log || fail "failed to query //:javabuilder_toolchain"
+
+ expect_log ":JavaBuilder"
+ expect_log ":java_compiler_jar"
+ expect_log ":jdk_compiler_jar"
+ expect_not_log ":VanillaJavaBuilder"
+ expect_not_log ":javac_jar"
}
+# VANILLA_TOOLCHAIN_CONFIGURATION shall use VanillaJavaBuilder and not override any JDK internal compiler classes.
function test_default_java_toolchain_vanillaToolchain() {
cat > BUILD <<EOF
load("@bazel_tools//tools/jdk:default_java_toolchain.bzl", "default_java_toolchain", "VANILLA_TOOLCHAIN_CONFIGURATION")
@@ -235,9 +266,18 @@
java_runtime = "@local_jdk//:jdk",
)
EOF
+
bazel build //:vanilla_toolchain || fail "default_java_toolchain target failed to build"
+ bazel cquery 'deps(//:vanilla_toolchain)' >& $TEST_log || fail "failed to query //:vanilla_toolchain"
+
+ expect_log ":VanillaJavaBuilder"
+ expect_not_log ":JavaBuilder"
+ expect_not_log ":java_compiler_jar"
+ expect_not_log ":jdk_compiler_jar"
+ expect_not_log ":javac_jar"
}
+# PREBUILT_TOOLCHAIN_CONFIGURATION shall use prebuilt ijar and singlejar binaries.
function test_default_java_toolchain_prebuiltToolchain() {
cat > BUILD <<EOF
load("@bazel_tools//tools/jdk:default_java_toolchain.bzl", "default_java_toolchain", "PREBUILT_TOOLCHAIN_CONFIGURATION")
@@ -246,9 +286,17 @@
configuration = PREBUILT_TOOLCHAIN_CONFIGURATION,
)
EOF
+
bazel build //:prebuilt_toolchain || fail "default_java_toolchain target failed to build"
+ bazel cquery 'deps(//:prebuilt_toolchain)' >& $TEST_log || fail "failed to query //:prebuilt_toolchain"
+
+ expect_log "ijar/ijar\(.exe\)\? "
+ expect_log "singlejar/singlejar_local"
+ expect_not_log "ijar/ijar.cc"
+ expect_not_log "singlejar/singlejar_main.cc"
}
+# NONPREBUILT_TOOLCHAIN_CONFIGURATION shall compile ijar and singlejar from sources.
function test_default_java_toolchain_nonprebuiltToolchain() {
cat > BUILD <<EOF
load("@bazel_tools//tools/jdk:default_java_toolchain.bzl", "default_java_toolchain", "NONPREBUILT_TOOLCHAIN_CONFIGURATION")
@@ -257,8 +305,14 @@
configuration = NONPREBUILT_TOOLCHAIN_CONFIGURATION,
)
EOF
+
bazel build //:nonprebuilt_toolchain || fail "default_java_toolchain target failed to build"
+ bazel cquery 'deps(//:nonprebuilt_toolchain)' >& $TEST_log || fail "failed to query //:nonprebuilt_toolchain"
+
+ expect_log "ijar/ijar.cc"
+ expect_log "singlejar/singlejar_main.cc"
+ expect_not_log "ijar/ijar\(.exe\)\? "
+ expect_not_log "singlejar/singlejar_local"
}
-
-run_suite "Java integration tests with default Bazel values"
+run_suite "Java toolchains tests, configured using flags or the default_java_toolchain macro."
diff --git a/src/test/shell/bazel/bazel_with_jdk_test.sh b/src/test/shell/bazel/bazel_with_jdk_test.sh
index b9ba99d..11843fb 100755
--- a/src/test/shell/bazel/bazel_with_jdk_test.sh
+++ b/src/test/shell/bazel/bazel_with_jdk_test.sh
@@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-# Tests that the version of Bazel with a bundled JDK works.
+# Tests detection of local JDK and that Bazel executes with a bundled JDK.
#
set -euo pipefail
@@ -90,6 +90,19 @@
setup_bazelrc
fi
+ mkdir -p java/main
+ cat >java/main/BUILD <<EOF
+java_library(
+ name = 'JavaExample',
+ srcs = ['JavaExample.java'],
+)
+EOF
+
+ cat >java/main/JavaExample.java <<EOF
+public class JavaExample {
+}
+EOF
+
# ... but ensure JAVA_HOME is set, so we can find a default local jdk
export JAVA_HOME="${javabase}"
}
@@ -123,7 +136,6 @@
# JVM selection: Do not automatically use remote JDK for execution JVM if local
# JDK is not found. Print an error message guiding the user how to use remote JDK.
# Rationale: Keeping build systems stable upon Bazel releases.
-
function test_bazel_reports_missing_local_jdk() {
# Make a JAVA_HOME with javac and without java
# This fails discovery on systems that rely on JAVA_HOME, rely on PATH and
@@ -135,21 +147,97 @@
export JAVA_HOME="$PWD"
export PATH="$PWD/bin:$PATH"
- mkdir -p java/main
- cat >java/main/BUILD <<EOF
-java_library(
- name = 'JavaExample',
- srcs = ['JavaExample.java'],
-)
-EOF
-
- cat >java/main/JavaExample.java <<EOF
-public class JavaExample {
-}
-EOF
-
- bazel build java/main:JavaExample &>"${TEST_log}" && fail "build should have failed" || true
+ bazel build java/main:JavaExample &>"${TEST_log}" \
+ && fail "build with missing local JDK should have failed" || true
expect_log "Auto-Configuration Error: Cannot find Java binary"
}
-run_suite "bazel test suite"
+# Bazel shall detect JDK version and configure it with "local_jdk_{version}" and "{version}" setting.
+function test_bazel_detects_local_jdk_version8() {
+ # Fake Java version 8
+ mkdir -p jdk/bin
+ touch jdk/bin/javac
+ chmod +x jdk/bin/javac
+ cat >jdk/bin/java <<EOF
+#!/bin/bash
+
+echo " Property settings:" >&2
+echo " java.version = 1.8.0 " >&2
+EOF
+ chmod +x jdk/bin/java
+ export JAVA_HOME="$PWD/jdk"
+ export PATH="$PWD/jdk/bin:$PATH"
+
+ bazel cquery --toolchain_resolution_debug --java_runtime_version=8 '//java/main:JavaExample' \
+ &>"${TEST_log}" || fail "Autodetecting a fake JDK version 8 and selecting it failed"
+ expect_log "@bazel_tools//tools/jdk:runtime_toolchain_type -> toolchain @local_jdk//:jdk"
+
+ bazel cquery --toolchain_resolution_debug --java_runtime_version=local_jdk_8 '//java/main:JavaExample' \
+ &>"${TEST_log}" || fail "Autodetecting a fake JDK version 8 and selecting it failed"
+ expect_log "@bazel_tools//tools/jdk:runtime_toolchain_type -> toolchain @local_jdk//:jdk"
+
+ bazel cquery --toolchain_resolution_debug --java_runtime_version=11 '//java/main:JavaExample' \
+ &>"${TEST_log}" || fail "Selecting prepackaged JDK version 11 failed"
+ expect_not_log "@bazel_tools//tools/jdk:runtime_toolchain_type -> toolchain @local_jdk//:jdk"
+}
+
+# Bazel shall detect JDK version and configure it with "local_jdk_{version}" and "{version}" setting.
+function test_bazel_detects_local_jdk_version11() {
+ # Fake Java version 11
+ mkdir -p jdk/bin
+ touch jdk/bin/javac
+ chmod +x jdk/bin/javac
+ cat >jdk/bin/java <<EOF
+#!/bin/bash
+
+echo " Property settings:" >&2
+echo " java.version = 11.0.1 " >&2
+EOF
+ chmod +x jdk/bin/java
+ export JAVA_HOME="$PWD/jdk"
+ export PATH="$PWD/jdk/bin:$PATH"
+
+ bazel cquery --toolchain_resolution_debug --java_runtime_version=11 '//java/main:JavaExample' \
+ &>"${TEST_log}" || fail "Autodetecting a fake JDK version 11 and selecting it failed"
+ expect_log "@bazel_tools//tools/jdk:runtime_toolchain_type -> toolchain @local_jdk//:jdk"
+
+ bazel cquery --toolchain_resolution_debug --java_runtime_version=local_jdk_11 '//java/main:JavaExample' \
+ &>"${TEST_log}" || fail "Autodetecting a fake JDK version 8 and selecting it failed"
+ expect_log "@bazel_tools//tools/jdk:runtime_toolchain_type -> toolchain @local_jdk//:jdk"
+
+ bazel cquery --toolchain_resolution_debug --java_runtime_version=15 '//java/main:JavaExample' \
+ &>"${TEST_log}" || fail "Selecting prepackaged JDK version 15 failed"
+ expect_not_log "@bazel_tools//tools/jdk:runtime_toolchain_type -> toolchain @local_jdk//:jdk"
+}
+
+# Failure to detect JDK version shall be handled gracefully.
+function test_bazel_gracefully_handles_unknown_java() {
+ # Fake Java version 11
+ mkdir -p jdk/bin
+ touch jdk/bin/javac
+ chmod +x jdk/bin/javac
+ cat >jdk/bin/java <<EOF
+#!/bin/bash
+
+echo " Property settings:" >&2
+echo " java.version = xxx.superfuture.version " >&2
+EOF
+ chmod +x jdk/bin/java
+ export JAVA_HOME="$PWD/jdk"
+ export PATH="$PWD/jdk/bin:$PATH"
+
+ bazel cquery --toolchain_resolution_debug '//java/main:JavaExample' &>"${TEST_log}" \
+ || fail "Failed to resolve Java toolchain when version cannot be detected"
+ expect_log "@bazel_tools//tools/jdk:runtime_toolchain_type -> toolchain @local_jdk//:jdk"
+}
+
+# Bazel shall provide Java compilation toolchains that use local JDK.
+function test_bazel_compiles_with_localjdk() {
+ bazel aquery '//java/main:JavaExample' --extra_toolchains=@local_jdk//:all &>"${TEST_log}" \
+ || fail "Failed to use extra toolchains provided by @local_jdk repository."
+
+ expect_log "exec external/local_jdk/bin/java"
+ expect_not_log "exec external/remotejdk11_linux/bin/java"
+}
+
+run_suite "Tests detection of local JDK and that Bazel executes with a bundled JDK."
diff --git a/tools/jdk/BUILD b/tools/jdk/BUILD
index de37f89..4e4098d 100644
--- a/tools/jdk/BUILD
+++ b/tools/jdk/BUILD
@@ -24,7 +24,6 @@
"proguard_whitelister_test.py",
"proguard_whitelister_test_input.pgcfg",
"remote_java_repository.bzl",
- "toolchain_utils.bzl",
],
)
diff --git a/tools/jdk/local_java_repository.bzl b/tools/jdk/local_java_repository.bzl
index 51aa1d3..90f4547 100644
--- a/tools/jdk/local_java_repository.bzl
+++ b/tools/jdk/local_java_repository.bzl
@@ -26,7 +26,7 @@
strip_properties = [property.strip() for property in properties_out.splitlines()]
version_property = [property for property in strip_properties if property.startswith("java.version = ")]
if len(version_property) != 1:
- return "unknown"
+ return None
version_value = version_property[0][len("java.version = "):]
(major, minor, rest) = version_value.split(".", 2)
@@ -69,17 +69,23 @@
values = {"java_runtime_version": version},
visibility = ["//visibility:private"],
)
+ native.config_setting(
+ name = name + "_name_version_setting",
+ values = {"java_runtime_version": name + "_" + version},
+ visibility = ["//visibility:private"],
+ )
native.alias(
- name = name + "_version_or_name_setting",
+ name = name + "_settings_alias",
actual = select({
+ name + "_name_setting": name + "_name_setting",
name + "_version_setting": name + "_version_setting",
- "//conditions:default": name + "_name_setting",
+ "//conditions:default": name + "_name_version_setting",
}),
visibility = ["//visibility:private"],
)
native.toolchain(
name = "runtime_toolchain_definition",
- target_settings = [":%s_version_or_name_setting" % name],
+ target_settings = [":%s_settings_alias" % name],
toolchain_type = "@bazel_tools//tools/jdk:runtime_toolchain_type",
toolchain = runtime_name,
)
@@ -92,7 +98,7 @@
target_version = version,
java_runtime = runtime_name,
)
- else:
+ elif type(version) == type("") and version.isdigit() and int(version) > 8:
for version in range(8, int(version) + 1):
default_java_toolchain(
name = name + "_toolchain_java" + str(version),
@@ -101,6 +107,8 @@
java_runtime = runtime_name,
)
+ # else version is not recognized and no compilation toolchains are predefined
+
def _local_java_repository_impl(repository_ctx):
"""Repository rule local_java_repository implementation.
@@ -148,8 +156,8 @@
local_java_runtime(
name = "%s",
runtime_name = %s,
- java_home = "%s",
- version = "%s",
+ java_home = "%s",
+ version = "%s",
)
""" % (repository_ctx.name, runtime_name, java_home, version)
diff --git a/tools/jdk/toolchain_utils.bzl b/tools/jdk/toolchain_utils.bzl
deleted file mode 100644
index fd7482a..0000000
--- a/tools/jdk/toolchain_utils.bzl
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright 2019 The Bazel Authors. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-Finds the Java toolchain.
-
-Returns the toolchain if enabled, and falls back to a toolchain constructed from
-legacy toolchain selection.
-"""
-
-def find_java_toolchain(ctx, target):
- """
- Finds the Java toolchain.
-
- If the Java toolchain is in use, returns it. Otherwise, returns a Java
- toolchain derived from legacy toolchain selection.
-
- Args:
- ctx: The rule context for which to find a toolchain.
- target: A java_toolchain target (for legacy toolchain resolution).
-
- Returns:
- A JavaToolchainInfo.
- """
-
- _ignore = [ctx]
-
- return target[java_common.JavaToolchainInfo]
-
-def find_java_runtime_toolchain(ctx, target):
- """
- Finds the Java runtime.
-
- If the Java toolchain is in use, returns it. Otherwise, returns a Java
- runtime derived from legacy toolchain selection.
-
- Args:
- ctx: The rule context for which to find a toolchain.
- target: A java_runtime target (for legacy toolchain resolution).
-
- Returns:
- A JavaRuntimeInfo.
- """
-
- _ignore = [ctx]
-
- return target[java_common.JavaRuntimeInfo]