From 2bb9b2640eab8f9efe5ca48bb0ddd78043969b0e Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Mon, 31 Oct 2022 15:47:11 +0000 Subject: [PATCH] Separate classpath of AOT tasks from source sets they populate Closes gh-32930 --- .../gradle/plugin/SpringBootAotPlugin.java | 58 ++++++++++++++----- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SpringBootAotPlugin.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SpringBootAotPlugin.java index 73b783fa714..79989379231 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SpringBootAotPlugin.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SpringBootAotPlugin.java @@ -21,7 +21,7 @@ import java.util.List; import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; -import org.gradle.api.artifacts.ConfigurationContainer; +import org.gradle.api.attributes.Attribute; import org.gradle.api.attributes.AttributeContainer; import org.gradle.api.attributes.LibraryElements; import org.gradle.api.attributes.Usage; @@ -78,7 +78,7 @@ public class SpringBootAotPlugin implements Plugin { SourceSet aotTestSourceSet = configureSourceSet(project, "aotTest", testSourceSet); plugins.withType(SpringBootPlugin.class).all((bootPlugin) -> { registerProcessAotTask(project, aotSourceSet, mainSourceSet); - registerProcessTestAotTask(project, aotTestSourceSet, testSourceSet); + registerProcessTestAotTask(project, mainSourceSet, aotTestSourceSet, testSourceSet); }); }); } @@ -89,18 +89,13 @@ public class SpringBootAotPlugin implements Plugin { return sourceSets.create(newSourceSetName, (sourceSet) -> { sourceSet.getJava().setSrcDirs(List.of("build/generated/" + newSourceSetName + "Sources")); sourceSet.getResources().setSrcDirs(List.of("build/generated/" + newSourceSetName + "Resources")); - sourceSet.setCompileClasspath(sourceSet.getCompileClasspath().plus(existingSourceSet.getCompileClasspath()) - .plus(existingSourceSet.getOutput())); - existingSourceSet.setRuntimeClasspath(existingSourceSet.getRuntimeClasspath().plus(sourceSet.getOutput())); - ConfigurationContainer configurations = project.getConfigurations(); - Configuration implementation = configurations.getByName(sourceSet.getImplementationConfigurationName()); - implementation - .extendsFrom(configurations.getByName(existingSourceSet.getImplementationConfigurationName())); - implementation.extendsFrom(configurations.getByName(existingSourceSet.getRuntimeOnlyConfigurationName())); - configurations.getByName(sourceSet.getCompileClasspathConfigurationName()).attributes((attributes) -> { - configureClassesAndResourcesLibraryElementsAttribute(project, attributes); - configureJavaRuntimeUsageAttribute(project, attributes); - }); + project.getDependencies().add(existingSourceSet.getRuntimeClasspathConfigurationName(), + project.files(sourceSet.getOutput())); + project.getConfigurations().getByName(sourceSet.getCompileClasspathConfigurationName()) + .attributes((attributes) -> { + configureClassesAndResourcesLibraryElementsAttribute(project, attributes); + configureJavaRuntimeUsageAttribute(project, attributes); + }); }); } @@ -119,11 +114,17 @@ public class SpringBootAotPlugin implements Plugin { TaskProvider resolveMainClassName = project.getTasks() .named(SpringBootPlugin.RESOLVE_MAIN_CLASS_NAME_TASK_NAME, ResolveMainClassName.class); Provider aotClasses = project.getLayout().getBuildDirectory().dir("generated/aotClasses"); + Configuration aotClasspath = createAotProcessingClasspath(project, PROCESS_AOT_TASK_NAME, mainSourceSet); + project.getDependencies().add(aotClasspath.getName(), project.files(mainSourceSet.getOutput())); + Configuration compileClasspath = project.getConfigurations() + .getByName(aotSourceSet.getCompileClasspathConfigurationName()); + compileClasspath.extendsFrom(aotClasspath); TaskProvider processAot = project.getTasks().register(PROCESS_AOT_TASK_NAME, ProcessAot.class, (task) -> { configureAotTask(project, aotSourceSet, task, aotClasses, mainSourceSet); task.getApplicationClass() .set(resolveMainClassName.flatMap(ResolveMainClassName::readMainClassName)); + task.setClasspath(aotClasspath); }); project.getDependencies().add(aotSourceSet.getImplementationConfigurationName(), project.files(aotClasses)); aotSourceSet.getOutput().dir(aotClasses); @@ -132,7 +133,6 @@ public class SpringBootAotPlugin implements Plugin { private void configureAotTask(Project project, SourceSet sourceSet, AbstractAot task, Provider generatedClasses, SourceSet inputSourceSet) { - task.setClasspath(sourceSet.getCompileClasspath()); task.getSourcesOutput().set(sourceSet.getJava().getSrcDirs().iterator().next()); task.getResourcesOutput().set(sourceSet.getResources().getSrcDirs().iterator().next()); task.getClassesOutput().set(generatedClasses); @@ -141,6 +141,25 @@ public class SpringBootAotPlugin implements Plugin { task.setClasspathRoots(inputSourceSet.getOutput().getClassesDirs()); } + @SuppressWarnings("unchecked") + private Configuration createAotProcessingClasspath(Project project, String taskName, SourceSet inputSourceSet) { + Configuration base = project.getConfigurations() + .getByName(inputSourceSet.getRuntimeClasspathConfigurationName()); + Configuration aotClasspath = project.getConfigurations().create(taskName + "Classpath", (classpath) -> { + classpath.setCanBeConsumed(false); + classpath.setCanBeResolved(true); + classpath.setDescription("Classpath of the " + taskName + " task."); + base.getExtendsFrom().forEach(classpath::extendsFrom); + classpath.attributes((attributes) -> { + AttributeContainer baseAttributes = base.getAttributes(); + for (Attribute attribute : baseAttributes.keySet()) { + attributes.attribute((Attribute) attribute, baseAttributes.getAttribute(attribute)); + } + }); + }); + return aotClasspath; + } + private void configureDependsOn(Project project, SourceSet aotSourceSet, TaskProvider processAot) { project.getTasks().named(aotSourceSet.getCompileJavaTaskName()) @@ -149,11 +168,18 @@ public class SpringBootAotPlugin implements Plugin { .configure((processResources) -> processResources.dependsOn(processAot)); } - private void registerProcessTestAotTask(Project project, SourceSet aotTestSourceSet, SourceSet testSourceSet) { + private void registerProcessTestAotTask(Project project, SourceSet mainSourceSet, SourceSet aotTestSourceSet, + SourceSet testSourceSet) { Provider aotTestClasses = project.getLayout().getBuildDirectory().dir("generated/aotTestClasses"); + Configuration aotClasspath = createAotProcessingClasspath(project, PROCESS_TEST_AOT_TASK_NAME, testSourceSet); + Configuration compileClasspath = project.getConfigurations() + .getByName(aotTestSourceSet.getCompileClasspathConfigurationName()); + compileClasspath.extendsFrom(aotClasspath); TaskProvider processTestAot = project.getTasks().register(PROCESS_TEST_AOT_TASK_NAME, ProcessTestAot.class, (task) -> { configureAotTask(project, aotTestSourceSet, task, aotTestClasses, testSourceSet); + task.setClasspath(project.getObjects().fileCollection().from(aotClasspath, + mainSourceSet.getOutput(), testSourceSet.getOutput())); task.setTestRuntimeClasspath( project.getConfigurations().getByName(testSourceSet.getImplementationConfigurationName())); });