Run kapt with daemon

This commit is contained in:
Alexey Tsvetkov
2016-12-19 15:36:59 +03:00
parent 865c6d887c
commit 69d1ee7b11
8 changed files with 50 additions and 60 deletions
@@ -57,8 +57,7 @@ abstract class KotlinCompilerRunner<in Env : CompilerEnvironment> {
protected abstract fun getDaemonConnection(environment: Env): DaemonConnection protected abstract fun getDaemonConnection(environment: Env): DaemonConnection
@Synchronized @Synchronized
protected fun newDaemonConnection(compilerPath: File, flagFile: File, environment: Env): DaemonConnection { protected fun newDaemonConnection(compilerId: CompilerId, flagFile: File, environment: Env): DaemonConnection {
val compilerId = CompilerId.makeCompilerId(compilerPath)
val daemonOptions = configureDaemonOptions() val daemonOptions = configureDaemonOptions()
val daemonJVMOptions = configureDaemonJVMOptions(inheritMemoryLimits = true, inheritAdditionalProperties = true) val daemonJVMOptions = configureDaemonJVMOptions(inheritMemoryLimits = true, inheritAdditionalProperties = true)
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.config.CompilerSettings import org.jetbrains.kotlin.config.CompilerSettings
import org.jetbrains.kotlin.daemon.common.CompilerId
import org.jetbrains.kotlin.daemon.common.isDaemonEnabled import org.jetbrains.kotlin.daemon.common.isDaemonEnabled
import org.jetbrains.kotlin.jps.build.KotlinBuilder import org.jetbrains.kotlin.jps.build.KotlinBuilder
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
@@ -138,10 +139,11 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner<JpsCompilerEnvironment>() {
if (jpsDaemonConnection == null) { if (jpsDaemonConnection == null) {
val libPath = CompilerRunnerUtil.getLibPath(environment.kotlinPaths, environment.messageCollector) val libPath = CompilerRunnerUtil.getLibPath(environment.kotlinPaths, environment.messageCollector)
val compilerPath = File(libPath, "kotlin-compiler.jar") val compilerPath = File(libPath, "kotlin-compiler.jar")
val compilerId = CompilerId.makeCompilerId(compilerPath)
val flagFile = File.createTempFile("kotlin-compiler-jps-session-", "-is-running").apply { val flagFile = File.createTempFile("kotlin-compiler-jps-session-", "-is-running").apply {
deleteOnExit() deleteOnExit()
} }
newDaemonConnection(compilerPath, flagFile, environment) newDaemonConnection(compilerId, flagFile, environment)
} }
return jpsDaemonConnection!! return jpsDaemonConnection!!
} }
@@ -321,7 +321,7 @@ class KotlinGradleIT: BaseGradleIT() {
project.build("build") { project.build("build") {
assertSuccessful() assertSuccessful()
assertContains("Using kotlin compiler jar: $compilerJar") assertContains("Kotlin compiler classpath: $compilerJar")
} }
} }
@@ -1,12 +1,11 @@
package org.jetbrains.kotlin.compilerRunner package org.jetbrains.kotlin.compilerRunner
import org.gradle.api.internal.artifacts.dsl.ArtifactFile
import org.jetbrains.kotlin.annotation.AnnotationFileUpdater import org.jetbrains.kotlin.annotation.AnnotationFileUpdater
import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.gradle.tasks.findToolsJar
import org.jetbrains.kotlin.incremental.ChangedFiles import org.jetbrains.kotlin.incremental.ChangedFiles
import org.jetbrains.kotlin.incremental.GradleICReporter import org.jetbrains.kotlin.incremental.GradleICReporter
import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistry
import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProvider import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProvider
import java.io.File import java.io.File
import java.net.URL import java.net.URL
@@ -16,8 +15,10 @@ internal open class GradleCompilerEnvironment(
messageCollector: MessageCollector, messageCollector: MessageCollector,
outputItemsCollector: OutputItemsCollector outputItemsCollector: OutputItemsCollector
) : CompilerEnvironment(Services.EMPTY, messageCollector, outputItemsCollector) { ) : CompilerEnvironment(Services.EMPTY, messageCollector, outputItemsCollector) {
val toolsJar: File? by lazy { findToolsJar() }
val compilerClasspath: List<File> val compilerClasspath: List<File>
get() = listOf(compilerJar).filterNotNull() get() = listOf(compilerJar, toolsJar).filterNotNull()
val compilerClasspathURLs: List<URL> val compilerClasspathURLs: List<URL>
get() = compilerClasspath.map { it.toURI().toURL() } get() = compilerClasspath.map { it.toURI().toURL() }
@@ -27,9 +27,11 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.daemon.client.RemoteOutputStreamServer import org.jetbrains.kotlin.daemon.client.RemoteOutputStreamServer
import org.jetbrains.kotlin.daemon.common.CompilerId
import org.jetbrains.kotlin.daemon.common.SOCKET_ANY_FREE_PORT import org.jetbrains.kotlin.daemon.common.SOCKET_ANY_FREE_PORT
import org.jetbrains.kotlin.gradle.plugin.ParentLastURLClassLoader import org.jetbrains.kotlin.gradle.plugin.ParentLastURLClassLoader
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
import org.jetbrains.kotlin.gradle.tasks.SourceRoots
import org.jetbrains.kotlin.incremental.classpathAsList import org.jetbrains.kotlin.incremental.classpathAsList
import org.jetbrains.kotlin.incremental.destinationAsFile import org.jetbrains.kotlin.incremental.destinationAsFile
import org.jetbrains.kotlin.incremental.makeModuleFile import org.jetbrains.kotlin.incremental.makeModuleFile
@@ -60,7 +62,6 @@ internal class GradleCompilerRunner(private val project: Project) : KotlinCompil
environment: GradleCompilerEnvironment environment: GradleCompilerEnvironment
): ExitCode { ): ExitCode {
val outputDir = args.destinationAsFile val outputDir = args.destinationAsFile
log.info("Using kotlin compiler jar: ${environment.compilerJar}")
if (environment !is GradleIncrementalCompilerEnvironment) { if (environment !is GradleIncrementalCompilerEnvironment) {
log.debug("Removing all kotlin classes in $outputDir") log.debug("Removing all kotlin classes in $outputDir")
@@ -109,7 +110,7 @@ internal class GradleCompilerRunner(private val project: Project) : KotlinCompil
override fun doRunCompiler(compilerClassName: String, argsArray: Array<String>, environment: GradleCompilerEnvironment): ExitCode { override fun doRunCompiler(compilerClassName: String, argsArray: Array<String>, environment: GradleCompilerEnvironment): ExitCode {
with (project.logger) { with (project.logger) {
kotlinDebug { "Kotlin compiler class: $compilerClassName" } kotlinDebug { "Kotlin compiler class: $compilerClassName" }
kotlinDebug { "Kotlin compiler jar: ${environment.compilerJar}" } kotlinDebug { "Kotlin compiler classpath: ${environment.compilerClasspath.map { it.canonicalPath }.joinToString()}" }
kotlinDebug { "Kotlin compiler args: ${argsArray.joinToString(" ")}" } kotlinDebug { "Kotlin compiler args: ${argsArray.joinToString(" ")}" }
} }
@@ -234,7 +235,8 @@ internal class GradleCompilerRunner(private val project: Project) : KotlinCompil
@Synchronized @Synchronized
override fun getDaemonConnection(environment: GradleCompilerEnvironment): DaemonConnection { override fun getDaemonConnection(environment: GradleCompilerEnvironment): DaemonConnection {
return newDaemonConnection(environment.compilerJar, flagFile, environment) val compilerId = CompilerId.makeCompilerId(environment.compilerClasspath)
return newDaemonConnection(compilerId, flagFile, environment)
} }
} }
@@ -4,14 +4,19 @@ import org.gradle.api.GradleException
import org.gradle.api.tasks.SourceTask import org.gradle.api.tasks.SourceTask
import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.api.tasks.compile.AbstractCompile
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.com.intellij.openapi.util.io.FileUtil import org.jetbrains.kotlin.com.intellij.openapi.util.io.FileUtil
import org.jetbrains.kotlin.compilerRunner.GradleCompilerEnvironment
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptionsImpl import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptionsImpl
import org.jetbrains.kotlin.gradle.dsl.fillDefaultValues import org.jetbrains.kotlin.gradle.dsl.fillDefaultValues
import org.jetbrains.kotlin.gradle.tasks.* import org.jetbrains.kotlin.gradle.tasks.*
import org.jetbrains.kotlin.incremental.classpathAsList
import org.jetbrains.kotlin.incremental.destinationAsFile
import java.io.File import java.io.File
import java.net.URLDecoder
import java.nio.charset.Charset
open class KaptTask : AbstractCompile() { open class KaptTask : AbstractCompile() {
private val rawSourceRoots = FilteringSourceRootsContainer({ !it.isInsideDestinationDir() }) private val rawSourceRoots = FilteringSourceRootsContainer({ !it.isInsideDestinationDir() })
@@ -40,20 +45,28 @@ open class KaptTask : AbstractCompile() {
destinationDir.deleteRecursively() destinationDir.deleteRecursively()
destinationDir.mkdirs() destinationDir.mkdirs()
val compiler = K2JVMCompiler()
val sourceRoots = SourceRoots.ForJvm.create(getSource(), rawSourceRoots) val sourceRoots = SourceRoots.ForJvm.create(getSource(), rawSourceRoots)
val compileClasspath = classpath.filter(File::exists) val compileClasspath = classpath.toList().filter(File::exists)
args.moduleName = kotlinCompileTask.moduleName args.moduleName = kotlinCompileTask.moduleName
args.pluginClasspaths = pluginOptions.classpath.toTypedArray() args.pluginClasspaths = pluginOptions.classpath.toTypedArray()
args.pluginOptions = pluginOptions.arguments.toTypedArray() args.pluginOptions = pluginOptions.arguments.toTypedArray()
args.destinationAsFile = destinationDir
args.classpathAsList = compileClasspath
args.verbose = project.hasProperty("kapt.verbose") && project.property("kapt.verbose").toString().toBoolean() == true
kotlinCompileTask.friendTaskName?.let { kotlinCompileTask.addFriendPathForTestTask(it, args) } kotlinCompileTask.friendTaskName?.let { kotlinCompileTask.addFriendPathForTestTask(it, args) }
kotlinCompileTask.parentKotlinOptionsImpl?.updateArguments(args) kotlinCompileTask.parentKotlinOptionsImpl?.updateArguments(args)
KotlinJvmOptionsImpl().updateArguments(args) KotlinJvmOptionsImpl().updateArguments(args)
val exitCode = compileJvmNotIncrementally(compiler, logger, val messageCollector = GradleMessageCollector(logger)
sourceRoots.kotlinSourceFiles, sourceRoots.javaSourceRoots, compileClasspath, val outputItemCollector = OutputItemsCollectorImpl()
destinationDir, args) val environment = GradleCompilerEnvironment(kotlinCompileTask.compilerJar, messageCollector, outputItemCollector)
if (environment.toolsJar == null) {
throw GradleException("Could not find tools.jar in system classpath, which is required for kapt to work")
}
val compilerRunner = GradleCompilerRunner(project)
val exitCode = compilerRunner.runJvmCompiler(sourceRoots.kotlinSourceFiles, sourceRoots.javaSourceRoots, args, environment)
throwGradleExceptionIfError(exitCode) throwGradleExceptionIfError(exitCode)
} }
} }
@@ -17,19 +17,15 @@
package org.jetbrains.kotlin.gradle.tasks package org.jetbrains.kotlin.gradle.tasks
import org.codehaus.groovy.runtime.MethodClosure import org.codehaus.groovy.runtime.MethodClosure
import org.gradle.api.GradleException
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.Task import org.gradle.api.Task
import org.gradle.api.logging.Logger import org.gradle.api.logging.Logger
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.SourceTask import org.gradle.api.tasks.SourceTask
import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.api.tasks.compile.AbstractCompile
import org.gradle.api.tasks.incremental.IncrementalTaskInputs import org.gradle.api.tasks.incremental.IncrementalTaskInputs
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.annotation.AnnotationFileUpdater import org.jetbrains.kotlin.annotation.AnnotationFileUpdater
import org.jetbrains.kotlin.annotation.AnnotationFileUpdaterImpl import org.jetbrains.kotlin.annotation.AnnotationFileUpdaterImpl
import org.jetbrains.kotlin.cli.common.CLICompiler
import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
@@ -37,10 +33,7 @@ import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.js.K2JSCompiler
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.compilerRunner.* import org.jetbrains.kotlin.compilerRunner.*
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.gradle.dsl.* import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.CoroutineSupport import org.jetbrains.kotlin.gradle.plugin.CoroutineSupport
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
@@ -80,7 +73,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractCo
} }
var compilerJarFile: File? = null var compilerJarFile: File? = null
protected val compilerJar: File internal val compilerJar: File
get() = compilerJarFile get() = compilerJarFile
?: findKotlinCompilerJar(project) ?: findKotlinCompilerJar(project)
?: throw IllegalStateException("Could not find Kotlin Compiler jar. Please specify $name.compilerJarFile") ?: throw IllegalStateException("Could not find Kotlin Compiler jar. Please specify $name.compilerJarFile")
@@ -279,41 +272,6 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
} }
} }
internal fun compileJvmNotIncrementally(
compiler: K2JVMCompiler,
logger: Logger,
sourcesToCompile: List<File>,
javaSourceRoots: Iterable<File>,
compileClasspath: Iterable<File>,
outputDir: File,
args: K2JVMCompilerArguments
): ExitCode {
logger.kotlinDebug("Removing all kotlin classes in $outputDir")
// we're free to delete all classes since only we know about that directory
// todo: can be optimized -- compile and remove only files that were not generated
listClassFiles(outputDir.canonicalPath).forEach { it.delete() }
val moduleFile = makeModuleFile(
args.moduleName,
isTest = false,
outputDir = outputDir,
sourcesToCompile = sourcesToCompile,
javaSourceRoots = javaSourceRoots,
classpath = compileClasspath,
friendDirs = listOf())
args.module = moduleFile.absolutePath
val messageCollector = GradleMessageCollector(logger)
try {
logger.kotlinDebug("compiling with args: ${ArgumentUtils.convertArgumentsToStringList(args)}")
logger.kotlinDebug("compiling with classpath: ${compileClasspath.toList().sorted().joinToString()}")
return compiler.exec(messageCollector, Services.EMPTY, args)
}
finally {
moduleFile.delete()
}
}
open class Kotlin2JsCompile() : AbstractKotlinCompile<K2JSCompilerArguments>(), KotlinJsCompile { open class Kotlin2JsCompile() : AbstractKotlinCompile<K2JSCompilerArguments>(), KotlinJsCompile {
private val kotlinOptionsImpl = KotlinJsOptionsImpl() private val kotlinOptionsImpl = KotlinJsOptionsImpl()
override val kotlinOptions: KotlinJsOptions override val kotlinOptions: KotlinJsOptions
@@ -21,6 +21,8 @@ import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ResolvedDependency import org.gradle.api.artifacts.ResolvedDependency
import org.gradle.api.initialization.dsl.ScriptHandler import org.gradle.api.initialization.dsl.ScriptHandler
import java.io.File import java.io.File
import java.net.URLDecoder
import java.nio.charset.Charset
import java.util.zip.ZipFile import java.util.zip.ZipFile
private val K2JVM_COMPILER_CLASS = "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler" private val K2JVM_COMPILER_CLASS = "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler"
@@ -39,6 +41,19 @@ internal fun findKotlinJsCompilerJar(project: Project): File? =
internal fun findKotlinMetadataCompilerJar(project: Project): File? = internal fun findKotlinMetadataCompilerJar(project: Project): File? =
findKotlinCompilerJar(project, K2METADATA_COMPILER_CLASS) findKotlinCompilerJar(project, K2METADATA_COMPILER_CLASS)
internal fun findToolsJar(): File? =
Class.forName("com.sun.tools.javac.util.Context")?.let(::findJarByClass)
private fun findJarByClass(klass: Class<*>): File? {
val classFileName = klass.name.substringAfterLast(".") + ".class"
val resource = klass.getResource(classFileName) ?: return null
val uri = resource.toString()
if (!uri.startsWith("jar:file:")) return null
val fileName = URLDecoder.decode(uri.removePrefix("jar:file:").substringBefore("!"), Charset.defaultCharset().name())
return File(fileName)
}
private fun findKotlinCompilerJar(project: Project, compilerClassName: String): File? { private fun findKotlinCompilerJar(project: Project, compilerClassName: String): File? {
val filesToCheck = findPotentialCompilerJars(project) val filesToCheck = findPotentialCompilerJars(project)
val entryToFind = compilerClassName.replace(".", "/") + ".class" val entryToFind = compilerClassName.replace(".", "/") + ".class"