Incremental KAPT - pass changed classpath entries
Pass computed list of changed classpath names to KAPT instead of relying on the history files to be computed by stub generation. Also, stop generating classpath history changes during the stub generation. This commit does not compute the actual changed classpath entries, and that will be done in the following commits. #KT-23880
This commit is contained in:
committed by
Alexey Tsvetkov
parent
0c09f56118
commit
c85e21d43b
-12
@@ -35,26 +35,14 @@ class KaptIncrementalWithAggregatingApt : KaptIncrementalIT() {
|
||||
fun testIncrementalChanges() {
|
||||
val project = getProject()
|
||||
|
||||
var aptTimestamp = 0L
|
||||
|
||||
project.build("clean", "build") {
|
||||
assertSuccessful()
|
||||
|
||||
val classpathHistory =
|
||||
fileInWorkingDir("build/kotlin/kaptGenerateStubsKotlin/classpath-fq-history").listFiles().asList().single()
|
||||
val stubsTimestamp = classpathHistory.name.toLong()
|
||||
|
||||
aptTimestamp = fileInWorkingDir("build/tmp/kapt3/incApCache/main/last-build-ts.bin").readText().toLong()
|
||||
assertTrue(stubsTimestamp < aptTimestamp)
|
||||
}
|
||||
|
||||
project.projectFile("useB.kt").modify { current -> "$current\nfun otherFunction() {}" }
|
||||
project.build("build") {
|
||||
assertSuccessful()
|
||||
|
||||
val newAptTimestamp = fileInWorkingDir("build/tmp/kapt3/incApCache/main/last-build-ts.bin").readText().toLong()
|
||||
assertTrue(aptTimestamp < newAptTimestamp)
|
||||
|
||||
assertEquals(
|
||||
setOf(
|
||||
fileInWorkingDir("build/tmp/kapt3/stubs/main/bar/UseBKt.java").absolutePath,
|
||||
|
||||
-12
@@ -38,26 +38,14 @@ class KaptIncrementalWithIsolatingApt : KaptIncrementalIT() {
|
||||
fun testIncrementalChanges() {
|
||||
val project = getProject()
|
||||
|
||||
var aptTimestamp = 0L
|
||||
|
||||
project.build("clean", "build") {
|
||||
assertSuccessful()
|
||||
|
||||
val classpathHistory =
|
||||
fileInWorkingDir("build/kotlin/kaptGenerateStubsKotlin/classpath-fq-history").listFiles().asList().single()
|
||||
val stubsTimestamp = classpathHistory.name.toLong()
|
||||
|
||||
aptTimestamp = fileInWorkingDir("build/tmp/kapt3/incApCache/main/last-build-ts.bin").readText().toLong()
|
||||
assertTrue(stubsTimestamp < aptTimestamp)
|
||||
}
|
||||
|
||||
project.projectFile("useB.kt").modify { current -> "$current\nfun otherFunction() {}" }
|
||||
project.build("build") {
|
||||
assertSuccessful()
|
||||
|
||||
val newAptTimestamp = fileInWorkingDir("build/tmp/kapt3/incApCache/main/last-build-ts.bin").readText().toLong()
|
||||
assertTrue(aptTimestamp < newAptTimestamp)
|
||||
|
||||
assertEquals(setOf(fileInWorkingDir("build/tmp/kapt3/stubs/main/bar/UseBKt.java").absolutePath), getProcessedSources(output))
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -268,7 +268,6 @@ internal class GradleKotlinCompilerWork @Inject constructor(
|
||||
outputFiles = outputFiles,
|
||||
multiModuleICSettings = icEnv.multiModuleICSettings,
|
||||
modulesInfo = incrementalModuleInfo!!,
|
||||
classpathFqNamesHistory = icEnv.classpathFqNamesHistory,
|
||||
kotlinScriptExtensions = kotlinScriptExtensions
|
||||
)
|
||||
|
||||
|
||||
+1
-2
@@ -15,8 +15,7 @@ internal class IncrementalCompilationEnvironment(
|
||||
val workingDir: File,
|
||||
val usePreciseJavaTracking: Boolean = false,
|
||||
val disableMultiModuleIC: Boolean = false,
|
||||
val multiModuleICSettings: MultiModuleICSettings,
|
||||
val classpathFqNamesHistory: File? = null
|
||||
val multiModuleICSettings: MultiModuleICSettings
|
||||
) : Serializable {
|
||||
companion object {
|
||||
const val serialVersionUID: Long = 0
|
||||
|
||||
+2
-9
@@ -234,9 +234,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
)
|
||||
|
||||
val kaptGenerateStubsTask = context.createKaptGenerateStubsTask()
|
||||
val kaptTask = context.createKaptKotlinTask(
|
||||
useWorkerApi = project.isUseWorkerApi(),
|
||||
classpathHistoryDir = kaptGenerateStubsTask.getClasspathFqNamesHistoryDir())
|
||||
val kaptTask = context.createKaptKotlinTask(useWorkerApi = project.isUseWorkerApi())
|
||||
|
||||
kaptGenerateStubsTask.source(*kaptConfigurations.toTypedArray())
|
||||
|
||||
@@ -374,7 +372,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
}
|
||||
}
|
||||
|
||||
private fun Kapt3SubpluginContext.createKaptKotlinTask(useWorkerApi: Boolean, classpathHistoryDir: File? = null): KaptTask {
|
||||
private fun Kapt3SubpluginContext.createKaptKotlinTask(useWorkerApi: Boolean): KaptTask {
|
||||
val taskClass = if (useWorkerApi) KaptWithoutKotlincTask::class.java else KaptWithKotlincTask::class.java
|
||||
val kaptTask = project.tasks.create(getKaptTaskName("kapt"), taskClass)
|
||||
|
||||
@@ -391,7 +389,6 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
kaptTask.isIncremental = project.isIncrementalKapt()
|
||||
if (kaptTask.isIncremental) {
|
||||
kaptTask.incAptCache = getKaptIncrementalAnnotationProcessingCache()
|
||||
kaptTask.classpathDirtyFqNamesHistoryDir = project.files(classpathHistoryDir)
|
||||
}
|
||||
|
||||
kotlinCompilation?.run {
|
||||
@@ -422,10 +419,6 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
kaptTask.pluginOptions.addPluginArgument(
|
||||
getCompilerPluginId(),
|
||||
SubpluginOption("incrementalCache", kaptTask.incAptCache!!.absolutePath))
|
||||
|
||||
kaptTask.pluginOptions.addPluginArgument(
|
||||
getCompilerPluginId(),
|
||||
SubpluginOption("classpathFqNamesHistory", kaptTask.classpathDirtyFqNamesHistoryDir.singleFile!!.absolutePath))
|
||||
}
|
||||
|
||||
buildAndAddOptionsTo(kaptTask, kaptTask.pluginOptions, aptMode = "apt")
|
||||
|
||||
-5
@@ -74,11 +74,6 @@ open class KaptGenerateStubsTask : KotlinCompile() {
|
||||
super.setSource(sourceRootsContainer.set(sources))
|
||||
}
|
||||
|
||||
@Internal
|
||||
override fun getClasspathFqNamesHistoryDir(): File? {
|
||||
return taskBuildDirectory.resolve("classpath-fq-history")
|
||||
}
|
||||
|
||||
private fun isSourceRootAllowed(source: File): Boolean =
|
||||
!destinationDir.isParentOf(source) &&
|
||||
!stubsDir.isParentOf(source) &&
|
||||
|
||||
+9
-6
@@ -67,9 +67,6 @@ abstract class KaptTask : ConventionTask(), TaskWithLocalState {
|
||||
@get:Input
|
||||
internal var includeCompileClasspath: Boolean = true
|
||||
|
||||
@get:InputFiles
|
||||
internal var classpathDirtyFqNamesHistoryDir: FileCollection = project.files()
|
||||
|
||||
@get:Input
|
||||
internal var isIncremental = true
|
||||
|
||||
@@ -160,15 +157,21 @@ abstract class KaptTask : ConventionTask(), TaskWithLocalState {
|
||||
protected fun getCompiledSources() = listOfNotNull(kotlinCompileTask.destinationDir, kotlinCompileTask.javaOutputDir)
|
||||
|
||||
protected fun getChangedFiles(inputs: IncrementalTaskInputs): List<File> {
|
||||
return if (!isIncremental || !inputs.isIncremental || !getCompiledSources().all { it.exists() }) {
|
||||
if (!isIncremental || !inputs.isIncremental || !getCompiledSources().all { it.exists() }) {
|
||||
clearLocalState()
|
||||
emptyList()
|
||||
return emptyList()
|
||||
} else {
|
||||
with(mutableSetOf<File>()) {
|
||||
val changes = with(mutableSetOf<File>()) {
|
||||
inputs.outOfDate { this.add(it.file) }
|
||||
inputs.removed { this.add(it.file) }
|
||||
return@with this.toList()
|
||||
}
|
||||
|
||||
return if (changes.all { it.extension == "java" }) {
|
||||
changes
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
-8
@@ -16,17 +16,13 @@ import org.gradle.api.tasks.incremental.IncrementalTaskInputs
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||
import org.jetbrains.kotlin.compilerRunner.GradleCompilerEnvironment
|
||||
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner
|
||||
import org.jetbrains.kotlin.compilerRunner.IncrementalCompilationEnvironment
|
||||
import org.jetbrains.kotlin.gradle.logging.GradleKotlinLogger
|
||||
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
|
||||
import org.jetbrains.kotlin.gradle.incremental.ChangedFiles
|
||||
import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles
|
||||
import org.jetbrains.kotlin.gradle.logging.GradleKotlinLogger
|
||||
import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector
|
||||
import org.jetbrains.kotlin.gradle.plugin.PLUGIN_CLASSPATH_CONFIGURATION_NAME
|
||||
import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions
|
||||
import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector
|
||||
import org.jetbrains.kotlin.gradle.tasks.clearLocalState
|
||||
import org.jetbrains.kotlin.gradle.utils.toSortedPathsArray
|
||||
import org.jetbrains.kotlin.incremental.ChangedFiles
|
||||
import java.io.File
|
||||
|
||||
open class KaptWithKotlincTask : KaptTask(), CompilerArgumentAwareWithInput<K2JVMCompilerArguments> {
|
||||
@@ -54,7 +50,10 @@ open class KaptWithKotlincTask : KaptTask(), CompilerArgumentAwareWithInput<K2JV
|
||||
val pluginOptionsWithKapt: CompilerPluginOptions = pluginOptions.withWrappedKaptOptions(
|
||||
withApClasspath = kaptClasspath,
|
||||
changedFiles = changedFiles,
|
||||
compiledSourcesDir = getCompiledSources())
|
||||
classpathChanges = classpathChanges,
|
||||
compiledSourcesDir = getCompiledSources(),
|
||||
processIncrementally = processIncrementally
|
||||
)
|
||||
|
||||
args.pluginOptions = (pluginOptionsWithKapt.arguments + args.pluginOptions!!).toTypedArray()
|
||||
|
||||
@@ -66,13 +65,25 @@ open class KaptWithKotlincTask : KaptTask(), CompilerArgumentAwareWithInput<K2JV
|
||||
* in the task action.
|
||||
*/
|
||||
private var changedFiles: List<File> = emptyList()
|
||||
private var classpathChanges: List<String> = emptyList()
|
||||
private var processIncrementally = false
|
||||
|
||||
@TaskAction
|
||||
fun compile(inputs: IncrementalTaskInputs) {
|
||||
logger.debug("Running kapt annotation processing using the Kotlin compiler")
|
||||
checkAnnotationProcessorClasspath()
|
||||
|
||||
changedFiles = getChangedFiles(inputs)
|
||||
val incrementalChanges = getChangedFiles(inputs)
|
||||
when {
|
||||
incrementalChanges.isNotEmpty() -> {
|
||||
changedFiles = incrementalChanges
|
||||
classpathChanges = emptyList()
|
||||
processIncrementally = true
|
||||
}
|
||||
else -> {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
val args = prepareCompilerArguments()
|
||||
|
||||
|
||||
+11
-8
@@ -12,10 +12,8 @@ import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.api.tasks.incremental.IncrementalTaskInputs
|
||||
import org.gradle.workers.IsolationMode
|
||||
import org.gradle.workers.WorkerExecutor
|
||||
import org.jetbrains.kotlin.gradle.incremental.ChangedFiles
|
||||
import org.jetbrains.kotlin.gradle.internal.Kapt3KotlinGradleSubplugin.Companion.KAPT_WORKER_DEPENDENCIES_CONFIGURATION_NAME
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper
|
||||
import org.jetbrains.kotlin.gradle.tasks.clearLocalState
|
||||
import org.jetbrains.kotlin.gradle.tasks.findKotlinStdlibClasspath
|
||||
import org.jetbrains.kotlin.gradle.tasks.findToolsJar
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
@@ -52,6 +50,8 @@ open class KaptWithoutKotlincTask @Inject constructor(private val workerExecutor
|
||||
logger.info("Running kapt annotation processing using the Gradle Worker API")
|
||||
checkAnnotationProcessorClasspath()
|
||||
|
||||
val incrementalChanges = getChangedFiles(inputs)
|
||||
|
||||
val compileClasspath = classpath.files.toMutableList()
|
||||
if (project.plugins.none { it is KotlinAndroidPluginWrapper }) {
|
||||
compileClasspath.addAll(0, PathUtil.getJdkClassesRootsFromCurrentJre())
|
||||
@@ -68,10 +68,11 @@ open class KaptWithoutKotlincTask @Inject constructor(private val workerExecutor
|
||||
compileClasspath,
|
||||
javaSourceRoots.toList(),
|
||||
|
||||
getChangedFiles(inputs),
|
||||
incrementalChanges,
|
||||
getCompiledSources(),
|
||||
incAptCache,
|
||||
classpathDirtyFqNamesHistoryDir.singleOrNull(),
|
||||
emptyList(),
|
||||
incrementalChanges.isNotEmpty(),
|
||||
|
||||
destinationDir,
|
||||
classesDir,
|
||||
@@ -94,7 +95,7 @@ open class KaptWithoutKotlincTask @Inject constructor(private val workerExecutor
|
||||
|
||||
workerExecutor.submit(KaptExecution::class.java) { config ->
|
||||
val isolationModeStr = project.findProperty("kapt.workers.isolation") as String? ?: "none"
|
||||
config.isolationMode = when(isolationModeStr.toLowerCase()) {
|
||||
config.isolationMode = when (isolationModeStr.toLowerCase()) {
|
||||
"process" -> IsolationMode.PROCESS
|
||||
"none" -> IsolationMode.NONE
|
||||
else -> IsolationMode.NONE
|
||||
@@ -148,7 +149,7 @@ private class KaptExecution @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun createKaptOptions(classLoader: ClassLoader) = with (optionsForWorker) {
|
||||
private fun createKaptOptions(classLoader: ClassLoader) = with(optionsForWorker) {
|
||||
val flags = kaptClass(classLoader).declaredMethods.single { it.name == "kaptFlags" }.invoke(null, flags)
|
||||
|
||||
val mode = Class.forName("org.jetbrains.kotlin.base.kapt3.AptMode", true, classLoader)
|
||||
@@ -165,7 +166,8 @@ private class KaptExecution @Inject constructor(
|
||||
changedFiles,
|
||||
compiledSources,
|
||||
incAptCache,
|
||||
classpathFqNamesHistory,
|
||||
classpathChanges,
|
||||
processIncrementally,
|
||||
|
||||
sourcesOutputDir,
|
||||
classesOutputDir,
|
||||
@@ -201,7 +203,8 @@ private data class KaptOptionsForWorker(
|
||||
val changedFiles: List<File>,
|
||||
val compiledSources: List<File>,
|
||||
val incAptCache: File?,
|
||||
val classpathFqNamesHistory: File?,
|
||||
val classpathChanges: List<String>,
|
||||
val processIncrementally: Boolean,
|
||||
|
||||
val sourcesOutputDir: File,
|
||||
val classesOutputDir: File,
|
||||
|
||||
+13
-2
@@ -44,13 +44,22 @@ fun encodePluginOptions(options: Map<String, List<String>>): String {
|
||||
}
|
||||
|
||||
internal fun CompilerPluginOptions.withWrappedKaptOptions(
|
||||
withApClasspath: Iterable<File>, changedFiles: List<File> = emptyList(), compiledSourcesDir: List<File> = emptyList()
|
||||
withApClasspath: Iterable<File>,
|
||||
changedFiles: List<File> = emptyList(),
|
||||
classpathChanges: List<String> = emptyList(),
|
||||
compiledSourcesDir: List<File> = emptyList(),
|
||||
processIncrementally: Boolean = false
|
||||
): CompilerPluginOptions {
|
||||
val resultOptionsByPluginId: MutableMap<String, List<SubpluginOption>> =
|
||||
subpluginOptionsByPluginId.toMutableMap()
|
||||
|
||||
resultOptionsByPluginId.compute(Kapt3KotlinGradleSubplugin.KAPT_SUBPLUGIN_ID) { _, kaptOptions ->
|
||||
val changedFilesOption = FilesSubpluginOption("changedFile", changedFiles).takeIf { changedFiles.isNotEmpty() }
|
||||
val classpathChangesOption = SubpluginOption(
|
||||
"classpathChange",
|
||||
classpathChanges.joinToString(separator = File.pathSeparator)
|
||||
).takeIf { classpathChanges.isNotEmpty() }
|
||||
val processIncrementallyOption = SubpluginOption("processIncrementally", processIncrementally.toString())
|
||||
val compiledSourcesOption =
|
||||
FilesSubpluginOption("compiledSourcesDir", compiledSourcesDir).takeIf { compiledSourcesDir.isNotEmpty() }
|
||||
|
||||
@@ -58,7 +67,9 @@ internal fun CompilerPluginOptions.withWrappedKaptOptions(
|
||||
kaptOptions.orEmpty() +
|
||||
withApClasspath.map { FilesSubpluginOption("apclasspath", listOf(it)) } +
|
||||
changedFilesOption +
|
||||
compiledSourcesOption
|
||||
classpathChangesOption +
|
||||
compiledSourcesOption +
|
||||
processIncrementallyOption
|
||||
|
||||
wrapPluginOptions(kaptOptionsWithClasspath.filterNotNull(), "configuration")
|
||||
}
|
||||
|
||||
+1
-6
@@ -435,8 +435,7 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
|
||||
taskBuildDirectory,
|
||||
usePreciseJavaTracking = usePreciseJavaTracking,
|
||||
disableMultiModuleIC = disableMultiModuleIC(),
|
||||
multiModuleICSettings = multiModuleICSettings,
|
||||
classpathFqNamesHistory = getClasspathFqNamesHistoryDir()
|
||||
multiModuleICSettings = multiModuleICSettings
|
||||
)
|
||||
} else null
|
||||
|
||||
@@ -479,10 +478,6 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
|
||||
return false
|
||||
}
|
||||
|
||||
@Optional
|
||||
@Internal
|
||||
internal open fun getClasspathFqNamesHistoryDir(): File? = null
|
||||
|
||||
// override setSource to track source directory sets and files (for generated android folders)
|
||||
override fun setSource(sources: Any?) {
|
||||
sourceRootsContainer.set(sources)
|
||||
|
||||
Reference in New Issue
Block a user