From 8294787b7c012491bafa67ef3595925275f6ab13 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 30 Dec 2022 14:38:28 -0600 Subject: [PATCH] Add version to JavaRuntimeInfo. 1. As suggested in https://github.com/bazelbuild/bazel/issues/6354#issuecomment-1310489402, add a JDK version attribute to the java_runtime rule. This will allow changing behavior based on the Java runtime's version. 2. As an application of the above, pass -Djava.security.manager=allow to Java tests on JDK 17+. This makes the Bazel Java test runner to work on JDK 19. Fixes https://github.com/bazelbuild/bazel/issues/14502. 3. To make the above generally useful, the remote_java_repository and local_java_repository must set the new version attribute in the java_runtime rules that they create. This means the old static jdk.BUILD file no longer suffices. Move the contents of jdk.BUILD into a Starlark file, so the version can be interpolated in by JDK repository rules and macros. (This isn't the nicest, but local_java_repository is not a repository rule, so the template cannot be in a non-Starlark file.) --- .../lib/bazel/rules/java/BazelJavaSemantics.java | 4 ++++ .../lib/bazel/rules/java/jdk.WORKSPACE.tmpl | 3 ++- .../build/lib/rules/java/JavaRuntime.java | 4 +++- .../build/lib/rules/java/JavaRuntimeInfo.java | 16 +++++++++++++--- .../build/lib/rules/java/JavaRuntimeRule.java | 5 +++++ .../java/JavaRuntimeInfoApi.java | 7 +++++++ .../bazel/java/bazel_java_binary.bzl | 2 ++ .../lib/analysis/mock/BazelAnalysisMock.java | 1 + .../lib/rules/java/JavaRuntimeInfoTest.java | 6 ++++-- src/test/py/bazel/query_test.py | 2 +- tools/jdk/BUILD | 2 +- tools/jdk/BUILD.tools | 1 - tools/jdk/{jdk.BUILD => jdk_build_file.bzl} | 4 +++- tools/jdk/local_java_repository.bzl | 11 +++++++++-- tools/jdk/remote_java_repository.bzl | 3 ++- 15 files changed, 57 insertions(+), 14 deletions(-) rename tools/jdk/{jdk.BUILD => jdk_build_file.bzl} (92%) diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java index 5869d56a2363ba..4e1ce53450daf3 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java @@ -57,6 +57,7 @@ import com.google.devtools.build.lib.rules.java.JavaConfiguration.OneVersionEnforcementLevel; import com.google.devtools.build.lib.rules.java.JavaHelper; import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider; +import com.google.devtools.build.lib.rules.java.JavaRuntimeInfo; import com.google.devtools.build.lib.rules.java.JavaSemantics; import com.google.devtools.build.lib.rules.java.JavaSourceJarsProvider; import com.google.devtools.build.lib.rules.java.JavaTargetAttributes; @@ -548,6 +549,9 @@ public Iterable getJvmFlags( if (testClass == null) { ruleContext.ruleError("cannot determine test class"); } else { + if (JavaRuntimeInfo.from(ruleContext).version() >= 17) { + jvmFlags.add("-Djava.security.manager=allow"); + } // Always run junit tests with -ea (enable assertion) jvmFlags.add("-ea"); // "suite" is a misnomer. diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/jdk.WORKSPACE.tmpl b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/jdk.WORKSPACE.tmpl index 29bd3a80af5033..3096a337fc9bb8 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/jdk.WORKSPACE.tmpl +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/jdk.WORKSPACE.tmpl @@ -1,6 +1,7 @@ # External dependencies for the java_* rules. load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") +load("@bazel_tools//tools/jdk:jdk_build_file.bzl", "JDK_BUILD_TEMPLATE") load("@bazel_tools//tools/jdk:local_java_repository.bzl", "local_java_repository") load("@bazel_tools//tools/jdk:remote_java_repository.bzl", "remote_java_repository") @@ -8,7 +9,7 @@ maybe( local_java_repository, name = "local_jdk", java_home = DEFAULT_SYSTEM_JAVABASE, - build_file = "@bazel_tools//tools/jdk:jdk.BUILD", + build_file_content = JDK_BUILD_TEMPLATE, ) # OpenJDK distributions that should only be downloaded on demand (e.g. when diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntime.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntime.java index 183bb35bd3c670..a65f31ca3b6c2f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntime.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntime.java @@ -15,6 +15,7 @@ package com.google.devtools.build.lib.rules.java; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.devtools.build.lib.packages.Type.INTEGER; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -129,7 +130,8 @@ public ConfiguredTarget create(RuleContext ruleContext) hermeticInputs, libModules, defaultCDS, - hermeticStaticLibs); + hermeticStaticLibs, + ruleContext.attributes().get("version", INTEGER).toIntUnchecked()); TemplateVariableInfo templateVariableInfo = new TemplateVariableInfo( diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeInfo.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeInfo.java index d8f91904543a40..579a87924ade15 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeInfo.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeInfo.java @@ -52,7 +52,8 @@ public static JavaRuntimeInfo create( NestedSet hermeticInputs, @Nullable Artifact libModules, @Nullable Artifact defaultCDS, - ImmutableList hermeticStaticLibs) { + ImmutableList hermeticStaticLibs, + int version) { return new JavaRuntimeInfo( javaBaseInputs, javaHome, @@ -62,7 +63,8 @@ public static JavaRuntimeInfo create( hermeticInputs, libModules, defaultCDS, - hermeticStaticLibs); + hermeticStaticLibs, + version); } @Override @@ -125,6 +127,7 @@ private static JavaRuntimeInfo from(RuleContext ruleContext, ToolchainInfo toolc @Nullable private final Artifact libModules; @Nullable private final Artifact defaultCDS; private final ImmutableList hermeticStaticLibs; + private final int version; private JavaRuntimeInfo( NestedSet javaBaseInputs, @@ -135,7 +138,8 @@ private JavaRuntimeInfo( NestedSet hermeticInputs, @Nullable Artifact libModules, @Nullable Artifact defaultCDS, - ImmutableList hermeticStaticLibs) { + ImmutableList hermeticStaticLibs, + int version) { this.javaBaseInputs = javaBaseInputs; this.javaHome = javaHome; this.javaBinaryExecPath = javaBinaryExecPath; @@ -145,6 +149,7 @@ private JavaRuntimeInfo( this.libModules = libModules; this.defaultCDS = defaultCDS; this.hermeticStaticLibs = hermeticStaticLibs; + this.version = version; } /** All input artifacts in the javabase. */ @@ -232,6 +237,11 @@ public Depset starlarkJavaBaseInputs() { return Depset.of(Artifact.class, javaBaseInputs()); } + @Override + public int version() { + return version; + } + @Override public com.google.devtools.build.lib.packages.Provider getProvider() { return PROVIDER; diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeRule.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeRule.java index 50a6e5c7fa34b1..ce876ebae67df0 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeRule.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeRule.java @@ -18,6 +18,7 @@ import static com.google.devtools.build.lib.packages.BuildType.LABEL; import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST; import static com.google.devtools.build.lib.packages.BuildType.LICENSE; +import static com.google.devtools.build.lib.packages.Type.INTEGER; import static com.google.devtools.build.lib.packages.Type.STRING; import com.google.devtools.build.lib.analysis.BaseRuleClasses; @@ -83,6 +84,10 @@ public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) */ .add(attr("java_home", STRING)) .add(attr("output_licenses", LICENSE)) + /* + The major version of the Java runtime. + */ + .add(attr("version", INTEGER)) .build(); } diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaRuntimeInfoApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaRuntimeInfoApi.java index 73c791dfb921db..55d89bb397c7ab 100644 --- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaRuntimeInfoApi.java +++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaRuntimeInfoApi.java @@ -104,4 +104,11 @@ public interface JavaRuntimeInfoApi extends StructApi { doc = "Returns the JDK static libraries.", structField = true) Sequence starlarkHermeticStaticLibs(); + + /** The Java version of the runtime. This may be 0 if the version is unknown. */ + @StarlarkMethod( + name = "version", + doc = "The Java version of the runtime. This may be 0 if the version is unknown.", + structField = true) + int version(); } diff --git a/src/main/starlark/builtins_bzl/bazel/java/bazel_java_binary.bzl b/src/main/starlark/builtins_bzl/bazel/java/bazel_java_binary.bzl index 5c8c299f2fc218..866383a97aa004 100644 --- a/src/main/starlark/builtins_bzl/bazel/java/bazel_java_binary.bzl +++ b/src/main/starlark/builtins_bzl/bazel/java/bazel_java_binary.bzl @@ -54,6 +54,8 @@ def _bazel_java_binary_impl(ctx): ) if ctx.attr.use_testrunner: + if semantics.find_java_runtime_toolchain(ctx).version >= 17: + jvm_flags.append("-Djava.security.manager=allow"); test_class = ctx.attr.test_class if hasattr(ctx.attr, "test_class") else "" if test_class == "": test_class = helper.primary_class(ctx) diff --git a/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java b/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java index ccf37edb96b154..8d9297b920fdd6 100644 --- a/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java +++ b/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java @@ -580,6 +580,7 @@ public void setupMockToolsRepository(MockToolsConfig config) throws IOException "", "def http_jar(**kwargs):", " pass"); + config.create("embedded_tools/tools/jdk/jdk_build_file.bzl", "JDK_BUILD_TEMPLATE = ''"); config.create( "embedded_tools/tools/jdk/local_java_repository.bzl", "def local_java_repository(**kwargs):", diff --git a/src/test/java/com/google/devtools/build/lib/rules/java/JavaRuntimeInfoTest.java b/src/test/java/com/google/devtools/build/lib/rules/java/JavaRuntimeInfoTest.java index 60cf66d994585d..d011d44a980493 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/java/JavaRuntimeInfoTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/java/JavaRuntimeInfoTest.java @@ -38,7 +38,8 @@ public void equalityIsObjectIdentity() { NestedSetBuilder.emptySet(Order.STABLE_ORDER), null, null, - ImmutableList.of()); + ImmutableList.of(), + 17); JavaRuntimeInfo b = JavaRuntimeInfo.create( NestedSetBuilder.emptySet(Order.STABLE_ORDER), @@ -49,7 +50,8 @@ public void equalityIsObjectIdentity() { NestedSetBuilder.emptySet(Order.STABLE_ORDER), null, null, - ImmutableList.of()); + ImmutableList.of(), + 17); new EqualsTester().addEqualityGroup(a).addEqualityGroup(b).testEquals(); } diff --git a/src/test/py/bazel/query_test.py b/src/test/py/bazel/query_test.py index ee52d932ed57a4..01237ebab7b2da 100644 --- a/src/test/py/bazel/query_test.py +++ b/src/test/py/bazel/query_test.py @@ -41,7 +41,7 @@ def testSimpleQuery(self): def testQueryFilesUsedByRepositoryRules(self): self.ScratchFile('WORKSPACE') self._AssertQueryOutputContains("kind('source file', deps(//external:*))", - '@bazel_tools//tools/jdk:jdk.BUILD') + '@bazel_tools//tools/genrule:genrule-setup.sh') def testBuildFilesForExternalRepos_Simple(self): self.ScratchFile('WORKSPACE', [ diff --git a/tools/jdk/BUILD b/tools/jdk/BUILD index 37da6445a4705e..c6998668444117 100644 --- a/tools/jdk/BUILD +++ b/tools/jdk/BUILD @@ -16,7 +16,7 @@ filegroup( "default_java_toolchain.bzl", "fail_rule.bzl", "java_toolchain_alias.bzl", - "jdk.BUILD", + "jdk_build_file.bzl", "local_java_repository.bzl", "nosystemjdk/README", "proguard_whitelister.py", diff --git a/tools/jdk/BUILD.tools b/tools/jdk/BUILD.tools index 61aa9ff6962050..adbcd3da50d778 100644 --- a/tools/jdk/BUILD.tools +++ b/tools/jdk/BUILD.tools @@ -195,7 +195,6 @@ alias( exports_files([ "BUILD.java_tools", - "jdk.BUILD", ]) alias( diff --git a/tools/jdk/jdk.BUILD b/tools/jdk/jdk_build_file.bzl similarity index 92% rename from tools/jdk/jdk.BUILD rename to tools/jdk/jdk_build_file.bzl index 427da22cbb9086..21efaaa2e33e7f 100644 --- a/tools/jdk/jdk.BUILD +++ b/tools/jdk/jdk_build_file.bzl @@ -1,4 +1,4 @@ -load("@rules_java//java:defs.bzl", "java_runtime") +JDK_BUILD_TEMPLATE = """load("@rules_java//java:defs.bzl", "java_runtime") package(default_visibility = ["//visibility:public"]) @@ -67,4 +67,6 @@ java_runtime( ":jdk-lib", ":jre", ], + version = ___VERSION___, ) +""" \ No newline at end of file diff --git a/tools/jdk/local_java_repository.bzl b/tools/jdk/local_java_repository.bzl index 205a763e07280e..96068b49893d0f 100644 --- a/tools/jdk/local_java_repository.bzl +++ b/tools/jdk/local_java_repository.bzl @@ -147,8 +147,13 @@ def _local_java_repository_impl(repository_ctx): # Prepare BUILD file using "local_java_runtime" macro build_file = "" + if repository_ctx.attr.build_file_content: + build_file = repository_ctx.attr.build_file_content if repository_ctx.attr.build_file != None: + if build_file != "": + fail("build_file and build_file_content are exclusive") build_file = repository_ctx.read(repository_ctx.path(repository_ctx.attr.build_file)) + build_file = build_file.replace("___VERSION___", version if version else "0") runtime_name = '"jdk"' if repository_ctx.attr.build_file else None local_java_runtime_macro = """ @@ -201,10 +206,11 @@ _local_java_repository_rule = repository_rule( "java_home": attr.string(), "version": attr.string(), "build_file": attr.label(), + "build_file_content": attr.string(), }, ) -def local_java_repository(name, java_home, version = "", build_file = None): +def local_java_repository(name, java_home, version = "", build_file = None, build_file_content = None): """Registers a runtime toolchain for local JDK and creates an unregistered compile toolchain. Toolchain resolution is constrained with --java_runtime_version flag @@ -220,7 +226,8 @@ def local_java_repository(name, java_home, version = "", build_file = None): name: A unique name for this rule. java_home: Location of the JDK imported. build_file: optionally BUILD file template + build_file_content: optional BUILD file template as a string version: optionally java version """ - _local_java_repository_rule(name = name, java_home = java_home, version = version, build_file = build_file) + _local_java_repository_rule(name = name, java_home = java_home, version = version, build_file = build_file, build_file_content = build_file_content) native.register_toolchains("@" + name + "//:runtime_toolchain_definition") diff --git a/tools/jdk/remote_java_repository.bzl b/tools/jdk/remote_java_repository.bzl index 791696c7dc9500..b52d4cef54c283 100644 --- a/tools/jdk/remote_java_repository.bzl +++ b/tools/jdk/remote_java_repository.bzl @@ -18,6 +18,7 @@ Rule remote_java_repository imports and registers JDK with the toolchain resolut """ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +load("@bazel_tools//tools/jdk:jdk_build_file.bzl", "JDK_BUILD_TEMPLATE") def _toolchain_config_impl(ctx): ctx.file("WORKSPACE", "workspace(name = \"{name}\")\n".format(name = ctx.name)) @@ -47,7 +48,7 @@ def remote_java_repository(name, version, target_compatible_with = None, prefix """ http_archive( name = name, - build_file = "@bazel_tools//tools/jdk:jdk.BUILD", + build_file_content = JDK_BUILD_TEMPLATE.replace("___VERSION___", version), **kwargs ) _toolchain_config(