From 2d04c91327cadb3f0d53bceea117d3939a25e143 Mon Sep 17 00:00:00 2001 From: hvadehra Date: Mon, 3 Apr 2023 14:49:17 +0200 Subject: [PATCH] [6.2.0] Add version to JavaRuntimeInfo (#17913) * 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.) Closes #17775. PiperOrigin-RevId: 518860040 Change-Id: I8223b6407dd09528a4e5a6bf12354e5fc68278c6 (cherry picked from commit 7556e1107b666d10b660470a571631463c7eb4ec) * Use string.replace() instead of string.format() to avoid issues with select{} in the template string * Remove test and fix formatting * Fix starlark_repository_test Change the grep pattern to exactly match what the test is looking for. The old pattern would match BUILD file content from the jdk_build_file.bzl template --------- Co-authored-by: Benjamin Peterson --- .../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 | 6 ++++++ .../java/JavaRuntimeInfoApi.java | 7 +++++++ .../lib/analysis/mock/BazelAnalysisMock.java | 1 + .../lib/rules/java/JavaRuntimeInfoTest.java | 6 ++++-- .../packages/BazelPackageLoaderTest.java | 2 ++ src/test/py/bazel/query_test.py | 6 ++++-- .../shell/bazel/starlark_repository_test.sh | 4 ++-- tools/jdk/BUILD | 2 +- tools/jdk/BUILD.tools | 1 - tools/jdk/{jdk.BUILD => jdk_build_file.bzl} | 20 ++++++++++++++++++- tools/jdk/local_java_repository.bzl | 18 ++++++++++++----- tools/jdk/remote_java_repository.bzl | 3 ++- 16 files changed, 83 insertions(+), 20 deletions(-) rename tools/jdk/{jdk.BUILD => jdk_build_file.bzl} (84%) 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 d74b95af8c2f52..1e6215256cc94b 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 @@ -54,6 +54,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; @@ -532,6 +533,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 e4132727095c69..91365fc3f1a569 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 b77cd763b771a0..5831083eca214a 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; @@ -116,7 +117,8 @@ public ConfiguredTarget create(RuleContext ruleContext) javaBinaryRunfilesPath, hermeticInputs, libModules, - 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 a1fdf3c2ca1182..9e9f0c1b2cec72 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 @@ -51,7 +51,8 @@ public static JavaRuntimeInfo create( PathFragment javaBinaryRunfilesPath, NestedSet hermeticInputs, @Nullable Artifact libModules, - ImmutableList hermeticStaticLibs) { + ImmutableList hermeticStaticLibs, + int version) { return new JavaRuntimeInfo( javaBaseInputs, javaHome, @@ -60,7 +61,8 @@ public static JavaRuntimeInfo create( javaBinaryRunfilesPath, hermeticInputs, libModules, - hermeticStaticLibs); + hermeticStaticLibs, + version); } @Override @@ -124,6 +126,7 @@ private static JavaRuntimeInfo from(RuleContext ruleContext, ToolchainInfo toolc private final NestedSet hermeticInputs; @Nullable private final Artifact libModules; private final ImmutableList hermeticStaticLibs; + private final int version; private JavaRuntimeInfo( NestedSet javaBaseInputs, @@ -133,7 +136,8 @@ private JavaRuntimeInfo( PathFragment javaBinaryRunfilesPath, NestedSet hermeticInputs, @Nullable Artifact libModules, - ImmutableList hermeticStaticLibs) { + ImmutableList hermeticStaticLibs, + int version) { this.javaBaseInputs = javaBaseInputs; this.javaHome = javaHome; this.javaBinaryExecPath = javaBinaryExecPath; @@ -142,6 +146,7 @@ private JavaRuntimeInfo( this.hermeticInputs = hermeticInputs; this.libModules = libModules; this.hermeticStaticLibs = hermeticStaticLibs; + this.version = version; } /** All input artifacts in the javabase. */ @@ -223,6 +228,11 @@ public Depset starlarkJavaBaseInputs() { return Depset.of(Artifact.TYPE, 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 5c0378771884cf..eb2cb2b4cc84bc 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; @@ -72,6 +73,11 @@ public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) */ .add(attr("java_home", STRING)) .add(attr("output_licenses", LICENSE)) + /* + The feature version of the Java runtime. I.e., the integer returned by + Runtime.version().feature(). + */ + .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 aa195cfe367238..b5199849952df2 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 @@ -95,4 +95,11 @@ public interface JavaRuntimeInfoApi extends StructApi { doc = "Returns the JDK static libraries.", structField = true) Sequence starlarkHermeticStaticLibs(); + + /** The Java feature version of the runtime. This is 0 if the version is unknown. */ + @StarlarkMethod( + name = "version", + doc = "The Java feature version of the runtime. This is 0 if the version is unknown.", + structField = true) + int version(); } 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 5d196a2e8c3004..378768323a32e9 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 @@ -578,6 +578,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 509f7b50d3b1e5..2d5cfcbcd6494d 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 @@ -37,7 +37,8 @@ public void equalityIsObjectIdentity() { PathFragment.create(""), NestedSetBuilder.emptySet(Order.STABLE_ORDER), null, - ImmutableList.of()); + ImmutableList.of(), + 17); JavaRuntimeInfo b = JavaRuntimeInfo.create( NestedSetBuilder.emptySet(Order.STABLE_ORDER), @@ -47,7 +48,8 @@ public void equalityIsObjectIdentity() { PathFragment.create(""), NestedSetBuilder.emptySet(Order.STABLE_ORDER), null, - ImmutableList.of()); + ImmutableList.of(), + 17); new EqualsTester().addEqualityGroup(a).addEqualityGroup(b).testEquals(); } diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/packages/BazelPackageLoaderTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/packages/BazelPackageLoaderTest.java index aa63fa25e9823a..7103946d2043e1 100644 --- a/src/test/java/com/google/devtools/build/lib/skyframe/packages/BazelPackageLoaderTest.java +++ b/src/test/java/com/google/devtools/build/lib/skyframe/packages/BazelPackageLoaderTest.java @@ -106,6 +106,8 @@ private static void mockEmbeddedTools(Path embeddedBinaries) throws IOException " if name not in native.existing_rules():", " repo_rule(name = name, **kwargs)"); FileSystemUtils.writeIsoLatin1(tools.getRelative("tools/jdk/BUILD")); + FileSystemUtils.writeIsoLatin1( + tools.getRelative("tools/jdk/jdk_build_file.bzl"), "JDK_BUILD_TEMPLATE = ''"); FileSystemUtils.writeIsoLatin1( tools.getRelative("tools/jdk/local_java_repository.bzl"), "def local_java_repository(**kwargs):", diff --git a/src/test/py/bazel/query_test.py b/src/test/py/bazel/query_test.py index ee52d932ed57a4..12804d7dee7faa 100644 --- a/src/test/py/bazel/query_test.py +++ b/src/test/py/bazel/query_test.py @@ -40,8 +40,10 @@ def testSimpleQuery(self): def testQueryFilesUsedByRepositoryRules(self): self.ScratchFile('WORKSPACE') - self._AssertQueryOutputContains("kind('source file', deps(//external:*))", - '@bazel_tools//tools/jdk:jdk.BUILD') + self._AssertQueryOutputContains( + "kind('source file', deps(//external:*))", + '@bazel_tools//tools/genrule:genrule-setup.sh', + ) def testBuildFilesForExternalRepos_Simple(self): self.ScratchFile('WORKSPACE', [ diff --git a/src/test/shell/bazel/starlark_repository_test.sh b/src/test/shell/bazel/starlark_repository_test.sh index afec945adb7ebc..1f526efcbdeb4c 100755 --- a/src/test/shell/bazel/starlark_repository_test.sh +++ b/src/test/shell/bazel/starlark_repository_test.sh @@ -1451,9 +1451,9 @@ EOF echo "new value" > reference.txt.shadow bazel sync --configure --experimental_repository_resolved_file=resolved.bzl \ 2>&1 || fail "Expected sync --configure to succeed" - grep -q 'name.*configure' resolved.bzl \ + grep -q '"name": "configure"' resolved.bzl \ || fail "Expected 'configure' to be synced" - grep -q 'name.*source' resolved.bzl \ + grep -q '"name": "source"' resolved.bzl \ && fail "Expected 'source' not to be synced" || : bazel build //:source //:configure diff --git a/tools/jdk/BUILD b/tools/jdk/BUILD index b78e0a337094ce..56c6d70126382d 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 a8bb7c78899595..5d00b96cefbef8 100644 --- a/tools/jdk/BUILD.tools +++ b/tools/jdk/BUILD.tools @@ -210,7 +210,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 84% rename from tools/jdk/jdk.BUILD rename to tools/jdk/jdk_build_file.bzl index 86be2fe831955d..419f3631fe7f5c 100644 --- a/tools/jdk/jdk.BUILD +++ b/tools/jdk/jdk_build_file.bzl @@ -1,4 +1,20 @@ -load("@rules_java//java:defs.bzl", "java_import", "java_runtime") +# Copyright 2023 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. + +"""A templated BUILD file for Java repositories.""" + +JDK_BUILD_TEMPLATE = """load("@rules_java//java:defs.bzl", "java_import", "java_runtime") package(default_visibility = ["//visibility:public"]) @@ -200,6 +216,7 @@ java_runtime( ":jdk-lib", ":jre-default", ], + version = ___RUNTIME_VERSION___, ) config_setting( @@ -207,3 +224,4 @@ config_setting( constraint_values = ["@platforms//os:windows"], visibility = ["//visibility:private"], ) +""" diff --git a/tools/jdk/local_java_repository.bzl b/tools/jdk/local_java_repository.bzl index 05686c70b44be7..0af39c1dd08c38 100644 --- a/tools/jdk/local_java_repository.bzl +++ b/tools/jdk/local_java_repository.bzl @@ -144,11 +144,17 @@ def _local_java_repository_impl(repository_ctx): version = repository_ctx.attr.version if repository_ctx.attr.version != "" else _detect_java_version(repository_ctx, java_bin) # Prepare BUILD file using "local_java_runtime" macro - build_file = "" - if repository_ctx.attr.build_file != None: + if repository_ctx.attr.build_file_content and repository_ctx.attr.build_file: + fail("build_file and build_file_content are exclusive") + if repository_ctx.attr.build_file_content: + build_file = repository_ctx.attr.build_file_content + elif repository_ctx.attr.build_file: build_file = repository_ctx.read(repository_ctx.path(repository_ctx.attr.build_file)) + else: + build_file = "" + build_file = build_file.replace("___RUNTIME_VERSION___", version if version.isdigit() else "0") - runtime_name = '"jdk"' if repository_ctx.attr.build_file else None + runtime_name = '"jdk"' if build_file else None local_java_runtime_macro = """ local_java_runtime( name = "%s", @@ -199,10 +205,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 @@ -218,7 +225,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..6161d45e8a44bf 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("___RUNTIME_VERSION___", version), **kwargs ) _toolchain_config(