[KAPT] Cache annotation processors' classloaders

Adds experimental feature to cache annotation processors' classloaders
It should increase speed of KAPT for consecutive runs
Works for gradle only (it stores cl in gradle daemon)
#KT-28901 Fixed
This commit is contained in:
Andrey Zinovyev
2021-03-02 10:55:42 +03:00
committed by TeamCityServer
parent e6b9935df9
commit 1093bffc62
16 changed files with 419 additions and 41 deletions
@@ -35,7 +35,14 @@ class KaptOptions(
val flags: KaptFlags,
val mode: AptMode,
val detectMemoryLeaks: DetectMemoryLeaksMode
val detectMemoryLeaks: DetectMemoryLeaksMode,
//these two config can be replaced with single function-like interface (ProcessorName -> ClassLoader),
// but it is hard to pass function between different classloaders
//if defined use it to run processors instead of creating new one
val processingClassLoader: ClassLoader?,
//construct new classloader for these processors instead of using one defined in processingClassLoader
val separateClassloaderForProcessors: Set<String>
) : KaptFlags {
override fun get(flag: KaptFlag) = flags[flag]
@@ -76,7 +83,9 @@ class KaptOptions(
changedFiles, compiledSources, incrementalCache, classpathChanges,
sourcesOutputDir, classesOutputDir, stubsOutputDir, incrementalDataOutputDir,
processingClasspath, processors, processingOptions, javacOptions, KaptFlags.fromSet(flags),
mode, detectMemoryLeaks
mode, detectMemoryLeaks,
processingClassLoader = null,
separateClassloaderForProcessors = emptySet()
)
}
}
@@ -203,4 +212,4 @@ fun KaptOptions.logString(additionalInfo: String = "") = buildString {
appendLine("[incremental apt] Compiled sources directories: ${compiledSources.joinToString()}")
appendLine("[incremental apt] Cache directory for incremental compilation: $incrementalCache")
appendLine("[incremental apt] Changed classpath names: ${classpathChanges.joinToString()}")
}
}
@@ -32,6 +32,7 @@ open class ProcessorLoader(private val options: KaptOptions, private val logger:
addAll(options.compileClasspath)
}
}
val classLoader = URLClassLoader(classpath.map { it.toURI().toURL() }.toTypedArray(), parentClassLoader)
this.annotationProcessingClassLoader = classLoader
@@ -74,7 +75,7 @@ open class ProcessorLoader(private val options: KaptOptions, private val logger:
}
}
open fun doLoadProcessors(classpath: LinkedHashSet<File>, classLoader: URLClassLoader): List<Processor> {
open fun doLoadProcessors(classpath: LinkedHashSet<File>, classLoader: ClassLoader): List<Processor> {
val processorNames = mutableSetOf<String>()
fun processSingleInput(input: InputStream) {
@@ -119,8 +120,17 @@ open class ProcessorLoader(private val options: KaptOptions, private val logger:
}
private fun tryLoadProcessor(fqName: String, classLoader: ClassLoader): Processor? {
val providedClassloader = options.processingClassLoader?.takeIf { !options.separateClassloaderForProcessors.contains(fqName) }
val classLoaderToUse = if (providedClassloader != null) {
logger.info { "Use provided ClassLoader for processor '$fqName'" }
providedClassloader
} else {
logger.info { "Use own ClassLoader for processor '$fqName'" }
classLoader
}
val annotationProcessorClass = try {
Class.forName(fqName, true, classLoader)
Class.forName(fqName, true, classLoaderToUse)
} catch (e: Throwable) {
logger.warn("Can't find annotation processor class $fqName: ${e.message}")
return null
@@ -143,4 +153,4 @@ open class ProcessorLoader(private val options: KaptOptions, private val logger:
override fun close() {
annotationProcessingClassLoader?.close()
}
}
}
@@ -81,9 +81,11 @@ class ClasspathBasedKapt3Extension(
override fun loadProcessors(): LoadedProcessors {
val efficientProcessorLoader = object : ProcessorLoader(options, logger) {
override fun doLoadProcessors(classpath: LinkedHashSet<File>, classLoader: URLClassLoader): List<Processor> {
return ServiceLoaderLite.loadImplementations(Processor::class.java, classLoader)
}
override fun doLoadProcessors(classpath: LinkedHashSet<File>, classLoader: ClassLoader): List<Processor> =
when (classLoader) {
is URLClassLoader -> ServiceLoaderLite.loadImplementations(Processor::class.java, classLoader)
else -> super.doLoadProcessors(classpath, classLoader)
}
}
this.processorLoader = efficientProcessorLoader