Use daemon when compiling Kotlin to JS

This commit is contained in:
Alexey Tsvetkov
2016-12-19 17:36:35 +03:00
parent 25816b2ccf
commit c7c2a93d1f
3 changed files with 45 additions and 53 deletions
@@ -1,9 +1,23 @@
package org.jetbrains.kotlin.gradle
import org.jetbrains.kotlin.gradle.util.getFileByName
import org.jetbrains.kotlin.gradle.util.modify
import org.junit.Test
class ExecutionStrategyIT(): BaseGradleIT() {
class ExecutionStrategyJsIT : ExecutionStrategyIT() {
override fun setupProject(project: Project) {
project.setupWorkingDir()
val buildGradle = project.projectDir.getFileByName("build.gradle")
buildGradle.modify { it.replace("apply plugin: \"kotlin\"", "apply plugin: \"kotlin2js\"") +
"\ncompileKotlin2Js.kotlinOptions.outputFile = \"out.js\"" }
}
override fun CompiledProject.checkOutput() {
assertFileExists("out.js")
}
}
open class ExecutionStrategyIT : BaseGradleIT() {
companion object {
private const val GRADLE_VERSION = "2.10"
}
@@ -20,6 +20,7 @@ import net.rubygrapefruit.platform.Native
import net.rubygrapefruit.platform.ProcessLauncher
import org.gradle.api.Project
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.config.Services
@@ -85,6 +86,17 @@ internal class GradleCompilerRunner(private val project: Project) : KotlinCompil
}
}
fun runJsCompiler(
kotlinSources: List<File>,
args: K2JSCompilerArguments,
messageCollector: MessageCollector,
outputItemsCollector: OutputItemsCollector,
kotlinCompilerJar: File
): ExitCode {
val additionalArguments = kotlinSources.joinToString(separator = " ") { it.absolutePath }
return runCompiler(K2JS_COMPILER, args, additionalArguments, messageCollector, outputItemsCollector, GradleCompilerEnvironment(kotlinCompilerJar))
}
override fun doRunCompiler(compilerClassName: String, argsArray: Array<String>, environment: GradleCompilerEnvironment, messageCollector: MessageCollector, collector: OutputItemsCollector): ExitCode {
val executionStrategy = System.getProperty(KOTLIN_COMPILER_EXECUTION_STRATEGY_PROPERTY) ?: DAEMON_EXECUTION_STRATEGY
if (executionStrategy == DAEMON_EXECUTION_STRATEGY) {
@@ -18,6 +18,7 @@ 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
@@ -81,6 +82,12 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractCo
}
var compilerJarFile: File? = null
protected val compilerJar: File
get() = compilerJarFile
?: findKotlinCompilerJar(project)
?: throw IllegalStateException("Could not find Kotlin Compiler jar. Please specify $name.compilerJarFile")
protected abstract fun findKotlinCompilerJar(project: Project): File?
internal var compilerCalled: Boolean = false
// TODO: consider more reliable approach (see usage)
internal var anyClassesCompiled: Boolean = false
@@ -161,6 +168,9 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
// created only if kapt2 is active
internal var sourceAnnotationsRegistry: SourceAnnotationsRegistry? = null
override fun findKotlinCompilerJar(project: Project): File? =
findKotlinJvmCompilerJar(project)
override fun populateCompilerArguments(): K2JVMCompilerArguments {
val args = K2JVMCompilerArguments().apply { fillDefaultValues() }
@@ -199,9 +209,6 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
args.classpathAsList = compileClasspath.toList()
args.destinationAsFile = destinationDir
val outputItemCollector = OutputItemsCollectorImpl()
val compilerJar = compilerJarFile
?: findKotlinJvmCompilerJar(project)
?: throw IllegalStateException("Could not find Kotlin Compiler jar. Please specify $name.compilerJarFile")
if (!incremental) {
anyClassesCompiled = true
@@ -332,6 +339,9 @@ open class Kotlin2JsCompile() : AbstractKotlinCompile<K2JSCompilerArguments>(),
outputs.file(MethodClosure(this, "getOutputFile"))
}
override fun findKotlinCompilerJar(project: Project): File? =
findKotlinJsCompilerJar(project)
override fun populateCompilerArguments(): K2JSCompilerArguments {
val args = K2JSCompilerArguments().apply { fillDefaultValues() }
args.outputFile = outputFile
@@ -367,20 +377,11 @@ open class Kotlin2JsCompile() : AbstractKotlinCompile<K2JSCompilerArguments>(),
logger.kotlinDebug("compiling with args ${ArgumentUtils.convertArgumentsToStringList(args)}")
val gradleVersion = getGradleVersion()
val exitCode = if (gradleVersion == null || gradleVersion >= ParsedGradleVersion(3, 2)) {
// Gradle 3.2 bundles kotlin compiler
// This can cause problems with builtins resolution
// Compiling out of process as a workaround
val argsArray = ArgumentUtils.convertArgumentsToStringList(args).toTypedArray()
val compilerJar = compilerJarFile
?: findKotlinJsCompilerJar(project)
?: throw IllegalStateException("Could not find kotlin compiler jar. As a workaround specify $name.compilerJarFile")
compileOutOfProcess(argsArray, compiler.javaClass.canonicalName, compilerJar)
}
else {
compileInProcess(args)
}
val messageCollector = GradleMessageCollector(logger)
val outputItemCollector = OutputItemsCollectorImpl()
val compilerRunner = GradleCompilerRunner(project)
val exitCode = compilerRunner.runJsCompiler(sourceRoots.kotlinSourceFiles, args, messageCollector, outputItemCollector, compilerJar)
when (exitCode) {
ExitCode.OK -> {
@@ -391,12 +392,6 @@ open class Kotlin2JsCompile() : AbstractKotlinCompile<K2JSCompilerArguments>(),
else -> throw GradleException("Unexpected exit code: $exitCode")
}
}
private fun compileInProcess(args: K2JSCompilerArguments): ExitCode {
val messageCollector = GradleMessageCollector(logger)
val exitCode = compiler.exec(messageCollector, Services.EMPTY, args)
return exitCode
}
}
private fun Task.getGradleVersion(): ParsedGradleVersion? {
@@ -408,35 +403,6 @@ private fun Task.getGradleVersion(): ParsedGradleVersion? {
return result
}
private fun compileOutOfProcess(
argsArray: Array<String>,
compilerClassName: String,
compilerJar: File
): ExitCode {
try {
val javaBin = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java"
val builder = ProcessBuilder(javaBin, "-cp", compilerJar.absolutePath, compilerClassName, *argsArray)
val process = builder.start()
// important to read inputStream, otherwise the process may hang on some systems
val readErrThread = thread {
process.errorStream!!.bufferedReader().forEachLine {
System.err.println(it)
}
}
process.inputStream!!.bufferedReader().forEachLine {
System.out.println(it)
}
readErrThread.join()
val exitCode = process.waitFor()
if (exitCode == 0) return ExitCode.OK else return ExitCode.COMPILATION_ERROR
}
catch (e: Throwable) {
return ExitCode.INTERNAL_ERROR
}
}
internal class GradleMessageCollector(val logger: Logger) : MessageCollector {
private var hasErrors = false