Merge pull request #752 from JetBrains/rr/compile-service-3
compile service 3
This commit is contained in:
@@ -16,8 +16,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.rmi.kotlinr
|
package org.jetbrains.kotlin.rmi.kotlinr
|
||||||
|
|
||||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||||
import org.jetbrains.kotlin.modules.TargetId
|
import org.jetbrains.kotlin.modules.TargetId
|
||||||
|
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
||||||
import org.jetbrains.kotlin.rmi.*
|
import org.jetbrains.kotlin.rmi.*
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import java.rmi.ConnectException
|
import java.rmi.ConnectException
|
||||||
@@ -27,6 +28,12 @@ import java.util.concurrent.TimeUnit
|
|||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
|
|
||||||
|
public class CompilationServices(
|
||||||
|
val incrementalCompilationComponents: IncrementalCompilationComponents? = null,
|
||||||
|
val compilationCanceledStatus: CompilationCanceledStatus? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
public object KotlinCompilerClient {
|
public object KotlinCompilerClient {
|
||||||
|
|
||||||
val DAEMON_DEFAULT_STARTUP_TIMEOUT_MS = 10000L
|
val DAEMON_DEFAULT_STARTUP_TIMEOUT_MS = 10000L
|
||||||
@@ -93,14 +100,14 @@ public object KotlinCompilerClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public fun shutdownCompileService(daemonOptions: DaemonOptions): Unit {
|
public fun shutdownCompileService(compilerId: CompilerId, daemonOptions: DaemonOptions): Unit {
|
||||||
KotlinCompilerClient.connectToCompileService(CompilerId(), DaemonJVMOptions(), daemonOptions, DaemonReportingTargets(out = System.out), autostart = false, checkId = false)
|
KotlinCompilerClient.connectToCompileService(compilerId, DaemonJVMOptions(), daemonOptions, DaemonReportingTargets(out = System.out), autostart = false, checkId = false)
|
||||||
?.shutdown()
|
?.shutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public fun shutdownCompileService(): Unit {
|
public fun shutdownCompileService(compilerId: CompilerId): Unit {
|
||||||
shutdownCompileService(DaemonOptions())
|
shutdownCompileService(compilerId, DaemonOptions())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -108,7 +115,7 @@ public object KotlinCompilerClient {
|
|||||||
|
|
||||||
val outStrm = RemoteOutputStreamServer(out)
|
val outStrm = RemoteOutputStreamServer(out)
|
||||||
try {
|
try {
|
||||||
return compiler.remoteCompile(args, outStrm, CompileService.OutputFormat.PLAIN, outStrm)
|
return compiler.remoteCompile(args, makeRemoteServices(CompilationServices()), outStrm, CompileService.OutputFormat.PLAIN, outStrm)
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
outStrm.disconnect()
|
outStrm.disconnect()
|
||||||
@@ -118,14 +125,13 @@ public object KotlinCompilerClient {
|
|||||||
|
|
||||||
// TODO: remove jvmStatic after all use sites will switch to kotlin
|
// TODO: remove jvmStatic after all use sites will switch to kotlin
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
public fun incrementalCompile(compiler: CompileService, args: Array<out String>, caches: Map<TargetId, IncrementalCache>, compilerOut: OutputStream, daemonOut: OutputStream): Int {
|
public fun incrementalCompile(compiler: CompileService, args: Array<out String>, services: CompilationServices, compilerOut: OutputStream, daemonOut: OutputStream): Int {
|
||||||
|
|
||||||
val compilerOutStreamServer = RemoteOutputStreamServer(compilerOut)
|
val compilerOutStreamServer = RemoteOutputStreamServer(compilerOut)
|
||||||
val daemonOutStreamServer = RemoteOutputStreamServer(daemonOut)
|
val daemonOutStreamServer = RemoteOutputStreamServer(daemonOut)
|
||||||
val cacheServers = hashMapOf<TargetId, RemoteIncrementalCacheServer>()
|
val cacheServers = hashMapOf<TargetId, RemoteIncrementalCacheServer>()
|
||||||
try {
|
try {
|
||||||
caches.mapValuesTo(cacheServers, { RemoteIncrementalCacheServer(it.getValue()) })
|
return compiler.remoteIncrementalCompile(args, makeRemoteServices(services), compilerOutStreamServer, CompileService.OutputFormat.XML, daemonOutStreamServer)
|
||||||
return compiler.remoteIncrementalCompile(args, cacheServers, compilerOutStreamServer, CompileService.OutputFormat.XML, daemonOutStreamServer)
|
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
cacheServers.forEach { it.getValue().disconnect() }
|
cacheServers.forEach { it.getValue().disconnect() }
|
||||||
@@ -135,6 +141,12 @@ public object KotlinCompilerClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun makeRemoteServices(services: CompilationServices): CompileService.RemoteCompilationServices =
|
||||||
|
CompileService.RemoteCompilationServices(
|
||||||
|
incrementalCompilationComponents = if (services.incrementalCompilationComponents == null) null else RemoteIncrementalCompilationComponentsServer(services.incrementalCompilationComponents),
|
||||||
|
compilationCanceledStatus = if (services.compilationCanceledStatus == null) null else RemoteCompilationCanceledStatusServer(services.compilationCanceledStatus)
|
||||||
|
)
|
||||||
|
|
||||||
data class ClientOptions(
|
data class ClientOptions(
|
||||||
public var stop: Boolean = false
|
public var stop: Boolean = false
|
||||||
) : OptionsGroup {
|
) : OptionsGroup {
|
||||||
@@ -196,7 +208,7 @@ public object KotlinCompilerClient {
|
|||||||
val memBefore = daemon.getUsedMemory() / 1024
|
val memBefore = daemon.getUsedMemory() / 1024
|
||||||
val startTime = System.nanoTime()
|
val startTime = System.nanoTime()
|
||||||
|
|
||||||
val res = daemon.remoteCompile(filteredArgs.toArrayList().toTypedArray(), outStrm, CompileService.OutputFormat.PLAIN, outStrm)
|
val res = daemon.remoteCompile(filteredArgs.toArrayList().toTypedArray(), makeRemoteServices(CompilationServices()), outStrm, CompileService.OutputFormat.PLAIN, outStrm)
|
||||||
|
|
||||||
val endTime = System.nanoTime()
|
val endTime = System.nanoTime()
|
||||||
println("Compilation result code: $res")
|
println("Compilation result code: $res")
|
||||||
|
|||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.rmi.kotlinr
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
||||||
|
import org.jetbrains.kotlin.rmi.CompileService
|
||||||
|
import org.jetbrains.kotlin.rmi.LoopbackNetworkInterface
|
||||||
|
import org.jetbrains.kotlin.rmi.SOCKET_ANY_FREE_PORT
|
||||||
|
import java.rmi.server.UnicastRemoteObject
|
||||||
|
|
||||||
|
|
||||||
|
public class RemoteCompilationCanceledStatusServer(val base: CompilationCanceledStatus, port: Int = SOCKET_ANY_FREE_PORT) : CompileService.RemoteCompilationCanceledStatus {
|
||||||
|
|
||||||
|
init {
|
||||||
|
UnicastRemoteObject.exportObject(this, port, LoopbackNetworkInterface.clientLoopbackSocketFactory, LoopbackNetworkInterface.serverLoopbackSocketFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun checkCanceled() {
|
||||||
|
base.checkCanceled()
|
||||||
|
}
|
||||||
|
}
|
||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.rmi.kotlinr
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||||
|
import org.jetbrains.kotlin.modules.TargetId
|
||||||
|
import org.jetbrains.kotlin.rmi.CompileService
|
||||||
|
import org.jetbrains.kotlin.rmi.LoopbackNetworkInterface
|
||||||
|
import org.jetbrains.kotlin.rmi.SOCKET_ANY_FREE_PORT
|
||||||
|
import java.rmi.server.UnicastRemoteObject
|
||||||
|
|
||||||
|
|
||||||
|
public class RemoteIncrementalCompilationComponentsServer(val base: IncrementalCompilationComponents, val port: Int = SOCKET_ANY_FREE_PORT) : CompileService.RemoteIncrementalCompilationComponents {
|
||||||
|
|
||||||
|
init {
|
||||||
|
UnicastRemoteObject.exportObject(this, port, LoopbackNetworkInterface.clientLoopbackSocketFactory, LoopbackNetworkInterface.serverLoopbackSocketFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val cacheServers = hashMapOf<TargetId, RemoteIncrementalCacheServer>()
|
||||||
|
private val lookupTrackerServer by lazy { RemoteLookupTrackerServer(base.getLookupTracker()) }
|
||||||
|
|
||||||
|
override fun getIncrementalCache(target: TargetId): CompileService.RemoteIncrementalCache =
|
||||||
|
cacheServers.get(target) ?: {
|
||||||
|
val newServer = RemoteIncrementalCacheServer(base.getIncrementalCache(target), port)
|
||||||
|
cacheServers.put(target, newServer)
|
||||||
|
newServer
|
||||||
|
}()
|
||||||
|
|
||||||
|
override fun getLookupTracker(): CompileService.RemoteLookupTracker = lookupTrackerServer
|
||||||
|
}
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.rmi.kotlinr
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||||
|
import org.jetbrains.kotlin.incremental.components.ScopeKind
|
||||||
|
import org.jetbrains.kotlin.rmi.CompileService
|
||||||
|
import org.jetbrains.kotlin.rmi.LoopbackNetworkInterface
|
||||||
|
import org.jetbrains.kotlin.rmi.SOCKET_ANY_FREE_PORT
|
||||||
|
import java.rmi.server.UnicastRemoteObject
|
||||||
|
|
||||||
|
|
||||||
|
public class RemoteLookupTrackerServer(val base: LookupTracker, port: Int = SOCKET_ANY_FREE_PORT) : CompileService.RemoteLookupTracker {
|
||||||
|
|
||||||
|
init {
|
||||||
|
UnicastRemoteObject.exportObject(this, port, LoopbackNetworkInterface.clientLoopbackSocketFactory, LoopbackNetworkInterface.serverLoopbackSocketFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun record(lookupContainingFile: String, lookupLine: Int?, lookupColumn: Int?, scopeFqName: String, scopeKind: ScopeKind, name: String) {
|
||||||
|
base.record(lookupContainingFile, lookupLine, lookupColumn, scopeFqName, scopeKind, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val _isDoNothing: Boolean = base == LookupTracker.DO_NOTHING
|
||||||
|
override fun isDoNothing(): Boolean = _isDoNothing
|
||||||
|
}
|
||||||
|
|
||||||
@@ -16,7 +16,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.rmi
|
package org.jetbrains.kotlin.rmi
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.incremental.components.ScopeKind
|
||||||
import org.jetbrains.kotlin.modules.TargetId
|
import org.jetbrains.kotlin.modules.TargetId
|
||||||
|
import java.io.Serializable
|
||||||
import java.rmi.Remote
|
import java.rmi.Remote
|
||||||
import java.rmi.RemoteException
|
import java.rmi.RemoteException
|
||||||
|
|
||||||
@@ -47,6 +49,38 @@ public interface CompileService : Remote {
|
|||||||
public fun close()
|
public fun close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface RemoteLookupTracker : Remote {
|
||||||
|
@Throws(RemoteException::class)
|
||||||
|
fun record(
|
||||||
|
lookupContainingFile: String,
|
||||||
|
lookupLine: Int?,
|
||||||
|
lookupColumn: Int?,
|
||||||
|
scopeFqName: String,
|
||||||
|
scopeKind: ScopeKind,
|
||||||
|
name: String
|
||||||
|
)
|
||||||
|
@Throws(RemoteException::class)
|
||||||
|
fun isDoNothing(): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface RemoteIncrementalCompilationComponents : Remote {
|
||||||
|
@Throws(RemoteException::class)
|
||||||
|
public fun getIncrementalCache(target: TargetId): RemoteIncrementalCache
|
||||||
|
|
||||||
|
@Throws(RemoteException::class)
|
||||||
|
public fun getLookupTracker(): RemoteLookupTracker
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface RemoteCompilationCanceledStatus : Remote {
|
||||||
|
@Throws(RemoteException::class)
|
||||||
|
fun checkCanceled(): Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
public data class RemoteCompilationServices(
|
||||||
|
public val incrementalCompilationComponents: RemoteIncrementalCompilationComponents? = null,
|
||||||
|
public val compilationCanceledStatus: RemoteCompilationCanceledStatus? = null
|
||||||
|
) : Serializable
|
||||||
|
|
||||||
@Throws(RemoteException::class)
|
@Throws(RemoteException::class)
|
||||||
public fun getCompilerId(): CompilerId
|
public fun getCompilerId(): CompilerId
|
||||||
|
|
||||||
@@ -59,6 +93,7 @@ public interface CompileService : Remote {
|
|||||||
@Throws(RemoteException::class)
|
@Throws(RemoteException::class)
|
||||||
public fun remoteCompile(
|
public fun remoteCompile(
|
||||||
args: Array<out String>,
|
args: Array<out String>,
|
||||||
|
services: RemoteCompilationServices,
|
||||||
compilerOutputStream: RemoteOutputStream,
|
compilerOutputStream: RemoteOutputStream,
|
||||||
outputFormat: OutputFormat,
|
outputFormat: OutputFormat,
|
||||||
serviceOutputStream: RemoteOutputStream
|
serviceOutputStream: RemoteOutputStream
|
||||||
@@ -67,7 +102,7 @@ public interface CompileService : Remote {
|
|||||||
@Throws(RemoteException::class)
|
@Throws(RemoteException::class)
|
||||||
public fun remoteIncrementalCompile(
|
public fun remoteIncrementalCompile(
|
||||||
args: Array<out String>,
|
args: Array<out String>,
|
||||||
caches: Map<TargetId, RemoteIncrementalCache>,
|
services: RemoteCompilationServices,
|
||||||
compilerOutputStream: RemoteOutputStream,
|
compilerOutputStream: RemoteOutputStream,
|
||||||
compilerOutputFormat: OutputFormat,
|
compilerOutputFormat: OutputFormat,
|
||||||
serviceOutputStream: RemoteOutputStream
|
serviceOutputStream: RemoteOutputStream
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ public val COMPILE_DAEMON_ENABLED_PROPERTY: String = "kotlin.daemon.enabled"
|
|||||||
public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String = "kotlin.daemon.jvm.options"
|
public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String = "kotlin.daemon.jvm.options"
|
||||||
public val COMPILE_DAEMON_OPTIONS_PROPERTY: String = "kotlin.daemon.options"
|
public val COMPILE_DAEMON_OPTIONS_PROPERTY: String = "kotlin.daemon.options"
|
||||||
public val COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY: String = "kotlin.daemon.client.alive.path"
|
public val COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY: String = "kotlin.daemon.client.alive.path"
|
||||||
|
public val COMPILE_DAEMON_LOG_PATH_PROPERTY: String = "kotlin.daemon.log.path"
|
||||||
public val COMPILE_DAEMON_REPORT_PERF_PROPERTY: String = "kotlin.daemon.perf"
|
public val COMPILE_DAEMON_REPORT_PERF_PROPERTY: String = "kotlin.daemon.perf"
|
||||||
public val COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY: String = "kotlin.daemon.verbose"
|
public val COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY: String = "kotlin.daemon.verbose"
|
||||||
public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String = "--daemon-"
|
public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String = "--daemon-"
|
||||||
@@ -284,7 +285,7 @@ public data class CompilerId(
|
|||||||
public fun isDaemonEnabled(): Boolean = System.getProperty(COMPILE_DAEMON_ENABLED_PROPERTY) != null
|
public fun isDaemonEnabled(): Boolean = System.getProperty(COMPILE_DAEMON_ENABLED_PROPERTY) != null
|
||||||
|
|
||||||
|
|
||||||
public fun configureDaemonJVMOptions(opts: DaemonJVMOptions, inheritMemoryLimits: Boolean): DaemonJVMOptions {
|
public fun configureDaemonJVMOptions(opts: DaemonJVMOptions, inheritMemoryLimits: Boolean, vararg additionalParams: String): DaemonJVMOptions {
|
||||||
// note: sequence matters, explicit override in COMPILE_DAEMON_JVM_OPTIONS_PROPERTY should be done after inputArguments processing
|
// note: sequence matters, explicit override in COMPILE_DAEMON_JVM_OPTIONS_PROPERTY should be done after inputArguments processing
|
||||||
if (inheritMemoryLimits) {
|
if (inheritMemoryLimits) {
|
||||||
ManagementFactory.getRuntimeMXBean().inputArguments.filterExtractProps(opts.mappers, "-")
|
ManagementFactory.getRuntimeMXBean().inputArguments.filterExtractProps(opts.mappers, "-")
|
||||||
@@ -299,12 +300,14 @@ public fun configureDaemonJVMOptions(opts: DaemonJVMOptions, inheritMemoryLimits
|
|||||||
|
|
||||||
System.getProperty(COMPILE_DAEMON_REPORT_PERF_PROPERTY)?.let { opts.jvmParams.add("D" + COMPILE_DAEMON_REPORT_PERF_PROPERTY) }
|
System.getProperty(COMPILE_DAEMON_REPORT_PERF_PROPERTY)?.let { opts.jvmParams.add("D" + COMPILE_DAEMON_REPORT_PERF_PROPERTY) }
|
||||||
System.getProperty(COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY)?.let { opts.jvmParams.add("D" + COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY) }
|
System.getProperty(COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY)?.let { opts.jvmParams.add("D" + COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY) }
|
||||||
|
System.getProperty(COMPILE_DAEMON_LOG_PATH_PROPERTY)?.let { opts.jvmParams.add("D$COMPILE_DAEMON_LOG_PATH_PROPERTY=\"$it\"" ) }
|
||||||
|
opts.jvmParams.addAll(additionalParams)
|
||||||
return opts
|
return opts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public fun configureDaemonJVMOptions(inheritMemoryLimits: Boolean): DaemonJVMOptions =
|
public fun configureDaemonJVMOptions(inheritMemoryLimits: Boolean, vararg additionalParams: String): DaemonJVMOptions =
|
||||||
configureDaemonJVMOptions(DaemonJVMOptions(), inheritMemoryLimits = inheritMemoryLimits)
|
configureDaemonJVMOptions(DaemonJVMOptions(), inheritMemoryLimits = inheritMemoryLimits, additionalParams = *additionalParams)
|
||||||
|
|
||||||
|
|
||||||
public fun configureDaemonOptions(opts: DaemonOptions): DaemonOptions {
|
public fun configureDaemonOptions(opts: DaemonOptions): DaemonOptions {
|
||||||
|
|||||||
@@ -59,18 +59,19 @@ class LogStream(name: String) : OutputStream() {
|
|||||||
public object CompileDaemon {
|
public object CompileDaemon {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val logPath: String = System.getProperty("kotlin.daemon.log.path")?.trimEnd('/','\\') ?: "%t"
|
|
||||||
val logTime: String = SimpleDateFormat("yyyy-MM-dd.HH-mm-ss-SSS").format(Date())
|
val logTime: String = SimpleDateFormat("yyyy-MM-dd.HH-mm-ss-SSS").format(Date())
|
||||||
|
val (logPath: String, fileIsGiven: Boolean) =
|
||||||
|
System.getProperty(COMPILE_DAEMON_LOG_PATH_PROPERTY)?.trimQuotes()?.let { Pair(it, File(it).isFile) } ?: Pair("%t", false)
|
||||||
val cfg: String =
|
val cfg: String =
|
||||||
"handlers = java.util.logging.FileHandler\n" +
|
"handlers = java.util.logging.FileHandler\n" +
|
||||||
"java.util.logging.FileHandler.level = ALL\n" +
|
"java.util.logging.FileHandler.level = ALL\n" +
|
||||||
"java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter\n" +
|
"java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter\n" +
|
||||||
"java.util.logging.FileHandler.encoding = UTF-8\n" +
|
"java.util.logging.FileHandler.encoding = UTF-8\n" +
|
||||||
"java.util.logging.FileHandler.limit = 1073741824\n" + // 1Mb
|
"java.util.logging.FileHandler.limit = ${if (fileIsGiven) 0 else (1 shl 20)}\n" + // if file is provided - disabled, else - 1Mb
|
||||||
"java.util.logging.FileHandler.count = 3\n" +
|
"java.util.logging.FileHandler.count = ${if (fileIsGiven) 1 else 3}\n" +
|
||||||
"java.util.logging.FileHandler.append = false\n" +
|
"java.util.logging.FileHandler.append = $fileIsGiven\n" +
|
||||||
"java.util.logging.FileHandler.pattern = $logPath/$COMPILE_DAEMON_DEFAULT_FILES_PREFIX.$logTime.%u%g.log\n" +
|
"java.util.logging.FileHandler.pattern = ${if (fileIsGiven) logPath else (logPath + File.separator + "$COMPILE_DAEMON_DEFAULT_FILES_PREFIX.$logTime.%u%g.log")}\n" +
|
||||||
"java.util.logging.SimpleFormatter.format = %1\$tF %1\$tT.%1\$tL [%3\$s] %4\$s: %5\$s\\n\n"
|
"java.util.logging.SimpleFormatter.format = %1\$tF %1\$tT.%1\$tL [%3\$s] %4\$s: %5\$s\\n\n"
|
||||||
|
|
||||||
LogManager.getLogManager().readConfiguration(cfg.byteInputStream())
|
LogManager.getLogManager().readConfiguration(cfg.byteInputStream())
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-23
@@ -19,22 +19,17 @@ package org.jetbrains.kotlin.rmi.service
|
|||||||
import org.jetbrains.kotlin.cli.common.CLICompiler
|
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.config.Services
|
import org.jetbrains.kotlin.config.Services
|
||||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
|
||||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
|
||||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||||
import org.jetbrains.kotlin.modules.TargetId
|
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
||||||
import org.jetbrains.kotlin.rmi.*
|
import org.jetbrains.kotlin.rmi.*
|
||||||
import java.io.IOException
|
|
||||||
import java.io.PrintStream
|
import java.io.PrintStream
|
||||||
import java.lang.management.ManagementFactory
|
import java.lang.management.ManagementFactory
|
||||||
import java.lang.management.ThreadMXBean
|
import java.lang.management.ThreadMXBean
|
||||||
import java.net.URLClassLoader
|
|
||||||
import java.rmi.NoSuchObjectException
|
import java.rmi.NoSuchObjectException
|
||||||
import java.rmi.registry.Registry
|
import java.rmi.registry.Registry
|
||||||
import java.rmi.server.UnicastRemoteObject
|
import java.rmi.server.UnicastRemoteObject
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
import java.util.jar.Manifest
|
|
||||||
import java.util.logging.Logger
|
import java.util.logging.Logger
|
||||||
import kotlin.concurrent.read
|
import kotlin.concurrent.read
|
||||||
import kotlin.concurrent.write
|
import kotlin.concurrent.write
|
||||||
@@ -65,6 +60,7 @@ class CompileServiceImpl<Compiler: CLICompiler<*>>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun remoteCompile(args: Array<out String>,
|
override fun remoteCompile(args: Array<out String>,
|
||||||
|
services: CompileService.RemoteCompilationServices,
|
||||||
compilerOutputStream: RemoteOutputStream,
|
compilerOutputStream: RemoteOutputStream,
|
||||||
outputFormat: CompileService.OutputFormat,
|
outputFormat: CompileService.OutputFormat,
|
||||||
serviceOutputStream: RemoteOutputStream
|
serviceOutputStream: RemoteOutputStream
|
||||||
@@ -77,7 +73,7 @@ class CompileServiceImpl<Compiler: CLICompiler<*>>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun remoteIncrementalCompile(args: Array<out String>,
|
override fun remoteIncrementalCompile(args: Array<out String>,
|
||||||
caches: Map<TargetId, CompileService.RemoteIncrementalCache>,
|
services: CompileService.RemoteCompilationServices,
|
||||||
compilerOutputStream: RemoteOutputStream,
|
compilerOutputStream: RemoteOutputStream,
|
||||||
compilerOutputFormat: CompileService.OutputFormat,
|
compilerOutputFormat: CompileService.OutputFormat,
|
||||||
serviceOutputStream: RemoteOutputStream
|
serviceOutputStream: RemoteOutputStream
|
||||||
@@ -85,7 +81,7 @@ class CompileServiceImpl<Compiler: CLICompiler<*>>(
|
|||||||
doCompile(args, compilerOutputStream, serviceOutputStream) { printStream ->
|
doCompile(args, compilerOutputStream, serviceOutputStream) { printStream ->
|
||||||
when (compilerOutputFormat) {
|
when (compilerOutputFormat) {
|
||||||
CompileService.OutputFormat.PLAIN -> throw NotImplementedError("Only XML output is supported in remote incremental compilation")
|
CompileService.OutputFormat.PLAIN -> throw NotImplementedError("Only XML output is supported in remote incremental compilation")
|
||||||
CompileService.OutputFormat.XML -> compiler.execAndOutputXml(printStream, createCompileServices(caches), *args)
|
CompileService.OutputFormat.XML -> compiler.execAndOutputXml(printStream, createCompileServices(services), *args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,13 +123,6 @@ class CompileServiceImpl<Compiler: CLICompiler<*>>(
|
|||||||
alive = true
|
alive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
private class IncrementalCompilationComponentsImpl(val targetToCache: Map<TargetId, CompileService.RemoteIncrementalCache>): IncrementalCompilationComponents {
|
|
||||||
// perf: cheap object, but still the pattern may be costly if there are too many calls to cache with the same id (which seems not to be the case now)
|
|
||||||
override fun getIncrementalCache(target: TargetId): IncrementalCache = RemoteIncrementalCacheClient(targetToCache[target]!!)
|
|
||||||
// TODO: add appropriate proxy into interaction when lookup tracker is needed
|
|
||||||
override fun getLookupTracker(): LookupTracker = LookupTracker.DO_NOTHING
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun doCompile(args: Array<out String>, compilerMessagesStreamProxy: RemoteOutputStream, serviceOutputStreamProxy: RemoteOutputStream, body: (PrintStream) -> ExitCode): Int =
|
private fun doCompile(args: Array<out String>, compilerMessagesStreamProxy: RemoteOutputStream, serviceOutputStreamProxy: RemoteOutputStream, body: (PrintStream) -> ExitCode): Int =
|
||||||
ifAlive {
|
ifAlive {
|
||||||
val compilerMessagesStream = PrintStream(RemoteOutputStreamClient(compilerMessagesStreamProxy))
|
val compilerMessagesStream = PrintStream(RemoteOutputStreamClient(compilerMessagesStreamProxy))
|
||||||
@@ -145,14 +134,12 @@ class CompileServiceImpl<Compiler: CLICompiler<*>>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createCompileServices(incrementalCaches: Map<TargetId, CompileService.RemoteIncrementalCache>): Services =
|
private fun createCompileServices(services: CompileService.RemoteCompilationServices): Services {
|
||||||
Services.Builder()
|
val builder = Services.Builder()
|
||||||
.register(IncrementalCompilationComponents::class.java, IncrementalCompilationComponentsImpl(incrementalCaches))
|
services.incrementalCompilationComponents?.let { builder.register(IncrementalCompilationComponents::class.java, RemoteIncrementalCompilationComponentsClient(it)) }
|
||||||
// TODO: add remote proxy for cancellation status tracking
|
services.compilationCanceledStatus?.let { builder.register(CompilationCanceledStatus::class.java, RemoteCompilationCanceledStatusClient(it)) }
|
||||||
// .register(javaClass<CompilationCanceledStatus>(), object: CompilationCanceledStatus {
|
return builder.build()
|
||||||
// override fun checkCanceled(): Unit = if (context.getCancelStatus().isCanceled()) throw CompilationCanceledException()
|
}
|
||||||
// })
|
|
||||||
.build()
|
|
||||||
|
|
||||||
|
|
||||||
fun usedMemory(): Long {
|
fun usedMemory(): Long {
|
||||||
|
|||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.rmi.service
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
||||||
|
import org.jetbrains.kotlin.rmi.CompileService
|
||||||
|
|
||||||
|
|
||||||
|
class RemoteCompilationCanceledStatusClient(val proxy: CompileService.RemoteCompilationCanceledStatus): CompilationCanceledStatus {
|
||||||
|
override fun checkCanceled() {
|
||||||
|
proxy.checkCanceled()
|
||||||
|
}
|
||||||
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.rmi.service
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||||
|
import org.jetbrains.kotlin.modules.TargetId
|
||||||
|
import org.jetbrains.kotlin.rmi.CompileService
|
||||||
|
|
||||||
|
|
||||||
|
class RemoteIncrementalCompilationComponentsClient(val proxy: CompileService.RemoteIncrementalCompilationComponents) : IncrementalCompilationComponents {
|
||||||
|
|
||||||
|
override fun getIncrementalCache(target: TargetId): IncrementalCache = RemoteIncrementalCacheClient(proxy.getIncrementalCache(target))
|
||||||
|
|
||||||
|
override fun getLookupTracker(): LookupTracker = RemoteLookupTrackerClient(proxy.getLookupTracker())
|
||||||
|
}
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.rmi.service
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||||
|
import org.jetbrains.kotlin.incremental.components.ScopeKind
|
||||||
|
import org.jetbrains.kotlin.rmi.CompileService
|
||||||
|
|
||||||
|
|
||||||
|
class RemoteLookupTrackerClient(val proxy: CompileService.RemoteLookupTracker) : LookupTracker {
|
||||||
|
|
||||||
|
private val isDoNothing = proxy.isDoNothing()
|
||||||
|
|
||||||
|
override fun record(lookupContainingFile: String, lookupLine: Int?, lookupColumn: Int?, scopeFqName: String, scopeKind: ScopeKind, name: String) {
|
||||||
|
if (!isDoNothing)
|
||||||
|
proxy.record(lookupContainingFile, lookupLine, lookupColumn, scopeFqName, scopeKind, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,54 +30,78 @@ public class CompilerDaemonTest : KotlinIntegrationTestBase() {
|
|||||||
|
|
||||||
data class CompilerResults(val resultCode: Int, val out: String)
|
data class CompilerResults(val resultCode: Int, val out: String)
|
||||||
|
|
||||||
val daemonOptions by lazy(LazyThreadSafetyMode.NONE) { DaemonOptions(runFilesPath = tmpdir.absolutePath) }
|
val compilerClassPath = listOf(
|
||||||
val daemonJVMOptions by lazy(LazyThreadSafetyMode.NONE) { DaemonJVMOptions() }
|
File(KotlinIntegrationTestBase.getCompilerLib(), "kotlin-compiler.jar"))
|
||||||
val compilerId by lazy(LazyThreadSafetyMode.NONE) {
|
val compilerId by lazy(LazyThreadSafetyMode.NONE) { CompilerId.makeCompilerId(compilerClassPath) }
|
||||||
CompilerId.makeCompilerId(
|
|
||||||
File(KotlinIntegrationTestBase.getCompilerLib(), "kotlin-compiler.jar"),
|
private fun compileOnDaemon(compilerId: CompilerId, daemonJVMOptions: DaemonJVMOptions, daemonOptions: DaemonOptions, vararg args: String): CompilerResults {
|
||||||
File("dependencies/bootstrap-compiler/Kotlin/kotlinc/lib/kotlin-runtime.jar"),
|
val daemon = KotlinCompilerClient.connectToCompileService(compilerId, daemonJVMOptions, daemonOptions, DaemonReportingTargets(out = System.err), autostart = true, checkId = true)
|
||||||
File("dependencies/bootstrap-compiler/Kotlin/kotlinc/lib/kotlin-reflect.jar"))
|
TestCase.assertNotNull("failed to connect daemon", daemon)
|
||||||
|
val strm = ByteArrayOutputStream()
|
||||||
|
val code = KotlinCompilerClient.compile(daemon!!, args, strm)
|
||||||
|
return CompilerResults(code, strm.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun compileOnDaemon(args: Array<out String>): CompilerResults {
|
private fun runDaemonCompilerTwice(compilerId: CompilerId, daemonJVMOptions: DaemonJVMOptions, daemonOptions: DaemonOptions, vararg args: String): Unit {
|
||||||
System.setProperty(COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY, "")
|
val res1 = compileOnDaemon(compilerId, daemonJVMOptions, daemonOptions, *args)
|
||||||
try {
|
|
||||||
val daemon = KotlinCompilerClient.connectToCompileService(compilerId, daemonJVMOptions, daemonOptions, DaemonReportingTargets(out = System.err), autostart = true, checkId = true)
|
|
||||||
TestCase.assertNotNull("failed to connect daemon", daemon)
|
|
||||||
val strm = ByteArrayOutputStream()
|
|
||||||
val code = KotlinCompilerClient.compile(daemon!!, args, strm)
|
|
||||||
return CompilerResults(code, strm.toString())
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
System.clearProperty(COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun runDaemonCompilerTwice(logName: String, vararg arguments: String): Unit {
|
|
||||||
KotlinCompilerClient.shutdownCompileService(daemonOptions)
|
|
||||||
|
|
||||||
try {
|
|
||||||
val res1 = compileOnDaemon(arguments)
|
|
||||||
TestCase.assertEquals("first compilation failed:\n${res1.out}", 0, res1.resultCode)
|
TestCase.assertEquals("first compilation failed:\n${res1.out}", 0, res1.resultCode)
|
||||||
val res2 = compileOnDaemon(arguments)
|
val res2 = compileOnDaemon(compilerId, daemonJVMOptions, daemonOptions, *args)
|
||||||
TestCase.assertEquals("second compilation failed:\n${res2.out}", 0, res2.resultCode)
|
TestCase.assertEquals("second compilation failed:\n${res2.out}", 0, res2.resultCode)
|
||||||
TestCase.assertEquals("build results differ", CliBaseTest.removePerfOutput(res1.out), CliBaseTest.removePerfOutput(res2.out))
|
TestCase.assertEquals("build results differ", CliBaseTest.removePerfOutput(res1.out), CliBaseTest.removePerfOutput(res2.out))
|
||||||
// TODO: add performance comparison assert
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
KotlinCompilerClient.shutdownCompileService(daemonOptions)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getTestBaseDir(): String = JetTestUtils.getTestDataPathBase() + "/integration/smoke/" + getTestName(true)
|
private fun getTestBaseDir(): String = JetTestUtils.getTestDataPathBase() + "/integration/smoke/" + getTestName(true)
|
||||||
|
private fun getHelloAppBaseDir(): String = JetTestUtils.getTestDataPathBase() + "/integration/smoke/helloApp"
|
||||||
|
|
||||||
private fun run(logName: String, vararg args: String): Int = runJava(getTestBaseDir(), logName, *args)
|
private fun run(logName: String, vararg args: String): Int = runJava(getTestBaseDir(), logName, *args)
|
||||||
|
|
||||||
public fun testHelloApp() {
|
|
||||||
val jar = tmpdir.absolutePath + File.separator + "hello.jar"
|
|
||||||
|
|
||||||
runDaemonCompilerTwice("hello.compile", "-include-runtime", File(getTestBaseDir(), "hello.kt").absolutePath, "-d", jar)
|
public fun testHelloApp() {
|
||||||
run("hello.run", "-cp", jar, "Hello.HelloPackage")
|
val flagFile = createTempFile(getTestName(true), ".alive")
|
||||||
|
flagFile.deleteOnExit()
|
||||||
|
val daemonOptions = DaemonOptions(runFilesPath = File(tmpdir, getTestName(true)).absolutePath,
|
||||||
|
clientAliveFlagPath = flagFile.absolutePath)
|
||||||
|
|
||||||
|
KotlinCompilerClient.shutdownCompileService(compilerId, daemonOptions)
|
||||||
|
|
||||||
|
val logFile = createTempFile("kotlin-daemon-test.", ".log")
|
||||||
|
|
||||||
|
val daemonJVMOptions = configureDaemonJVMOptions(false,
|
||||||
|
"D$COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY",
|
||||||
|
"D$COMPILE_DAEMON_LOG_PATH_PROPERTY=\"${logFile.absolutePath}\"")
|
||||||
|
var daemonShotDown = false
|
||||||
|
|
||||||
|
try {
|
||||||
|
val jar = tmpdir.absolutePath + File.separator + "hello.jar"
|
||||||
|
runDaemonCompilerTwice(compilerId, daemonJVMOptions, daemonOptions,
|
||||||
|
"-include-runtime", File(getTestBaseDir(), "hello.kt").absolutePath, "-d", jar)
|
||||||
|
|
||||||
|
KotlinCompilerClient.shutdownCompileService(compilerId, daemonOptions)
|
||||||
|
daemonShotDown = true
|
||||||
|
var compileTime1 = 0L
|
||||||
|
var compileTime2 = 0L
|
||||||
|
logFile.reader().useLines {
|
||||||
|
it.ifNotContainsSequence( LinePattern("Kotlin compiler daemon version"),
|
||||||
|
LinePattern("Starting compilation with args: "),
|
||||||
|
LinePattern("Elapsed time: (\\d+) ms", { it.groups.get(1)?.value?.toLong()?.let { compileTime1 = it }; true } ),
|
||||||
|
LinePattern("Starting compilation with args: "),
|
||||||
|
LinePattern("Elapsed time: (\\d+) ms", { it.groups.get(1)?.value?.toLong()?.let { compileTime2 = it }; true } ),
|
||||||
|
LinePattern("Shutdown complete"))
|
||||||
|
{ unmatchedPattern, lineNo ->
|
||||||
|
TestCase.fail("pattern not found in the input: " + unmatchedPattern.regex +
|
||||||
|
"\nunmatched part of the log file (" + logFile.absolutePath +
|
||||||
|
") from line " + lineNo + ":\n\n" + logFile.reader().useLines { it.drop(lineNo).joinToString("\n") })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TestCase.assertTrue("Expecting that compilation 1 ($compileTime1 ms) is at least two times longer than compilation 2 ($compileTime2 ms)",
|
||||||
|
compileTime1 > compileTime2 * 2)
|
||||||
|
logFile.delete()
|
||||||
|
run("hello.run", "-cp", jar, "Hello.HelloPackage")
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if (!daemonShotDown)
|
||||||
|
KotlinCompilerClient.shutdownCompileService(compilerId, daemonOptions)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun testDaemonJvmOptionsParsing() {
|
public fun testDaemonJvmOptionsParsing() {
|
||||||
@@ -91,12 +115,12 @@ public class CompilerDaemonTest : KotlinIntegrationTestBase() {
|
|||||||
TestCase.assertEquals(arrayListOf("aaa", "bbb,ccc", "ddd", "xxx,yyy"), opts.jvmParams)
|
TestCase.assertEquals(arrayListOf("aaa", "bbb,ccc", "ddd", "xxx,yyy"), opts.jvmParams)
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
backupJvmOptions?.let { System.setProperty(COMPILE_DAEMON_JVM_OPTIONS_PROPERTY, it) }
|
restoreSystemProperty(COMPILE_DAEMON_JVM_OPTIONS_PROPERTY, backupJvmOptions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun testDaemonOptionsParsing() {
|
public fun testDaemonOptionsParsing() {
|
||||||
val backupJvmOptions = System.getProperty(COMPILE_DAEMON_OPTIONS_PROPERTY)
|
val backupOptions = System.getProperty(COMPILE_DAEMON_OPTIONS_PROPERTY)
|
||||||
try {
|
try {
|
||||||
System.setProperty(COMPILE_DAEMON_OPTIONS_PROPERTY, "runFilesPath=abcd,clientAliveFlagPath=efgh,autoshutdownIdleSeconds=1111")
|
System.setProperty(COMPILE_DAEMON_OPTIONS_PROPERTY, "runFilesPath=abcd,clientAliveFlagPath=efgh,autoshutdownIdleSeconds=1111")
|
||||||
val opts = configureDaemonOptions()
|
val opts = configureDaemonOptions()
|
||||||
@@ -105,7 +129,71 @@ public class CompilerDaemonTest : KotlinIntegrationTestBase() {
|
|||||||
TestCase.assertEquals(1111, opts.autoshutdownIdleSeconds)
|
TestCase.assertEquals(1111, opts.autoshutdownIdleSeconds)
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
backupJvmOptions?.let { System.setProperty(COMPILE_DAEMON_OPTIONS_PROPERTY, it) }
|
restoreSystemProperty(COMPILE_DAEMON_OPTIONS_PROPERTY, backupOptions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun testDaemonInstances() {
|
||||||
|
val jar = tmpdir.absolutePath + File.separator + "hello1.jar"
|
||||||
|
val flagFile = createTempFile(getTestName(true), ".alive")
|
||||||
|
flagFile.deleteOnExit()
|
||||||
|
val daemonOptions = DaemonOptions(runFilesPath = File(tmpdir, getTestName(true)).absolutePath,
|
||||||
|
clientAliveFlagPath = flagFile.absolutePath)
|
||||||
|
val compilerId2 = CompilerId.makeCompilerId(compilerClassPath +
|
||||||
|
File(KotlinIntegrationTestBase.getCompilerLib(), "kotlin-compiler-sources.jar"))
|
||||||
|
|
||||||
|
KotlinCompilerClient.shutdownCompileService(compilerId, daemonOptions)
|
||||||
|
KotlinCompilerClient.shutdownCompileService(compilerId2, daemonOptions)
|
||||||
|
|
||||||
|
val logFile1 = createTempFile("kotlin-daemon1-test", ".log")
|
||||||
|
val logFile2 = createTempFile("kotlin-daemon2-test", ".log")
|
||||||
|
val daemonJVMOptions1 =
|
||||||
|
configureDaemonJVMOptions(false,
|
||||||
|
"D$COMPILE_DAEMON_LOG_PATH_PROPERTY=\"${logFile1.absolutePath}\"")
|
||||||
|
val daemonJVMOptions2 =
|
||||||
|
configureDaemonJVMOptions(false,
|
||||||
|
"D$COMPILE_DAEMON_LOG_PATH_PROPERTY=\"${logFile2.absolutePath}\"")
|
||||||
|
|
||||||
|
TestCase.assertTrue(logFile1.length() == 0L && logFile2.length() == 0L)
|
||||||
|
|
||||||
|
val res1 = compileOnDaemon(compilerId, daemonJVMOptions1, daemonOptions,
|
||||||
|
"-include-runtime", File(getHelloAppBaseDir(), "hello.kt").absolutePath, "-d", jar)
|
||||||
|
TestCase.assertEquals("first compilation failed:\n${res1.out}", 0, res1.resultCode)
|
||||||
|
|
||||||
|
logFile1.assertLogContainsSequence("Starting compilation with args: ")
|
||||||
|
TestCase.assertEquals("expecting '${logFile2.absolutePath}' to be empty", 0L, logFile2.length())
|
||||||
|
|
||||||
|
val res2 = compileOnDaemon(compilerId2, daemonJVMOptions2, daemonOptions,
|
||||||
|
"-include-runtime", File(getHelloAppBaseDir(), "hello.kt").absolutePath, "-d", jar)
|
||||||
|
TestCase.assertEquals("second compilation failed:\n${res2.out}", 0, res1.resultCode)
|
||||||
|
|
||||||
|
logFile2.assertLogContainsSequence("Starting compilation with args: ")
|
||||||
|
|
||||||
|
KotlinCompilerClient.shutdownCompileService(compilerId, daemonOptions)
|
||||||
|
logFile1.assertLogContainsSequence("Shutdown complete")
|
||||||
|
logFile1.delete()
|
||||||
|
|
||||||
|
KotlinCompilerClient.shutdownCompileService(compilerId2, daemonOptions)
|
||||||
|
logFile2.assertLogContainsSequence("Shutdown complete")
|
||||||
|
logFile2.delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun File.assertLogContainsSequence(vararg patterns: String) {
|
||||||
|
reader().useLines {
|
||||||
|
it.ifNotContainsSequence( patterns.map { LinePattern(it) })
|
||||||
|
{
|
||||||
|
pattern,lineNo -> TestCase.fail("Pattern '${pattern.regex}' is not found in the log file '$absolutePath'")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun restoreSystemProperty(propertyName: String, backupValue: String?) {
|
||||||
|
if (backupValue == null) {
|
||||||
|
System.clearProperty(propertyName)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.setProperty(propertyName, backupValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.daemon
|
||||||
|
|
||||||
|
import kotlin.text.MatchResult
|
||||||
|
import kotlin.text.Regex
|
||||||
|
|
||||||
|
/**
|
||||||
|
* holder of a [regex] and optional [matchCheck] for additional checks on match result
|
||||||
|
*/
|
||||||
|
internal class LinePattern(val regex: Regex, val matchCheck: (MatchResult) -> Boolean = { true })
|
||||||
|
internal fun LinePattern(regex: String, matchCheck: (MatchResult) -> Boolean = { true }) = LinePattern(regex.toRegex(), matchCheck)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* calls [body] if receiver does not contain complete sequence of lines matched by [patternsIter], separated by any number of other lines
|
||||||
|
* [body] receives first unmatched pattern and index of last matched line in the sequence
|
||||||
|
*/
|
||||||
|
internal fun Sequence<String>.ifNotContainsSequence(patternsIter: Iterator<LinePattern>,
|
||||||
|
body: (LinePattern, Int) -> Unit) : Unit {
|
||||||
|
class Accumulator(it: Iterator<LinePattern>) {
|
||||||
|
val iter = EndBoundIteratorWithValue(it)
|
||||||
|
var lineNo = 1
|
||||||
|
var lastMatchedLineNo = 0
|
||||||
|
fun nextLineAndPattern(): Accumulator { iter.traverseNext(); lastMatchedLineNo = lineNo; return nextLine() }
|
||||||
|
fun nextLine(): Accumulator { lineNo++; return this }
|
||||||
|
}
|
||||||
|
val res = fold(Accumulator(patternsIter))
|
||||||
|
{ acc, line ->
|
||||||
|
when {
|
||||||
|
!acc.iter.isValid() -> return@fold acc
|
||||||
|
acc.iter.value.regex.match(line)?.let { acc.iter.value.matchCheck(it) } ?: false -> acc.nextLineAndPattern()
|
||||||
|
else -> acc.nextLine()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (res.iter.isValid()) {
|
||||||
|
body(res.iter.value, res.lastMatchedLineNo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* calls [body] if receiver does not contain complete sequence of lines matched by [patterns], separated by any number of other lines
|
||||||
|
* [body] receives first unmatched pattern and index of last matched line in the sequence
|
||||||
|
*/
|
||||||
|
internal fun Sequence<String>.ifNotContainsSequence(patterns: List<LinePattern>,
|
||||||
|
body: (LinePattern, Int) -> Unit): Unit {
|
||||||
|
ifNotContainsSequence(patterns.iterator(), body)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* calls [body] if receiver does not contain complete sequence of lines matched by [patterns], separated by any number of other lines
|
||||||
|
* [body] receives first unmatched pattern and index of last matched line in the sequence
|
||||||
|
*/
|
||||||
|
internal fun Sequence<String>.ifNotContainsSequence(vararg patterns: LinePattern,
|
||||||
|
body: (LinePattern, Int) -> Unit): Unit {
|
||||||
|
ifNotContainsSequence(patterns.iterator(), body)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// emulates Stepanov's / STL iterator, but with "embedded" end check via isValid:
|
||||||
|
// iterator points to a current value and upon init points to the first element or is invalid
|
||||||
|
// allows to express some algorithms more concisely
|
||||||
|
private class EndBoundIteratorWithValue<T: Any, Iter: Iterator<T>>(val base: Iter) {
|
||||||
|
private var _value: T? = base.nextOrNull()
|
||||||
|
|
||||||
|
val value: T get() = _value ?: throw Exception("Dereferencing invalid iterator")
|
||||||
|
|
||||||
|
fun isValid(): Boolean = _value != null
|
||||||
|
|
||||||
|
fun traverseNext(): EndBoundIteratorWithValue<T, Iter> {
|
||||||
|
_value = base.nextOrNull()
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun<T: Any> Iterator<T>.nextOrNull(): T? = if (hasNext()) next() else null
|
||||||
@@ -1,274 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2015 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.compilerRunner;
|
|
||||||
|
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
|
||||||
import com.intellij.util.ArrayUtil;
|
|
||||||
import com.intellij.util.Function;
|
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
|
||||||
import com.intellij.util.xmlb.XmlSerializerUtil;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.kotlin.cli.common.ExitCode;
|
|
||||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments;
|
|
||||||
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments;
|
|
||||||
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.common.messages.MessageCollectorUtil;
|
|
||||||
import org.jetbrains.kotlin.config.CompilerSettings;
|
|
||||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache;
|
|
||||||
import org.jetbrains.kotlin.modules.TargetId;
|
|
||||||
import org.jetbrains.kotlin.rmi.*;
|
|
||||||
import org.jetbrains.kotlin.rmi.kotlinr.DaemonReportCategory;
|
|
||||||
import org.jetbrains.kotlin.rmi.kotlinr.DaemonReportMessage;
|
|
||||||
import org.jetbrains.kotlin.rmi.kotlinr.DaemonReportingTargets;
|
|
||||||
import org.jetbrains.kotlin.rmi.kotlinr.KotlinCompilerClient;
|
|
||||||
import org.jetbrains.kotlin.utils.UtilsPackage;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation.NO_LOCATION;
|
|
||||||
import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR;
|
|
||||||
import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO;
|
|
||||||
|
|
||||||
public class KotlinCompilerRunner {
|
|
||||||
private static final String K2JVM_COMPILER = "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler";
|
|
||||||
private static final String K2JS_COMPILER = "org.jetbrains.kotlin.cli.js.K2JSCompiler";
|
|
||||||
private static final String INTERNAL_ERROR = ExitCode.INTERNAL_ERROR.toString();
|
|
||||||
|
|
||||||
public static void runK2JvmCompiler(
|
|
||||||
CommonCompilerArguments commonArguments,
|
|
||||||
K2JVMCompilerArguments k2jvmArguments,
|
|
||||||
CompilerSettings compilerSettings,
|
|
||||||
MessageCollector messageCollector,
|
|
||||||
CompilerEnvironment environment,
|
|
||||||
Map<TargetId, IncrementalCache> incrementalCaches,
|
|
||||||
File moduleFile,
|
|
||||||
OutputItemsCollector collector
|
|
||||||
) {
|
|
||||||
K2JVMCompilerArguments arguments = mergeBeans(commonArguments, k2jvmArguments);
|
|
||||||
setupK2JvmArguments(moduleFile, arguments);
|
|
||||||
|
|
||||||
runCompiler(K2JVM_COMPILER, arguments, compilerSettings.getAdditionalArguments(), messageCollector, collector, environment,
|
|
||||||
incrementalCaches);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void runK2JsCompiler(
|
|
||||||
@NotNull CommonCompilerArguments commonArguments,
|
|
||||||
@NotNull K2JSCompilerArguments k2jsArguments,
|
|
||||||
@NotNull CompilerSettings compilerSettings,
|
|
||||||
@NotNull MessageCollector messageCollector,
|
|
||||||
@NotNull CompilerEnvironment environment,
|
|
||||||
Map<TargetId, IncrementalCache> incrementalCaches,
|
|
||||||
@NotNull OutputItemsCollector collector,
|
|
||||||
@NotNull Collection<File> sourceFiles,
|
|
||||||
@NotNull List<String> libraryFiles,
|
|
||||||
@NotNull File outputFile
|
|
||||||
) {
|
|
||||||
K2JSCompilerArguments arguments = mergeBeans(commonArguments, k2jsArguments);
|
|
||||||
setupK2JsArguments(outputFile, sourceFiles, libraryFiles, arguments);
|
|
||||||
|
|
||||||
runCompiler(K2JS_COMPILER, arguments, compilerSettings.getAdditionalArguments(), messageCollector, collector, environment,
|
|
||||||
incrementalCaches);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ProcessCompilerOutput(
|
|
||||||
MessageCollector messageCollector,
|
|
||||||
OutputItemsCollector collector,
|
|
||||||
ByteArrayOutputStream stream,
|
|
||||||
String exitCode
|
|
||||||
) {
|
|
||||||
BufferedReader reader = new BufferedReader(new StringReader(stream.toString()));
|
|
||||||
CompilerOutputParser.parseCompilerMessagesFromReader(messageCollector, reader, collector);
|
|
||||||
|
|
||||||
if (INTERNAL_ERROR.equals(exitCode)) {
|
|
||||||
reportInternalCompilerError(messageCollector);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void reportInternalCompilerError(MessageCollector messageCollector) {
|
|
||||||
messageCollector.report(ERROR, "Compiler terminated with internal error", NO_LOCATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void runCompiler(
|
|
||||||
String compilerClassName,
|
|
||||||
CommonCompilerArguments arguments,
|
|
||||||
String additionalArguments,
|
|
||||||
MessageCollector messageCollector,
|
|
||||||
OutputItemsCollector collector,
|
|
||||||
CompilerEnvironment environment,
|
|
||||||
Map<TargetId, IncrementalCache> incrementalCaches
|
|
||||||
) {
|
|
||||||
try {
|
|
||||||
messageCollector.report(INFO, "Using kotlin-home = " + environment.getKotlinPaths().getHomePath(), NO_LOCATION);
|
|
||||||
|
|
||||||
List<String> argumentsList = ArgumentUtils.convertArgumentsToStringList(arguments);
|
|
||||||
argumentsList.addAll(StringUtil.split(additionalArguments, " "));
|
|
||||||
|
|
||||||
String[] argsArray = ArrayUtil.toStringArray(argumentsList);
|
|
||||||
|
|
||||||
if (!tryCompileWithDaemon(messageCollector, collector, environment, incrementalCaches, argsArray)) {
|
|
||||||
// otherwise fallback to in-process
|
|
||||||
|
|
||||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
|
||||||
PrintStream out = new PrintStream(stream);
|
|
||||||
|
|
||||||
Object rc = CompilerRunnerUtil.invokeExecMethod( compilerClassName, argsArray, environment, messageCollector, out);
|
|
||||||
|
|
||||||
// exec() returns an ExitCode object, class of which is loaded with a different class loader,
|
|
||||||
// so we take it's contents through reflection
|
|
||||||
ProcessCompilerOutput(messageCollector, collector, stream, getReturnCodeFromObject(rc));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Throwable e) {
|
|
||||||
MessageCollectorUtil.reportException(messageCollector, e);
|
|
||||||
reportInternalCompilerError(messageCollector);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean tryCompileWithDaemon(
|
|
||||||
MessageCollector messageCollector,
|
|
||||||
OutputItemsCollector collector,
|
|
||||||
CompilerEnvironment environment,
|
|
||||||
Map<TargetId, IncrementalCache> incrementalCaches,
|
|
||||||
String[] argsArray
|
|
||||||
) throws IOException {
|
|
||||||
if (incrementalCaches != null && RmiPackage.isDaemonEnabled()) {
|
|
||||||
File libPath = CompilerRunnerUtil.getLibPath(environment.getKotlinPaths(), messageCollector);
|
|
||||||
// TODO: it may be a good idea to cache the compilerId, since making it means calculating digest over jar(s) and if \\
|
|
||||||
// the lifetime of JPS process is small anyway, we can neglect the probability of changed compiler
|
|
||||||
CompilerId compilerId = CompilerId.makeCompilerId(new File(libPath, "kotlin-compiler.jar"));
|
|
||||||
DaemonOptions daemonOptions = RmiPackage.configureDaemonOptions();
|
|
||||||
DaemonJVMOptions daemonJVMOptions = RmiPackage.configureDaemonJVMOptions(true);
|
|
||||||
|
|
||||||
ArrayList<DaemonReportMessage> daemonReportMessages = new ArrayList<DaemonReportMessage>();
|
|
||||||
|
|
||||||
CompileService daemon = KotlinCompilerClient.connectToCompileService(compilerId, daemonJVMOptions, daemonOptions, new DaemonReportingTargets(null, daemonReportMessages), true, true);
|
|
||||||
|
|
||||||
for (DaemonReportMessage msg: daemonReportMessages) {
|
|
||||||
if (msg.getCategory() == DaemonReportCategory.EXCEPTION && daemon == null) {
|
|
||||||
messageCollector.report(CompilerMessageSeverity.INFO,
|
|
||||||
"Falling back to compilation without daemon due to error: " + msg.getMessage(),
|
|
||||||
CompilerMessageLocation.NO_LOCATION);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
messageCollector.report(CompilerMessageSeverity.INFO, msg.getMessage(), CompilerMessageLocation.NO_LOCATION);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (daemon != null) {
|
|
||||||
ByteArrayOutputStream compilerOut = new ByteArrayOutputStream();
|
|
||||||
ByteArrayOutputStream daemonOut = new ByteArrayOutputStream();
|
|
||||||
|
|
||||||
Integer res = KotlinCompilerClient.incrementalCompile(daemon, argsArray, incrementalCaches, compilerOut, daemonOut);
|
|
||||||
|
|
||||||
ProcessCompilerOutput(messageCollector, collector, compilerOut, res.toString());
|
|
||||||
BufferedReader reader = new BufferedReader(new StringReader(daemonOut.toString()));
|
|
||||||
String line = null;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
messageCollector.report(CompilerMessageSeverity.INFO, line, CompilerMessageLocation.NO_LOCATION);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static String getReturnCodeFromObject(@Nullable Object rc) throws Exception {
|
|
||||||
if (rc == null) {
|
|
||||||
return INTERNAL_ERROR;
|
|
||||||
}
|
|
||||||
else if (ExitCode.class.getName().equals(rc.getClass().getName())) {
|
|
||||||
return rc.toString();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new IllegalStateException("Unexpected return: " + rc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T extends CommonCompilerArguments> T mergeBeans(CommonCompilerArguments from, T to) {
|
|
||||||
// TODO: rewrite when updated version of com.intellij.util.xmlb is available on TeamCity
|
|
||||||
try {
|
|
||||||
T copy = XmlSerializerUtil.createCopy(to);
|
|
||||||
|
|
||||||
List<Field> fromFields = collectFieldsToCopy(from.getClass());
|
|
||||||
for (Field fromField : fromFields) {
|
|
||||||
Field toField = copy.getClass().getField(fromField.getName());
|
|
||||||
toField.set(copy, fromField.get(from));
|
|
||||||
}
|
|
||||||
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
catch (NoSuchFieldException e) {
|
|
||||||
throw UtilsPackage.rethrow(e);
|
|
||||||
}
|
|
||||||
catch (IllegalAccessException e) {
|
|
||||||
throw UtilsPackage.rethrow(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<Field> collectFieldsToCopy(Class<?> clazz) {
|
|
||||||
List<Field> fromFields = new ArrayList<Field>();
|
|
||||||
|
|
||||||
Class currentClass = clazz;
|
|
||||||
do {
|
|
||||||
for (Field field : currentClass.getDeclaredFields()) {
|
|
||||||
int modifiers = field.getModifiers();
|
|
||||||
if (!Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers)) {
|
|
||||||
fromFields.add(field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while ((currentClass = currentClass.getSuperclass()) != null);
|
|
||||||
|
|
||||||
return fromFields;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void setupK2JvmArguments(File moduleFile, K2JVMCompilerArguments settings) {
|
|
||||||
settings.module = moduleFile.getAbsolutePath();
|
|
||||||
settings.noStdlib = true;
|
|
||||||
settings.noJdkAnnotations = true;
|
|
||||||
settings.noJdk = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void setupK2JsArguments(
|
|
||||||
@NotNull File outputFile,
|
|
||||||
@NotNull Collection<File> sourceFiles,
|
|
||||||
@NotNull List<String> libraryFiles,
|
|
||||||
@NotNull K2JSCompilerArguments settings
|
|
||||||
) {
|
|
||||||
settings.noStdlib = true;
|
|
||||||
settings.freeArgs = ContainerUtil.map(sourceFiles, new Function<File, String>() {
|
|
||||||
@Override
|
|
||||||
public String fun(File file) {
|
|
||||||
return file.getPath();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
settings.outputFile = outputFile.getPath();
|
|
||||||
settings.metaInfo = true;
|
|
||||||
settings.libraryFiles = ArrayUtil.toStringArray(libraryFiles);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.compilerRunner
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
|
import com.intellij.util.ArrayUtil
|
||||||
|
import com.intellij.util.Function
|
||||||
|
import com.intellij.util.containers.ContainerUtil
|
||||||
|
import com.intellij.util.xmlb.XmlSerializerUtil
|
||||||
|
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||||
|
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||||
|
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
|
||||||
|
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.CompilerMessageSeverity.ERROR
|
||||||
|
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO
|
||||||
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||||
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil
|
||||||
|
import org.jetbrains.kotlin.config.CompilerSettings
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||||
|
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
||||||
|
import org.jetbrains.kotlin.rmi.CompilerId
|
||||||
|
import org.jetbrains.kotlin.rmi.configureDaemonJVMOptions
|
||||||
|
import org.jetbrains.kotlin.rmi.configureDaemonOptions
|
||||||
|
import org.jetbrains.kotlin.rmi.isDaemonEnabled
|
||||||
|
import org.jetbrains.kotlin.rmi.kotlinr.*
|
||||||
|
import org.jetbrains.kotlin.utils.rethrow
|
||||||
|
import java.io.*
|
||||||
|
import java.lang.reflect.Field
|
||||||
|
import java.lang.reflect.Modifier
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
public object KotlinCompilerRunner {
|
||||||
|
private val K2JVM_COMPILER = "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler"
|
||||||
|
private val K2JS_COMPILER = "org.jetbrains.kotlin.cli.js.K2JSCompiler"
|
||||||
|
private val INTERNAL_ERROR = ExitCode.INTERNAL_ERROR.toString()
|
||||||
|
|
||||||
|
public fun runK2JvmCompiler(
|
||||||
|
commonArguments: CommonCompilerArguments,
|
||||||
|
k2jvmArguments: K2JVMCompilerArguments,
|
||||||
|
compilerSettings: CompilerSettings,
|
||||||
|
messageCollector: MessageCollector,
|
||||||
|
environment: CompilerEnvironment,
|
||||||
|
moduleFile: File,
|
||||||
|
collector: OutputItemsCollector) {
|
||||||
|
val arguments = mergeBeans(commonArguments, k2jvmArguments)
|
||||||
|
setupK2JvmArguments(moduleFile, arguments)
|
||||||
|
|
||||||
|
runCompiler(K2JVM_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment)
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun runK2JsCompiler(
|
||||||
|
commonArguments: CommonCompilerArguments,
|
||||||
|
k2jsArguments: K2JSCompilerArguments,
|
||||||
|
compilerSettings: CompilerSettings,
|
||||||
|
messageCollector: MessageCollector,
|
||||||
|
environment: CompilerEnvironment,
|
||||||
|
collector: OutputItemsCollector,
|
||||||
|
sourceFiles: Collection<File>,
|
||||||
|
libraryFiles: List<String>,
|
||||||
|
outputFile: File) {
|
||||||
|
val arguments = mergeBeans(commonArguments, k2jsArguments)
|
||||||
|
setupK2JsArguments(outputFile, sourceFiles, libraryFiles, arguments)
|
||||||
|
|
||||||
|
runCompiler(K2JS_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun processCompilerOutput(
|
||||||
|
messageCollector: MessageCollector,
|
||||||
|
collector: OutputItemsCollector,
|
||||||
|
stream: ByteArrayOutputStream,
|
||||||
|
exitCode: String) {
|
||||||
|
val reader = BufferedReader(StringReader(stream.toString()))
|
||||||
|
CompilerOutputParser.parseCompilerMessagesFromReader(messageCollector, reader, collector)
|
||||||
|
|
||||||
|
if (INTERNAL_ERROR == exitCode) {
|
||||||
|
reportInternalCompilerError(messageCollector)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun reportInternalCompilerError(messageCollector: MessageCollector) {
|
||||||
|
messageCollector.report(ERROR, "Compiler terminated with internal error", CompilerMessageLocation.NO_LOCATION)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun runCompiler(
|
||||||
|
compilerClassName: String,
|
||||||
|
arguments: CommonCompilerArguments,
|
||||||
|
additionalArguments: String,
|
||||||
|
messageCollector: MessageCollector,
|
||||||
|
collector: OutputItemsCollector,
|
||||||
|
environment: CompilerEnvironment) {
|
||||||
|
try {
|
||||||
|
messageCollector.report(INFO, "Using kotlin-home = " + environment.kotlinPaths.homePath, CompilerMessageLocation.NO_LOCATION)
|
||||||
|
|
||||||
|
val argumentsList = ArgumentUtils.convertArgumentsToStringList(arguments)
|
||||||
|
argumentsList.addAll(additionalArguments.split(" "))
|
||||||
|
|
||||||
|
val argsArray = argumentsList.toTypedArray()
|
||||||
|
|
||||||
|
if (!tryCompileWithDaemon(messageCollector, collector, environment, argsArray)) {
|
||||||
|
// otherwise fallback to in-process
|
||||||
|
|
||||||
|
val stream = ByteArrayOutputStream()
|
||||||
|
val out = PrintStream(stream)
|
||||||
|
|
||||||
|
val rc = CompilerRunnerUtil.invokeExecMethod(compilerClassName, argsArray, environment, messageCollector, out)
|
||||||
|
|
||||||
|
// exec() returns an ExitCode object, class of which is loaded with a different class loader,
|
||||||
|
// so we take it's contents through reflection
|
||||||
|
processCompilerOutput(messageCollector, collector, stream, getReturnCodeFromObject(rc))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e: Throwable) {
|
||||||
|
MessageCollectorUtil.reportException(messageCollector, e)
|
||||||
|
reportInternalCompilerError(messageCollector)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun tryCompileWithDaemon(messageCollector: MessageCollector,
|
||||||
|
collector: OutputItemsCollector,
|
||||||
|
environment: CompilerEnvironment,
|
||||||
|
argsArray: Array<String>): Boolean {
|
||||||
|
|
||||||
|
if (isDaemonEnabled()) {
|
||||||
|
val libPath = CompilerRunnerUtil.getLibPath(environment.kotlinPaths, messageCollector)
|
||||||
|
// TODO: it may be a good idea to cache the compilerId, since making it means calculating digest over jar(s) and if \\
|
||||||
|
// the lifetime of JPS process is small anyway, we can neglect the probability of changed compiler
|
||||||
|
val compilerId = CompilerId.makeCompilerId(File(libPath, "kotlin-compiler.jar"))
|
||||||
|
val daemonOptions = configureDaemonOptions()
|
||||||
|
val daemonJVMOptions = configureDaemonJVMOptions(true)
|
||||||
|
|
||||||
|
val daemonReportMessages = ArrayList<DaemonReportMessage>()
|
||||||
|
|
||||||
|
val daemon = KotlinCompilerClient.connectToCompileService(compilerId, daemonJVMOptions, daemonOptions, DaemonReportingTargets(null, daemonReportMessages), true, true)
|
||||||
|
|
||||||
|
for (msg in daemonReportMessages) {
|
||||||
|
if (msg.category === DaemonReportCategory.EXCEPTION && daemon == null) {
|
||||||
|
messageCollector.report(CompilerMessageSeverity.INFO,
|
||||||
|
"Falling back to compilation without daemon due to error: " + msg.message,
|
||||||
|
CompilerMessageLocation.NO_LOCATION)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
messageCollector.report(CompilerMessageSeverity.INFO, msg.message, CompilerMessageLocation.NO_LOCATION)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (daemon != null) {
|
||||||
|
val compilerOut = ByteArrayOutputStream()
|
||||||
|
val daemonOut = ByteArrayOutputStream()
|
||||||
|
|
||||||
|
val services = CompilationServices(
|
||||||
|
incrementalCompilationComponents = environment.services.get(IncrementalCompilationComponents::class.java),
|
||||||
|
compilationCanceledStatus = environment.services.get(CompilationCanceledStatus::class.java))
|
||||||
|
|
||||||
|
val res = KotlinCompilerClient.incrementalCompile(daemon, argsArray, services, compilerOut, daemonOut)
|
||||||
|
|
||||||
|
processCompilerOutput(messageCollector, collector, compilerOut, res.toString())
|
||||||
|
BufferedReader(StringReader(daemonOut.toString())).forEachLine {
|
||||||
|
messageCollector.report(CompilerMessageSeverity.INFO, it, CompilerMessageLocation.NO_LOCATION)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getReturnCodeFromObject(rc: Any?): String {
|
||||||
|
when {
|
||||||
|
rc == null -> return INTERNAL_ERROR
|
||||||
|
ExitCode::class.java.name == rc.javaClass.name -> return rc.toString()
|
||||||
|
else -> throw IllegalStateException("Unexpected return: " + rc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T : CommonCompilerArguments> mergeBeans(from: CommonCompilerArguments, to: T): T {
|
||||||
|
// TODO: rewrite when updated version of com.intellij.util.xmlb is available on TeamCity
|
||||||
|
val copy = XmlSerializerUtil.createCopy(to)
|
||||||
|
|
||||||
|
val fromFields = collectFieldsToCopy(from.javaClass)
|
||||||
|
for (fromField in fromFields) {
|
||||||
|
val toField = copy.javaClass.getField(fromField.name)
|
||||||
|
toField.set(copy, fromField.get(from))
|
||||||
|
}
|
||||||
|
|
||||||
|
return copy
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun collectFieldsToCopy(clazz: Class<*>): List<Field> {
|
||||||
|
val fromFields = ArrayList<Field>()
|
||||||
|
|
||||||
|
var currentClass: Class<*>? = clazz
|
||||||
|
while (currentClass != null) {
|
||||||
|
for (field in currentClass.declaredFields) {
|
||||||
|
val modifiers = field.modifiers
|
||||||
|
if (!Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers)) {
|
||||||
|
fromFields.add(field)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentClass = currentClass.superclass
|
||||||
|
}
|
||||||
|
|
||||||
|
return fromFields
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupK2JvmArguments(moduleFile: File, settings: K2JVMCompilerArguments) {
|
||||||
|
with(settings) {
|
||||||
|
module = moduleFile.absolutePath
|
||||||
|
noStdlib = true
|
||||||
|
noJdkAnnotations = true
|
||||||
|
noJdk = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupK2JsArguments( _outputFile: File, sourceFiles: Collection<File>, _libraryFiles: List<String>, settings: K2JSCompilerArguments) {
|
||||||
|
with(settings) {
|
||||||
|
noStdlib = true
|
||||||
|
freeArgs = sourceFiles.map { it.path }
|
||||||
|
outputFile = _outputFile.path
|
||||||
|
metaInfo = true
|
||||||
|
libraryFiles = _libraryFiles.toTypedArray()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,8 +47,7 @@ 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.common.messages.OutputMessageUtil
|
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
|
||||||
import org.jetbrains.kotlin.compilerRunner.CompilerEnvironment
|
import org.jetbrains.kotlin.compilerRunner.CompilerEnvironment
|
||||||
import org.jetbrains.kotlin.compilerRunner.KotlinCompilerRunner.runK2JsCompiler
|
import org.jetbrains.kotlin.compilerRunner.KotlinCompilerRunner
|
||||||
import org.jetbrains.kotlin.compilerRunner.KotlinCompilerRunner.runK2JvmCompiler
|
|
||||||
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
|
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
|
||||||
import org.jetbrains.kotlin.config.CompilerRunnerConstants
|
import org.jetbrains.kotlin.config.CompilerRunnerConstants
|
||||||
import org.jetbrains.kotlin.config.CompilerRunnerConstants.INTERNAL_ERROR_PREFIX
|
import org.jetbrains.kotlin.config.CompilerRunnerConstants.INTERNAL_ERROR_PREFIX
|
||||||
@@ -319,10 +318,7 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return compileToJvm(allCompiledFiles, chunk, commonArguments, context, dirtyFilesHolder, environment,
|
return compileToJvm(allCompiledFiles, chunk, commonArguments, context, dirtyFilesHolder, environment, filesToCompile, messageCollector)
|
||||||
incrementalCaches.mapKeysTo(HashMap<TargetId, IncrementalCache>(incrementalCaches.size()),
|
|
||||||
{ TargetId(it.getKey()) }),
|
|
||||||
filesToCompile, messageCollector)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createCompileEnvironment(
|
private fun createCompileEnvironment(
|
||||||
@@ -520,7 +516,7 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
|
|||||||
val compilerSettings = JpsKotlinCompilerSettings.getCompilerSettings(project)
|
val compilerSettings = JpsKotlinCompilerSettings.getCompilerSettings(project)
|
||||||
val k2JsArguments = JpsKotlinCompilerSettings.getK2JsCompilerArguments(project)
|
val k2JsArguments = JpsKotlinCompilerSettings.getK2JsCompilerArguments(project)
|
||||||
|
|
||||||
runK2JsCompiler(commonArguments, k2JsArguments, compilerSettings, messageCollector, environment, incrementalCaches, outputItemCollector, sourceFiles, libraryFiles, outputFile)
|
KotlinCompilerRunner.runK2JsCompiler(commonArguments, k2JsArguments, compilerSettings, messageCollector, environment, outputItemCollector, sourceFiles, libraryFiles, outputFile)
|
||||||
return outputItemCollector
|
return outputItemCollector
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -543,7 +539,6 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
|
|||||||
context: CompileContext,
|
context: CompileContext,
|
||||||
dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>,
|
dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>,
|
||||||
environment: CompilerEnvironment,
|
environment: CompilerEnvironment,
|
||||||
incrementalCaches: MutableMap<TargetId, IncrementalCache>?,
|
|
||||||
filesToCompile: MultiMap<ModuleBuildTarget, File>, messageCollector: MessageCollectorAdapter
|
filesToCompile: MultiMap<ModuleBuildTarget, File>, messageCollector: MessageCollectorAdapter
|
||||||
): OutputItemsCollectorImpl? {
|
): OutputItemsCollectorImpl? {
|
||||||
val outputItemCollector = OutputItemsCollectorImpl()
|
val outputItemCollector = OutputItemsCollectorImpl()
|
||||||
@@ -587,7 +582,7 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
|
|||||||
+ (if (totalRemovedFiles == 0) "" else " ($totalRemovedFiles removed files)")
|
+ (if (totalRemovedFiles == 0) "" else " ($totalRemovedFiles removed files)")
|
||||||
+ " in " + filesToCompile.keySet().map { it.getPresentableName() }.join())
|
+ " in " + filesToCompile.keySet().map { it.getPresentableName() }.join())
|
||||||
|
|
||||||
runK2JvmCompiler(commonArguments, k2JvmArguments, compilerSettings, messageCollector, environment, incrementalCaches, moduleFile, outputItemCollector)
|
KotlinCompilerRunner.runK2JvmCompiler(commonArguments, k2JvmArguments, compilerSettings, messageCollector, environment, moduleFile, outputItemCollector)
|
||||||
moduleFile.delete()
|
moduleFile.delete()
|
||||||
|
|
||||||
return outputItemCollector
|
return outputItemCollector
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import com.intellij.util.PathUtil
|
|||||||
import org.jetbrains.jps.model.java.JpsJavaExtensionService
|
import org.jetbrains.jps.model.java.JpsJavaExtensionService
|
||||||
import org.jetbrains.kotlin.rmi.COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY
|
import org.jetbrains.kotlin.rmi.COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY
|
||||||
import org.jetbrains.kotlin.rmi.COMPILE_DAEMON_ENABLED_PROPERTY
|
import org.jetbrains.kotlin.rmi.COMPILE_DAEMON_ENABLED_PROPERTY
|
||||||
|
import org.jetbrains.kotlin.rmi.COMPILE_DAEMON_LOG_PATH_PROPERTY
|
||||||
import org.jetbrains.kotlin.rmi.COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY
|
import org.jetbrains.kotlin.rmi.COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY
|
||||||
import org.jetbrains.kotlin.test.JetTestUtils
|
import org.jetbrains.kotlin.test.JetTestUtils
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -71,12 +72,15 @@ public class SimpleKotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() {
|
|||||||
System.setProperty(COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY, "")
|
System.setProperty(COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY, "")
|
||||||
// spaces in the name to test proper file name handling
|
// spaces in the name to test proper file name handling
|
||||||
val flagFile = File.createTempFile("kotlin-jps - tests-", "-is-running");
|
val flagFile = File.createTempFile("kotlin-jps - tests-", "-is-running");
|
||||||
|
val logFile = File.createTempFile("kotlin-daemon", ".log")
|
||||||
|
System.setProperty(COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY, flagFile.absolutePath)
|
||||||
|
System.setProperty(COMPILE_DAEMON_LOG_PATH_PROPERTY, logFile.absolutePath)
|
||||||
try {
|
try {
|
||||||
System.setProperty(COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY, flagFile.absolutePath)
|
|
||||||
testLoadingKotlinFromDifferentModules()
|
testLoadingKotlinFromDifferentModules()
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
flagFile.delete()
|
flagFile.delete()
|
||||||
|
System.clearProperty(COMPILE_DAEMON_LOG_PATH_PROPERTY)
|
||||||
System.clearProperty(COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY)
|
System.clearProperty(COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY)
|
||||||
System.clearProperty(COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY)
|
System.clearProperty(COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY)
|
||||||
System.clearProperty(COMPILE_DAEMON_ENABLED_PROPERTY)
|
System.clearProperty(COMPILE_DAEMON_ENABLED_PROPERTY)
|
||||||
|
|||||||
Reference in New Issue
Block a user