Skip to content

Commit

Permalink
[6.2.0] Add version to JavaRuntimeInfo (bazelbuild#17913)
Browse files Browse the repository at this point in the history
* Add version to JavaRuntimeInfo.

1. As suggested in bazelbuild#6354 (comment), 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 bazelbuild#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 bazelbuild#17775.

PiperOrigin-RevId: 518860040
Change-Id: I8223b6407dd09528a4e5a6bf12354e5fc68278c6

(cherry picked from commit 7556e11)

* 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 <benjamin@engflow.com>
  • Loading branch information
hvadehra and benjaminp committed Apr 3, 2023
1 parent 3ea18cc commit 2d04c91
Show file tree
Hide file tree
Showing 16 changed files with 83 additions and 20 deletions.
Expand Up @@ -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;
Expand Down Expand Up @@ -532,6 +533,9 @@ public Iterable<String> 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.
Expand Down
@@ -1,14 +1,15 @@
# 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")

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
Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -116,7 +117,8 @@ public ConfiguredTarget create(RuleContext ruleContext)
javaBinaryRunfilesPath,
hermeticInputs,
libModules,
hermeticStaticLibs);
hermeticStaticLibs,
ruleContext.attributes().get("version", INTEGER).toIntUnchecked());

TemplateVariableInfo templateVariableInfo =
new TemplateVariableInfo(
Expand Down
Expand Up @@ -51,7 +51,8 @@ public static JavaRuntimeInfo create(
PathFragment javaBinaryRunfilesPath,
NestedSet<Artifact> hermeticInputs,
@Nullable Artifact libModules,
ImmutableList<CcInfo> hermeticStaticLibs) {
ImmutableList<CcInfo> hermeticStaticLibs,
int version) {
return new JavaRuntimeInfo(
javaBaseInputs,
javaHome,
Expand All @@ -60,7 +61,8 @@ public static JavaRuntimeInfo create(
javaBinaryRunfilesPath,
hermeticInputs,
libModules,
hermeticStaticLibs);
hermeticStaticLibs,
version);
}

@Override
Expand Down Expand Up @@ -124,6 +126,7 @@ private static JavaRuntimeInfo from(RuleContext ruleContext, ToolchainInfo toolc
private final NestedSet<Artifact> hermeticInputs;
@Nullable private final Artifact libModules;
private final ImmutableList<CcInfo> hermeticStaticLibs;
private final int version;

private JavaRuntimeInfo(
NestedSet<Artifact> javaBaseInputs,
Expand All @@ -133,7 +136,8 @@ private JavaRuntimeInfo(
PathFragment javaBinaryRunfilesPath,
NestedSet<Artifact> hermeticInputs,
@Nullable Artifact libModules,
ImmutableList<CcInfo> hermeticStaticLibs) {
ImmutableList<CcInfo> hermeticStaticLibs,
int version) {
this.javaBaseInputs = javaBaseInputs;
this.javaHome = javaHome;
this.javaBinaryExecPath = javaBinaryExecPath;
Expand All @@ -142,6 +146,7 @@ private JavaRuntimeInfo(
this.hermeticInputs = hermeticInputs;
this.libModules = libModules;
this.hermeticStaticLibs = hermeticStaticLibs;
this.version = version;
}

/** All input artifacts in the javabase. */
Expand Down Expand Up @@ -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;
Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -72,6 +73,11 @@ public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env)
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
.add(attr("java_home", STRING))
.add(attr("output_licenses", LICENSE))
/* <!-- #BLAZE_RULE(java_runtime).ATTRIBUTE(version) -->
The feature version of the Java runtime. I.e., the integer returned by
<code>Runtime.version().feature()</code>.
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
.add(attr("version", INTEGER))
.build();
}

Expand Down
Expand Up @@ -95,4 +95,11 @@ public interface JavaRuntimeInfoApi extends StructApi {
doc = "Returns the JDK static libraries.",
structField = true)
Sequence<CcInfo> 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();
}
Expand Up @@ -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):",
Expand Down
Expand Up @@ -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),
Expand All @@ -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();
}
Expand Down
Expand Up @@ -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):",
Expand Down
6 changes: 4 additions & 2 deletions src/test/py/bazel/query_test.py
Expand Up @@ -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', [
Expand Down
4 changes: 2 additions & 2 deletions src/test/shell/bazel/starlark_repository_test.sh
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion tools/jdk/BUILD
Expand Up @@ -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",
Expand Down
1 change: 0 additions & 1 deletion tools/jdk/BUILD.tools
Expand Up @@ -210,7 +210,6 @@ alias(

exports_files([
"BUILD.java_tools",
"jdk.BUILD",
])

alias(
Expand Down
20 changes: 19 additions & 1 deletion tools/jdk/jdk.BUILD → 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"])
Expand Down Expand Up @@ -200,10 +216,12 @@ java_runtime(
":jdk-lib",
":jre-default",
],
version = ___RUNTIME_VERSION___,
)
config_setting(
name = "windows",
constraint_values = ["@platforms//os:windows"],
visibility = ["//visibility:private"],
)
"""
18 changes: 13 additions & 5 deletions tools/jdk/local_java_repository.bzl
Expand Up @@ -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",
Expand Down Expand Up @@ -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
Expand All @@ -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")
3 changes: 2 additions & 1 deletion tools/jdk/remote_java_repository.bzl
Expand Up @@ -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))
Expand Down Expand Up @@ -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(
Expand Down

0 comments on commit 2d04c91

Please sign in to comment.