diff --git a/spring-boot-project/spring-boot-starters/spring-boot-starter-parent/build.gradle b/spring-boot-project/spring-boot-starters/spring-boot-starter-parent/build.gradle index d73bcc0cbb..2b2028ea2c 100644 --- a/spring-boot-project/spring-boot-starters/spring-boot-starter-parent/build.gradle +++ b/spring-boot-project/spring-boot-starters/spring-boot-starter-parent/build.gradle @@ -233,6 +233,17 @@ publishing.publications.withType(MavenPublication) { build { pluginManagement { plugins { + plugin { + delegate.groupId('org.apache.maven.plugins') + delegate.artifactId('maven-jar-plugin') + configuration { + archive { + manifestEntries { + delegate.'Spring-Boot-Native-Processed'("true") + } + } + } + } plugin { delegate.groupId('org.springframework.boot') delegate.artifactId('spring-boot-maven-plugin') diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/NativeImagePluginAction.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/NativeImagePluginAction.java index 7526220cb4..612479175d 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/NativeImagePluginAction.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/NativeImagePluginAction.java @@ -59,10 +59,11 @@ class NativeImagePluginAction implements PluginApplicationAction { SourceSetContainer sourceSets = javaPluginExtension.getSourceSets(); GraalVMExtension graalVmExtension = configureGraalVmExtension(project); configureMainNativeBinaryClasspath(project, sourceSets, graalVmExtension); - configureTestNativeBinaryClasspath(project, sourceSets, graalVmExtension); + configureTestNativeBinaryClasspath(sourceSets, graalVmExtension); configureGraalVmReachabilityExtension(graalVmExtension); copyReachabilityMetadataToBootJar(project); configureBootBuildImageToProduceANativeImage(project); + configureJarManifestNativeAttribute(project); }); } @@ -85,8 +86,7 @@ class NativeImagePluginAction implements PluginApplicationAction { return !SpringBootPlugin.DEVELOPMENT_ONLY_CONFIGURATION_NAME.equals(configuration.getName()); } - private void configureTestNativeBinaryClasspath(Project project, SourceSetContainer sourceSets, - GraalVMExtension graalVmExtension) { + private void configureTestNativeBinaryClasspath(SourceSetContainer sourceSets, GraalVMExtension graalVmExtension) { FileCollection runtimeClasspath = sourceSets.getByName(SpringBootAotPlugin.AOT_TEST_SOURCE_SET_NAME) .getRuntimeClasspath(); graalVmExtension.getBinaries().getByName(NativeImagePlugin.NATIVE_TEST_EXTENSION).classpath(runtimeClasspath); @@ -119,4 +119,11 @@ class NativeImagePluginAction implements PluginApplicationAction { }); } + private void configureJarManifestNativeAttribute(Project project) { + project.getTasks() + .named(SpringBootPlugin.BOOT_JAR_TASK_NAME, BootJar.class) + .configure((bootJar) -> bootJar + .manifest(((manifest) -> manifest.getAttributes().put("Spring-Boot-Native-Processed", true)))); + } + } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/NativeImagePluginActionIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/NativeImagePluginActionIntegrationTests.java index 877fc0ec24..cc277d5c42 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/NativeImagePluginActionIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/NativeImagePluginActionIntegrationTests.java @@ -25,6 +25,7 @@ import java.util.Enumeration; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; +import java.util.jar.Manifest; import org.gradle.testkit.runner.BuildResult; import org.gradle.testkit.runner.TaskOutcome; @@ -115,6 +116,17 @@ class NativeImagePluginActionIntegrationTests { projectPath("build/resources/aotTest"), projectPath("build/generated/aotTestClasses")); } + @TestTemplate + void nativeEntryIsAddedToManifest() throws IOException { + writeDummySpringApplicationAotProcessorMainClass(); + BuildResult result = this.gradleBuild.build("bootJar"); + assertThat(result.task(":bootJar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); + File buildLibs = new File(this.gradleBuild.getProjectDir(), "build/libs"); + JarFile jarFile = new JarFile(new File(buildLibs, this.gradleBuild.getProjectDir().getName() + ".jar")); + Manifest manifest = jarFile.getManifest(); + assertThat(manifest.getMainAttributes().getValue("Spring-Boot-Native-Processed")).isEqualTo("true"); + } + private String projectPath(String path) { try { return new File(this.gradleBuild.getProjectDir(), path).getCanonicalPath(); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/plugin/NativeImagePluginActionIntegrationTests-nativeEntryIsAddedToManifest.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/plugin/NativeImagePluginActionIntegrationTests-nativeEntryIsAddedToManifest.gradle new file mode 100644 index 0000000000..a668b9c72f --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/plugin/NativeImagePluginActionIntegrationTests-nativeEntryIsAddedToManifest.gradle @@ -0,0 +1,8 @@ +plugins { + id 'java' + id 'org.springframework.boot' + id 'org.springframework.boot.aot' +} + +apply plugin: 'org.graalvm.buildtools.native' +