Skip to content

Commit 23ae91b

Browse files
Add native image manifest entry
A manifest entry `Spring-Boot-Native-Processed: true` is added to the jar manifest by the Maven or Gradle plugin when the jar has been built for use in a native image. With the Gradle plugin, this is done in reaction to the GraalVM Native Image Plugin being applied to the project. With the Maven plugin, this is done when the `native` profile is applied to the build.
1 parent 5ac6a3d commit 23ae91b

File tree

4 files changed

+41
-3
lines changed

4 files changed

+41
-3
lines changed

spring-boot-project/spring-boot-starters/spring-boot-starter-parent/build.gradle

+11
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,17 @@ publishing.publications.withType(MavenPublication) {
233233
build {
234234
pluginManagement {
235235
plugins {
236+
plugin {
237+
delegate.groupId('org.apache.maven.plugins')
238+
delegate.artifactId('maven-jar-plugin')
239+
configuration {
240+
archive {
241+
manifestEntries {
242+
delegate.'Spring-Boot-Native-Processed'("true")
243+
}
244+
}
245+
}
246+
}
236247
plugin {
237248
delegate.groupId('org.springframework.boot')
238249
delegate.artifactId('spring-boot-maven-plugin')

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/NativeImagePluginAction.java

+10-3
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,11 @@ public void execute(Project project) {
5959
SourceSetContainer sourceSets = javaPluginExtension.getSourceSets();
6060
GraalVMExtension graalVmExtension = configureGraalVmExtension(project);
6161
configureMainNativeBinaryClasspath(project, sourceSets, graalVmExtension);
62-
configureTestNativeBinaryClasspath(project, sourceSets, graalVmExtension);
62+
configureTestNativeBinaryClasspath(sourceSets, graalVmExtension);
6363
configureGraalVmReachabilityExtension(graalVmExtension);
6464
copyReachabilityMetadataToBootJar(project);
6565
configureBootBuildImageToProduceANativeImage(project);
66+
configureJarManifestNativeAttribute(project);
6667
});
6768
}
6869

@@ -85,8 +86,7 @@ private boolean isNotDevelopmentOnly(Configuration configuration) {
8586
return !SpringBootPlugin.DEVELOPMENT_ONLY_CONFIGURATION_NAME.equals(configuration.getName());
8687
}
8788

88-
private void configureTestNativeBinaryClasspath(Project project, SourceSetContainer sourceSets,
89-
GraalVMExtension graalVmExtension) {
89+
private void configureTestNativeBinaryClasspath(SourceSetContainer sourceSets, GraalVMExtension graalVmExtension) {
9090
FileCollection runtimeClasspath = sourceSets.getByName(SpringBootAotPlugin.AOT_TEST_SOURCE_SET_NAME)
9191
.getRuntimeClasspath();
9292
graalVmExtension.getBinaries().getByName(NativeImagePlugin.NATIVE_TEST_EXTENSION).classpath(runtimeClasspath);
@@ -119,4 +119,11 @@ private void configureBootBuildImageToProduceANativeImage(Project project) {
119119
});
120120
}
121121

122+
private void configureJarManifestNativeAttribute(Project project) {
123+
project.getTasks()
124+
.named(SpringBootPlugin.BOOT_JAR_TASK_NAME, BootJar.class)
125+
.configure((bootJar) -> bootJar
126+
.manifest(((manifest) -> manifest.getAttributes().put("Spring-Boot-Native-Processed", true))));
127+
}
128+
122129
}

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/NativeImagePluginActionIntegrationTests.java

+12
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.List;
2626
import java.util.jar.JarEntry;
2727
import java.util.jar.JarFile;
28+
import java.util.jar.Manifest;
2829

2930
import org.gradle.testkit.runner.BuildResult;
3031
import org.gradle.testkit.runner.TaskOutcome;
@@ -115,6 +116,17 @@ void classesGeneratedDuringAotTestProcessingAreOnTheTestNativeImageClasspath() {
115116
projectPath("build/resources/aotTest"), projectPath("build/generated/aotTestClasses"));
116117
}
117118

119+
@TestTemplate
120+
void nativeEntryIsAddedToManifest() throws IOException {
121+
writeDummySpringApplicationAotProcessorMainClass();
122+
BuildResult result = this.gradleBuild.build("bootJar");
123+
assertThat(result.task(":bootJar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
124+
File buildLibs = new File(this.gradleBuild.getProjectDir(), "build/libs");
125+
JarFile jarFile = new JarFile(new File(buildLibs, this.gradleBuild.getProjectDir().getName() + ".jar"));
126+
Manifest manifest = jarFile.getManifest();
127+
assertThat(manifest.getMainAttributes().getValue("Spring-Boot-Native-Processed")).isEqualTo("true");
128+
}
129+
118130
private String projectPath(String path) {
119131
try {
120132
return new File(this.gradleBuild.getProjectDir(), path).getCanonicalPath();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
plugins {
2+
id 'java'
3+
id 'org.springframework.boot'
4+
id 'org.springframework.boot.aot'
5+
}
6+
7+
apply plugin: 'org.graalvm.buildtools.native'
8+

0 commit comments

Comments
 (0)