From 53ff268c7e7d61614e3fdba74d55103e64b8f80b Mon Sep 17 00:00:00 2001 From: Googler Date: Thu, 16 Feb 2023 11:19:02 -0800 Subject: [PATCH] Support packaging the JDK default CDS image in hermetic deploy JAR using 'java_runtime.default_cds' attribute. If a hermetic 'java_runtime' target specifies the 'default_cds' attribute, and the 'java_binary' target does not provide its own CDS archive (by specifying the 'classlist' attribute), the java_runtime's default CDS is packaged when building a hermetic deploy JAR. This CL simply bridges the current hermetic support with the earlier work (unknown commit has added the related single JAR connection for embedding CDS) for deploy JAR embedded CDS. The 'java_runtime' change is in unknown commit, which has additional integration test cases for the hermetic default CDS. #hermetic-java-static-linking PiperOrigin-RevId: 510195888 Change-Id: I51e8fef364bcb7c53c42d010cd51dbc4f689247c --- .../devtools/build/lib/rules/java/JavaBinary.java | 8 ++++++++ .../devtools/build/lib/rules/java/JavaRuntime.java | 5 +++++ .../build/lib/rules/java/JavaRuntimeInfo.java | 11 +++++++++++ .../build/lib/rules/java/JavaRuntimeRule.java | 12 ++++++++++++ .../starlarkbuildapi/java/JavaRuntimeInfoApi.java | 9 +++++++++ .../common/java/java_binary_deploy_jar.bzl | 11 +++++++---- .../build/lib/rules/java/JavaRuntimeInfoTest.java | 2 ++ 7 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java index aa91b1f495c7e6..1034f43099fa7e 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java @@ -411,6 +411,7 @@ public ConfiguredTarget create(RuleContext ruleContext) ImmutableList deployManifestLines = getDeployManifestLines(ruleContext, originalMainClass); + // Create the java_binary target specific CDS archive. Artifact jsa = createSharedArchive(ruleContext, javaArtifacts, attributes); if (ruleContext.isAttrDefined("hermetic", BOOLEAN) @@ -428,6 +429,13 @@ public ConfiguredTarget create(RuleContext ruleContext) .setLibModules(javaRuntime.libModules()) .setHermeticInputs(javaRuntime.hermeticInputs()); } + + if (jsa == null) { + // Use the JDK default CDS specified by the JavaRuntime if the + // java_binary target specific CDS archive is null, when building + // a hermetic deploy JAR. + jsa = javaRuntime.defaultCDS(); + } } deployArchiveBuilder 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 467d772e6c7ebf..183bb35bd3c670 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 @@ -99,6 +99,10 @@ public ConfiguredTarget create(RuleContext ruleContext) ImmutableList hermeticStaticLibs = ImmutableList.copyOf(ruleContext.getPrerequisites("hermetic_static_libs", CcInfo.PROVIDER)); + // If a runtime does not set default_cds in hermetic mode, it is not fatal. + // We can skip the default CDS in the check below. + Artifact defaultCDS = ruleContext.getPrerequisiteArtifact("default_cds"); + if ((!hermeticInputs.isEmpty() || libModules != null || !hermeticStaticLibs.isEmpty()) && (hermeticInputs.isEmpty() || libModules == null || hermeticStaticLibs.isEmpty())) { ruleContext.attributeError( @@ -124,6 +128,7 @@ public ConfiguredTarget create(RuleContext ruleContext) javaBinaryRunfilesPath, hermeticInputs, libModules, + defaultCDS, hermeticStaticLibs); TemplateVariableInfo 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 43e693d1dfde15..5d0cd11f1a9efc 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,6 +51,7 @@ public static JavaRuntimeInfo create( PathFragment javaBinaryRunfilesPath, NestedSet hermeticInputs, @Nullable Artifact libModules, + @Nullable Artifact defaultCDS, ImmutableList hermeticStaticLibs) { return new JavaRuntimeInfo( javaBaseInputs, @@ -60,6 +61,7 @@ public static JavaRuntimeInfo create( javaBinaryRunfilesPath, hermeticInputs, libModules, + defaultCDS, hermeticStaticLibs); } @@ -121,6 +123,7 @@ private static JavaRuntimeInfo from(RuleContext ruleContext, ToolchainInfo toolc private final PathFragment javaBinaryRunfilesPath; private final NestedSet hermeticInputs; @Nullable private final Artifact libModules; + @Nullable private final Artifact defaultCDS; private final ImmutableList hermeticStaticLibs; private JavaRuntimeInfo( @@ -131,6 +134,7 @@ private JavaRuntimeInfo( PathFragment javaBinaryRunfilesPath, NestedSet hermeticInputs, @Nullable Artifact libModules, + @Nullable Artifact defaultCDS, ImmutableList hermeticStaticLibs) { this.javaBaseInputs = javaBaseInputs; this.javaHome = javaHome; @@ -139,6 +143,7 @@ private JavaRuntimeInfo( this.javaBinaryRunfilesPath = javaBinaryRunfilesPath; this.hermeticInputs = hermeticInputs; this.libModules = libModules; + this.defaultCDS = defaultCDS; this.hermeticStaticLibs = hermeticStaticLibs; } @@ -199,6 +204,12 @@ public Artifact libModules() { return libModules; } + @Override + @Nullable + public Artifact defaultCDS() { + return defaultCDS; + } + public ImmutableList hermeticStaticLibs() { return hermeticStaticLibs; } 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 3d3c49ed3217aa..50a6e5c7fa34b1 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 @@ -55,6 +55,18 @@ public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) .singleArtifact() .allowedFileTypes(FileTypeSet.ANY_FILE) .exec()) + /* + Default CDS archive for hermetic java_runtime. When hermetic + is enabled for a java_binary target and if the target does not + provide its own CDS archive by specifying the + classlist attribute, + the java_runtime default CDS is packaged in the hermetic deploy JAR. + */ + .add( + attr("default_cds", LABEL) + .singleArtifact() + .allowedFileTypes(FileTypeSet.ANY_FILE) + .exec()) .add( attr("hermetic_static_libs", LABEL_LIST) .mandatoryProviders(StarlarkProviderIdentifier.forKey(CcInfo.PROVIDER.getKey())) 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..73c791dfb921db 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 @@ -89,6 +89,15 @@ public interface JavaRuntimeInfoApi extends StructApi { @Nullable FileApi libModules(); + /** The JDK default CDS. */ + @StarlarkMethod( + name = "default_cds", + doc = "Returns the JDK default CDS archive.", + structField = true, + allowReturnNones = true) + @Nullable + FileApi defaultCDS(); + /** The JDK static libraries needed for hermetic deployments. */ @StarlarkMethod( name = "hermetic_static_libs", diff --git a/src/main/starlark/builtins_bzl/common/java/java_binary_deploy_jar.bzl b/src/main/starlark/builtins_bzl/common/java/java_binary_deploy_jar.bzl index cf0e98d29d2ee3..6751616c1e9831 100644 --- a/src/main/starlark/builtins_bzl/common/java/java_binary_deploy_jar.bzl +++ b/src/main/starlark/builtins_bzl/common/java/java_binary_deploy_jar.bzl @@ -181,10 +181,6 @@ def _create_deploy_archive( if one_version_level == "WARNING": args.add("--succeed_on_found_violations") - if shared_archive: - input_files.append(shared_archive) - args.add("--cds_archive", shared_archive) - if multi_release: args.add("--multi_release") @@ -197,6 +193,13 @@ def _create_deploy_archive( args.add_all("--resources", hermetic_files) input_files.append(lib_modules) + if shared_archive == None: + shared_archive = runtime.default_cds + + if shared_archive: + input_files.append(shared_archive) + args.add("--cds_archive", shared_archive) + args.add_all("--add_exports", add_exports) args.add_all("--add_opens", add_opens) 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..60cf66d994585d 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,6 +37,7 @@ public void equalityIsObjectIdentity() { PathFragment.create(""), NestedSetBuilder.emptySet(Order.STABLE_ORDER), null, + null, ImmutableList.of()); JavaRuntimeInfo b = JavaRuntimeInfo.create( @@ -47,6 +48,7 @@ public void equalityIsObjectIdentity() { PathFragment.create(""), NestedSetBuilder.emptySet(Order.STABLE_ORDER), null, + null, ImmutableList.of()); new EqualsTester().addEqualityGroup(a).addEqualityGroup(b).testEquals();