From 69d1ee7b11200428f187d9329d2f0c16becfeabf Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov Date: Mon, 19 Dec 2016 15:36:59 +0300 Subject: [PATCH] Run kapt with daemon --- .../compilerRunner/KotlinCompilerRunner.kt | 3 +- .../compilerRunner/JpsKotlinCompilerRunner.kt | 4 +- .../kotlin/gradle/KotlinGradlePluginIT.kt | 2 +- .../GradleCompilerEnvironment.kt | 7 +-- .../GradleKotlinCompilerRunner.kt | 8 ++-- .../kotlin/gradle/internal/KaptTask.kt | 27 +++++++++--- .../jetbrains/kotlin/gradle/tasks/Tasks.kt | 44 +------------------ ...arSearchingUtil.kt => jarSearchingUtil.kt} | 15 +++++++ 8 files changed, 50 insertions(+), 60 deletions(-) rename libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/{compilerJarSearchingUtil.kt => jarSearchingUtil.kt} (85%) diff --git a/compiler/compiler-runner/src/org/jetbrains/kotlin/compilerRunner/KotlinCompilerRunner.kt b/compiler/compiler-runner/src/org/jetbrains/kotlin/compilerRunner/KotlinCompilerRunner.kt index 110f7839653..dc61fc60fbf 100644 --- a/compiler/compiler-runner/src/org/jetbrains/kotlin/compilerRunner/KotlinCompilerRunner.kt +++ b/compiler/compiler-runner/src/org/jetbrains/kotlin/compilerRunner/KotlinCompilerRunner.kt @@ -57,8 +57,7 @@ abstract class KotlinCompilerRunner { 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) diff --git a/jps-plugin/src/org/jetbrains/kotlin/compilerRunner/JpsKotlinCompilerRunner.kt b/jps-plugin/src/org/jetbrains/kotlin/compilerRunner/JpsKotlinCompilerRunner.kt index 2cfb0394f2d..c31cd3dfcf5 100644 --- a/jps-plugin/src/org/jetbrains/kotlin/compilerRunner/JpsKotlinCompilerRunner.kt +++ b/jps-plugin/src/org/jetbrains/kotlin/compilerRunner/JpsKotlinCompilerRunner.kt @@ -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() { 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!! } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt index 8890ed4d9e7..fc01f9e5bae 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt @@ -321,7 +321,7 @@ class KotlinGradleIT: BaseGradleIT() { project.build("build") { assertSuccessful() - assertContains("Using kotlin compiler jar: $compilerJar") + assertContains("Kotlin compiler classpath: $compilerJar") } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleCompilerEnvironment.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleCompilerEnvironment.kt index a3722387fcc..7fc1c15d17d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleCompilerEnvironment.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleCompilerEnvironment.kt @@ -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 - get() = listOf(compilerJar).filterNotNull() + get() = listOf(compilerJar, toolsJar).filterNotNull() val compilerClasspathURLs: List get() = compilerClasspath.map { it.toURI().toURL() } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt index 458f47e6fde..8e7752bdd0b 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt @@ -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, 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) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KaptTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KaptTask.kt index f2e8b0a0ecb..41a057a0e50 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KaptTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KaptTask.kt @@ -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) } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt index c23aaa69567..4de2cca165a 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt @@ -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() : 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(), Kotl } } -internal fun compileJvmNotIncrementally( - compiler: K2JVMCompiler, - logger: Logger, - sourcesToCompile: List, - javaSourceRoots: Iterable, - compileClasspath: Iterable, - 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(), KotlinJsCompile { private val kotlinOptionsImpl = KotlinJsOptionsImpl() override val kotlinOptions: KotlinJsOptions diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/compilerJarSearchingUtil.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/jarSearchingUtil.kt similarity index 85% rename from libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/compilerJarSearchingUtil.kt rename to libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/jarSearchingUtil.kt index 575eb798e22..0bcb8ea23b0 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/compilerJarSearchingUtil.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/jarSearchingUtil.kt @@ -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"