Decouple Kapt task from KotlinCompile task configuration

This fixes KotlinCompile task instantiation on configuring Kapt tasks
as well Kapt tasks itself eager realization.

Additionally this change removes circular dependency between kapt and
compilation tasks.

^KT-54468 In Progress
This commit is contained in:
Yahor Berdnikau
2023-01-20 15:54:37 +01:00
committed by Space Team
parent e06606aa3f
commit ee1517cd6a
4 changed files with 77 additions and 27 deletions
@@ -27,8 +27,7 @@ class ConfigurationAvoidanceIT : KGPBaseTest() {
@JvmGradlePluginTests
@GradleTestVersions(
maxVersion = TestVersions.Gradle.G_7_5,
additionalVersions = [TestVersions.Gradle.G_7_3, TestVersions.Gradle.G_7_4]
additionalVersions = [TestVersions.Gradle.G_7_3]
)
@DisplayName("KGP/Jvm does not eagerly configure any tasks")
@GradleTest
@@ -49,6 +48,29 @@ class ConfigurationAvoidanceIT : KGPBaseTest() {
}
}
@OtherGradlePluginTests
@GradleTestVersions(
additionalVersions = [TestVersions.Gradle.G_7_3]
)
@DisplayName("KGP/Kapt does not eagerly configure any tasks")
@GradleTest
fun testKaptConfigurationAvoidance(gradleVersion: GradleVersion) {
project("kapt2/simple", gradleVersion) {
buildGradle.appendText(
"""
|
|tasks.configureEach {
| if (name != "help" && name != "clean") {
| throw new GradleException("Configuration avoidance failure for ${'$'}name!")
| }
|}
""".trimMargin()
)
build("--dry-run")
}
}
@AndroidGradlePluginTests
@DisplayName("Android unrelated tasks are not configured")
@AndroidTestVersions(minVersion = TestVersions.AGP.AGP_42)
@@ -1,3 +1,5 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
plugins {
id "java"
id "org.jetbrains.kotlin.jvm"
@@ -16,4 +18,6 @@ dependencies {
testImplementation 'junit:junit:4.13.2'
}
compileKotlin.kotlinOptions.allWarningsAsErrors = true
tasks.named("compileKotlin", KotlinJvmCompile) {
compilerOptions.allWarningsAsErrors = true
}
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin.Companion.isUse
import org.jetbrains.kotlin.gradle.model.builder.KaptModelBuilder
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaCompilation
import org.jetbrains.kotlin.gradle.tasks.*
import org.jetbrains.kotlin.gradle.tasks.configuration.*
import org.jetbrains.kotlin.gradle.utils.SingleWarningPerBuild
@@ -283,15 +284,12 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To
)
val kaptGenerateStubsTaskProvider: TaskProvider<KaptGenerateStubsTask> = context.createKaptGenerateStubsTask()
val kaptTaskProvider: TaskProvider<out KaptTask> = context.createKaptKotlinTask()
val kaptTaskProvider: TaskProvider<out KaptTask> = context.createKaptKotlinTask(
kaptGenerateStubsTaskProvider
)
kaptGenerateStubsTaskProvider.configure { kaptGenerateStubsTask ->
kaptGenerateStubsTask.dependsOn(*buildDependencies.toTypedArray())
kaptGenerateStubsTask.dependsOn(
project.provider {
kotlinCompilation.compileKotlinTask.dependsOn.filter { it !is TaskProvider<*> || it.name != kaptTaskProvider.name }
}
)
if (androidVariantData != null) {
kaptGenerateStubsTask.additionalSources.from(
@@ -305,9 +303,6 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To
}
}
kaptTaskProvider.configure { kaptTask ->
kaptTask.dependsOn(kaptGenerateStubsTaskProvider)
}
context.kotlinCompile.configure { it.dependsOn(kaptTaskProvider) }
/** Plugin options are applied to kapt*Compile inside [createKaptKotlinTask] */
@@ -357,9 +352,16 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To
).get()
}
private fun Kapt3SubpluginContext.createKaptKotlinTask(): TaskProvider<out KaptTask> {
private fun Kapt3SubpluginContext.createKaptKotlinTask(
generateStubsTask: TaskProvider<KaptGenerateStubsTask>
): TaskProvider<out KaptTask> {
val taskName = getKaptTaskName("kapt")
val taskConfigAction = KaptWithoutKotlincConfig(kotlinCompilation.compileKotlinTaskProvider.get() as KotlinCompile, kaptExtension)
@Suppress("UNCHECKED_CAST")
val taskConfigAction = KaptWithoutKotlincConfig(
kotlinCompilation.project,
generateStubsTask,
kaptExtension
)
val kaptClasspathConfiguration = project.configurations.create("kaptClasspath_$taskName")
.setExtendsFrom(kaptClasspathConfigurations).also {
@@ -367,6 +369,8 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To
it.isCanBeConsumed = false
}
taskConfigAction.configureTaskProvider { taskProvider ->
taskProvider.dependsOn(generateStubsTask)
if (javaCompile != null) {
val androidVariantData = KaptWithAndroid.androidVariantData(this)
if (androidVariantData != null) {
@@ -379,7 +383,14 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To
disableAnnotationProcessingInJavaTask()
}
kotlinCompilation.output.classesDirs.from(taskProvider.flatMap { it.classesDir })
// Workaround for changes in Gradle 7.3 causing eager task realization
// For details check `KotlinSourceSetProcessor.prepareKotlinCompileTask()`
if (kotlinCompilation is KotlinWithJavaCompilation<*, *>) {
val kotlinSourceDirectorySet = kotlinCompilation.defaultSourceSet.kotlin
kotlinSourceDirectorySet.compiledBy(taskProvider, KaptTask::classesDir)
} else {
kotlinCompilation.output.classesDirs.from(taskProvider.flatMap { it.classesDir })
}
kotlinCompilation.compileTaskProvider.configure { task ->
with(task as AbstractKotlinCompile<*>) {
@@ -24,12 +24,10 @@ import org.jetbrains.kotlin.gradle.internal.kapt.incremental.CLASS_STRUCTURE_ART
import org.jetbrains.kotlin.gradle.internal.kapt.incremental.StructureTransformAction
import org.jetbrains.kotlin.gradle.internal.kapt.incremental.StructureTransformLegacyAction
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.tasks.toCompilerPluginOptions
import org.jetbrains.kotlin.gradle.utils.listProperty
import org.jetbrains.kotlin.gradle.utils.markResolvable
import java.io.File
import java.util.concurrent.Callable
internal open class KaptConfig<TASK : KaptTask>(
project: Project,
@@ -49,7 +47,7 @@ internal open class KaptConfig<TASK : KaptTask>(
task.includeCompileClasspath.set(ext.includeCompileClasspath ?: project.isIncludeCompileClasspath())
task.classpathStructure.from(kaptClasspathSnapshot)
task.localStateDirectories.from(Callable { task.incAptCache.orNull })
task.localStateDirectories.from({ task.incAptCache.orNull })
task.onlyIf {
it as KaptTask
it.includeCompileClasspath.get() || !it.kaptClasspath.isEmpty
@@ -58,18 +56,26 @@ internal open class KaptConfig<TASK : KaptTask>(
}
}
internal constructor(kotlinCompileTask: KotlinCompile, ext: KaptExtension) : this(kotlinCompileTask.project, ext) {
internal constructor(
project: Project,
kaptGenerateStubsTask: TaskProvider<KaptGenerateStubsTask>,
ext: KaptExtension
) : this(project, ext) {
configureTask { task ->
task.classpath.from(kotlinCompileTask.libraries - project.files(task.classesDir))
task.compiledSources.from(
kotlinCompileTask.destinationDirectory,
Callable { kotlinCompileTask.javaOutputDir.takeIf { it.isPresent } })
task.classpath.from(
kaptGenerateStubsTask.map { it.libraries }
)
task.compiledSources
.from(
kaptGenerateStubsTask.flatMap { it.kotlinCompileDestinationDirectory },
{ kaptGenerateStubsTask.get().javaOutputDir.takeIf { it.isPresent } }
)
.disallowChanges()
task.sourceSetName.value(kotlinCompileTask.sourceSetName).disallowChanges()
task.sourceSetName.value(kaptGenerateStubsTask.flatMap { it.sourceSetName }).disallowChanges()
val kaptSources = objectFactory.fileCollection()
.from(kotlinCompileTask.javaSources, task.stubsDir)
.from(kaptGenerateStubsTask.map { it.javaSources }, task.stubsDir)
.asFileTree
.matching { it.include("**/*.java") }
.filter {
@@ -175,14 +181,21 @@ internal class KaptWithoutKotlincConfig : KaptConfig<KaptWithoutKotlincTask> {
)
task.kaptJars.from(project.configurations.getByName(Kapt3GradleSubplugin.KAPT_WORKER_DEPENDENCIES_CONFIGURATION_NAME))
task.mapDiagnosticLocations = ext.mapDiagnosticLocations
task.annotationProcessorFqNames.set(providers.provider { ext.processors.split(',').filter { it.isNotEmpty() } })
task.annotationProcessorFqNames.set(providers.provider {
@Suppress("DEPRECATION")
ext.processors.split(',').filter { it.isNotEmpty() }
})
task.disableClassloaderCacheForProcessors = project.disableClassloaderCacheForProcessors()
task.classLoadersCacheSize = project.classLoadersCacheSize()
task.javacOptions.set(getJavaOptions(task.defaultJavaSourceCompatibility))
}
}
constructor(kotlinCompileTask: KotlinCompile, ext: KaptExtension) : super(kotlinCompileTask, ext) {
constructor(
project: Project,
kaptGenerateStubsTask: TaskProvider<KaptGenerateStubsTask>,
ext: KaptExtension
) : super(project, kaptGenerateStubsTask, ext) {
project.configurations.findByName(Kapt3GradleSubplugin.KAPT_WORKER_DEPENDENCIES_CONFIGURATION_NAME)
?: project.configurations.create(Kapt3GradleSubplugin.KAPT_WORKER_DEPENDENCIES_CONFIGURATION_NAME).apply {
dependencies.addAllLater(project.listProperty {