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
@Synchronized
protected fun newDaemonConnection(compilerPath: File, flagFile: File, environment: Env): DaemonConnection {
val compilerId = CompilerId.makeCompilerId(compilerPath)
protected fun newDaemonConnection(compilerId: CompilerId, flagFile: File, environment: Env): DaemonConnection {
val daemonOptions = configureDaemonOptions()
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.MessageCollector
import org.jetbrains.kotlin.config.CompilerSettings
import org.jetbrains.kotlin.daemon.common.CompilerId
import org.jetbrains.kotlin.daemon.common.isDaemonEnabled
import org.jetbrains.kotlin.jps.build.KotlinBuilder
import java.io.ByteArrayOutputStream
@@ -138,10 +139,11 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner<JpsCompilerEnvironment>() {
if (jpsDaemonConnection == null) {
val libPath = CompilerRunnerUtil.getLibPath(environment.kotlinPaths, environment.messageCollector)
val compilerPath = File(libPath, "kotlin-compiler.jar")
val compilerId = CompilerId.makeCompilerId(compilerPath)
val flagFile = File.createTempFile("kotlin-compiler-jps-session-", "-is-running").apply {
deleteOnExit()
}
newDaemonConnection(compilerPath, flagFile, environment)
newDaemonConnection(compilerId, flagFile, environment)
}
return jpsDaemonConnection!!
}
@@ -321,7 +321,7 @@ class KotlinGradleIT: BaseGradleIT() {
project.build("build") {
assertSuccessful()
assertContains("Using kotlin compiler jar: $compilerJar")
assertContains("Kotlin compiler classpath: $compilerJar")
}
}
@@ -1,12 +1,11 @@
package org.jetbrains.kotlin.compilerRunner
import org.gradle.api.internal.artifacts.dsl.ArtifactFile
import org.jetbrains.kotlin.annotation.AnnotationFileUpdater
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.gradle.tasks.findToolsJar
import org.jetbrains.kotlin.incremental.ChangedFiles
import org.jetbrains.kotlin.incremental.GradleICReporter
import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistry
import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProvider
import java.io.File
import java.net.URL
@@ -16,8 +15,10 @@ internal open class GradleCompilerEnvironment(
messageCollector: MessageCollector,
outputItemsCollector: OutputItemsCollector
) : CompilerEnvironment(Services.EMPTY, messageCollector, outputItemsCollector) {
val toolsJar: File? by lazy { findToolsJar() }
val compilerClasspath: List<File>
get() = listOf(compilerJar).filterNotNull()
get() = listOf(compilerJar, toolsJar).filterNotNull()
val compilerClasspathURLs: List<URL>
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.config.Services
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.gradle.plugin.ParentLastURLClassLoader
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.destinationAsFile
import org.jetbrains.kotlin.incremental.makeModuleFile
@@ -60,7 +62,6 @@ internal class GradleCompilerRunner(private val project: Project) : KotlinCompil
environment: GradleCompilerEnvironment
): ExitCode {
val outputDir = args.destinationAsFile
log.info("Using kotlin compiler jar: ${environment.compilerJar}")
if (environment !is GradleIncrementalCompilerEnvironment) {
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 {
with (project.logger) {
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(" ")}" }
}
@@ -234,7 +235,8 @@ internal class GradleCompilerRunner(private val project: Project) : KotlinCompil
@Synchronized
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.TaskAction
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.jvm.K2JVMCompiler
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.fillDefaultValues
import org.jetbrains.kotlin.gradle.tasks.*
import org.jetbrains.kotlin.incremental.classpathAsList
import org.jetbrains.kotlin.incremental.destinationAsFile
import java.io.File
import java.net.URLDecoder
import java.nio.charset.Charset
open class KaptTask : AbstractCompile() {
private val rawSourceRoots = FilteringSourceRootsContainer({ !it.isInsideDestinationDir() })
@@ -40,20 +45,28 @@ open class KaptTask : AbstractCompile() {
destinationDir.deleteRecursively()
destinationDir.mkdirs()
val compiler = K2JVMCompiler()
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.pluginClasspaths = pluginOptions.classpath.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.parentKotlinOptionsImpl?.updateArguments(args)
KotlinJvmOptionsImpl().updateArguments(args)
val exitCode = compileJvmNotIncrementally(compiler, logger,
sourceRoots.kotlinSourceFiles, sourceRoots.javaSourceRoots, compileClasspath,
destinationDir, args)
val messageCollector = GradleMessageCollector(logger)
val outputItemCollector = OutputItemsCollectorImpl()
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)
}
}
@@ -17,19 +17,15 @@
package org.jetbrains.kotlin.gradle.tasks
import org.codehaus.groovy.runtime.MethodClosure
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.logging.Logger
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.SourceTask
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.compile.AbstractCompile
import org.gradle.api.tasks.incremental.IncrementalTaskInputs
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.annotation.AnnotationFileUpdater
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.arguments.CommonCompilerArguments
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.CompilerMessageSeverity
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.config.Services
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.CoroutineSupport
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
@@ -80,7 +73,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractCo
}
var compilerJarFile: File? = null
protected val compilerJar: File
internal val compilerJar: File
get() = compilerJarFile
?: findKotlinCompilerJar(project)
?: 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 {
private val kotlinOptionsImpl = KotlinJsOptionsImpl()
override val kotlinOptions: KotlinJsOptions
@@ -21,6 +21,8 @@ import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ResolvedDependency
import org.gradle.api.initialization.dsl.ScriptHandler
import java.io.File
import java.net.URLDecoder
import java.nio.charset.Charset
import java.util.zip.ZipFile
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? =
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? {
val filesToCheck = findPotentialCompilerJars(project)
val entryToFind = compilerClassName.replace(".", "/") + ".class"