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 5a4e109934..100c601836 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 @@ -16,12 +16,17 @@ package org.springframework.boot.gradle.plugin; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.stream.Collectors; + import org.graalvm.buildtools.gradle.NativeImagePlugin; import org.graalvm.buildtools.gradle.dsl.GraalVMExtension; import org.graalvm.buildtools.gradle.dsl.GraalVMReachabilityMetadataRepositoryExtension; import org.gradle.api.Action; import org.gradle.api.Plugin; import org.gradle.api.Project; +import org.gradle.api.artifacts.Configuration; import org.gradle.api.plugins.ExtensionAware; import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.JavaPluginExtension; @@ -53,9 +58,8 @@ class NativeImagePluginAction implements PluginApplicationAction { JavaPluginExtension javaPluginExtension = project.getExtensions().getByType(JavaPluginExtension.class); SourceSetContainer sourceSets = javaPluginExtension.getSourceSets(); GraalVMExtension graalVmExtension = configureGraalVmExtension(project); - configureNativeBinaryClasspath(sourceSets, graalVmExtension, NativeImagePlugin.NATIVE_MAIN_EXTENSION, - SpringBootAotPlugin.AOT_SOURCE_SET_NAME); - configureNativeBinaryClasspath(sourceSets, graalVmExtension, NativeImagePlugin.NATIVE_TEST_EXTENSION, + configureMainNativeBinaryClasspath(project, sourceSets, graalVmExtension); + configureTestNativeBinaryClasspath(sourceSets, graalVmExtension, SpringBootAotPlugin.AOT_TEST_SOURCE_SET_NAME); configureGraalVmReachabilityExtension(graalVmExtension); copyReachabilityMetadataToBootJar(project); @@ -63,10 +67,24 @@ class NativeImagePluginAction implements PluginApplicationAction { }); } - private void configureNativeBinaryClasspath(SourceSetContainer sourceSets, GraalVMExtension graalVmExtension, - String binaryName, String sourceSetName) { - SourceSetOutput output = sourceSets.getByName(sourceSetName).getOutput(); - graalVmExtension.getBinaries().getByName(binaryName).classpath(output); + private void configureMainNativeBinaryClasspath(Project project, SourceSetContainer sourceSets, + GraalVMExtension graalVmExtension) { + SourceSetOutput output = sourceSets.getByName(SpringBootAotPlugin.AOT_SOURCE_SET_NAME).getOutput(); + graalVmExtension.getBinaries().getByName(NativeImagePlugin.NATIVE_MAIN_EXTENSION).classpath(output); + Configuration nativeImageClasspath = project.getConfigurations().getByName("nativeImageClasspath"); + nativeImageClasspath.setExtendsFrom(removeDevelopmentOnly(nativeImageClasspath.getExtendsFrom())); + } + + private Iterable removeDevelopmentOnly(Set configurations) { + return configurations.stream().filter(( + configuration) -> !SpringBootPlugin.DEVELOPMENT_ONLY_CONFIGURATION_NAME.equals(configuration.getName())) + .collect(Collectors.toCollection(LinkedHashSet::new)); + } + + private void configureTestNativeBinaryClasspath(SourceSetContainer sourceSets, GraalVMExtension graalVmExtension, + String sourceSetName) { + SourceSetOutput output = sourceSets.getByName(SpringBootAotPlugin.AOT_TEST_SOURCE_SET_NAME).getOutput(); + graalVmExtension.getBinaries().getByName(NativeImagePlugin.NATIVE_TEST_EXTENSION).classpath(output); } private GraalVMExtension configureGraalVmExtension(Project project) { 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 39e1bf1099..31fa2f34e0 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 @@ -94,6 +94,13 @@ class NativeImagePluginActionIntegrationTests { assertThat(result.getOutput()).contains("paketobuildpacks/builder:tiny").contains("BP_NATIVE_IMAGE = true"); } + @TestTemplate + void developmentOnlyDependenciesDoNotAppearInNativeImageClasspath() { + writeDummySpringApplicationAotProcessorMainClass(); + BuildResult result = this.gradleBuild.build("checkNativeImageClasspath"); + assertThat(result.getOutput()).doesNotContain("commons-lang"); + } + private void writeDummySpringApplicationAotProcessorMainClass() { File examplePackage = new File(this.gradleBuild.getProjectDir(), "src/main/java/org/springframework/boot"); examplePackage.mkdirs(); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/plugin/NativeImagePluginActionIntegrationTests-developmentOnlyDependenciesDoNotAppearInNativeImageClasspath.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/plugin/NativeImagePluginActionIntegrationTests-developmentOnlyDependenciesDoNotAppearInNativeImageClasspath.gradle new file mode 100644 index 0000000000..8bb6c48dda --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/plugin/NativeImagePluginActionIntegrationTests-developmentOnlyDependenciesDoNotAppearInNativeImageClasspath.gradle @@ -0,0 +1,20 @@ +plugins { + id 'org.springframework.boot' version '{version}' + id 'java' +} + +apply plugin: 'org.graalvm.buildtools.native' + +repositories { + mavenCentral() +} + +dependencies { + developmentOnly("org.apache.commons:commons-lang3:3.12.0") +} + +task('checkNativeImageClasspath') { + doFirst { + tasks.nativeCompile.options.get().classpath.each { println it } + } +}