diff --git a/dist/kobaltw b/dist/kobaltw index 4f39dc35..333738df 100755 --- a/dist/kobaltw +++ b/dist/kobaltw @@ -1,7 +1,11 @@ #!/usr/bin/env sh -DIRNAME=`dirname $(readlink -f "$0")` -if [[ "$(uname)" == "CYGWIN"* ]]; then - DIRNAME=`cygpath -d "$DIRNAME"` +case "$(uname)" in + CYGWIN*) DIRNAME=$(cygpath -d "$(dirname "$(readlink -f "$0")")");; + Darwin*) DIRNAME=$(dirname "$(readlink "$0")");; + *) DIRNAME=$(dirname "$(readlink -f "$0")");; +esac +if [ "$DIRNAME" = "." ]; then + DIRNAME="$(dirname "$0")" fi java -jar "${DIRNAME}/../kobalt/wrapper/kobalt-wrapper.jar" $* \ No newline at end of file diff --git a/kobalt/src/Build.kt b/kobalt/src/Build.kt index a497aac2..99ee7f52 100644 --- a/kobalt/src/Build.kt +++ b/kobalt/src/Build.kt @@ -43,7 +43,6 @@ object Versions { val junitVintageVersion = "$junit.0-M4" } - fun mavenResolver(vararg m: String) = m.map { "org.apache.maven.resolver:maven-resolver-$it:${Versions.mavenResolver}" } .toTypedArray() @@ -114,7 +113,7 @@ val kobaltPluginApi = project { "org.slf4j:slf4j-simple:${Versions.slf4j}", *mavenResolver("api", "spi", "util", "impl", "connector-basic", "transport-http", "transport-file"), "org.apache.maven:maven-aether-provider:3.3.9", - "org.testng.testng-remote:testng-remote:1.3.0", + "org.testng.testng-remote:testng-remote:1.3.2", "org.testng:testng:${Versions.testng}", "commons-io:commons-io:2.5", "org.junit.platform:junit-platform-surefire-provider:${Versions.junitPlatform}", @@ -140,12 +139,8 @@ val kobaltPluginApi = project { } } -// install { -// libDir = "lib-test" -// } - kotlinCompiler { - args("-nowarn") + args("nowarn") } bintray { @@ -233,7 +228,7 @@ val kobaltApp = project(kobaltPluginApi, wrapper) { } kotlinCompiler { - args("-nowarn") + args("nowarn") } bintray { diff --git a/kobalt/wrapper/kobalt-wrapper.properties b/kobalt/wrapper/kobalt-wrapper.properties index f5e39865..842b3300 100644 --- a/kobalt/wrapper/kobalt-wrapper.properties +++ b/kobalt/wrapper/kobalt-wrapper.properties @@ -1 +1 @@ -kobalt.version=1.0.62 +kobalt.version=1.0.72 \ No newline at end of file diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/BuildScript.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/BuildScript.kt index 48ecc0e3..4c35b9ed 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/BuildScript.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/BuildScript.kt @@ -74,8 +74,18 @@ data class ProxyConfig(val host: String = "", val port: Int = 0, val type: Strin fun toAetherProxy() = Proxy(type, host, port) // TODO make support for proxy auth } -data class HostConfig(var url: String = "", var name: String = url, var username: String? = null, - var password: String? = null) { +data class HostConfig(var url: String = "", var name: String = HostConfig.createRepoName(url), + var username: String? = null, var password: String? = null) { + + companion object { + /** + * For repos specified in the build file (repos()) that don't have an associated unique name, + * create such a name from the URL. This is a requirement from Maven Resolver, and failing to do + * this leads to very weird resolution errors. + */ + private fun createRepoName(url: String) = url.replace("/", "_").replace("\\", "_").replace(":", "_") + } + fun hasAuth() : Boolean { return (! username.isNullOrBlank()) && (! password.isNullOrBlank()) } @@ -106,6 +116,7 @@ fun buildFileClasspath(vararg deps: String) { } fun newBuildFileClasspath(vararg deps: String) { + //FIXME newBuildFileClasspath called twice deps.forEach { Kobalt.addBuildFileClasspath(it) } } @@ -115,7 +126,7 @@ fun authRepos(vararg repos : HostConfig) { } @Directive -fun authRepo(init: HostConfig.() -> Unit) = HostConfig().apply { init() } +fun authRepo(init: HostConfig.() -> Unit) = HostConfig(name = "").apply { init() } @Directive fun glob(g: String) : IFileSpec.GlobSpec = IFileSpec.GlobSpec(g) diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/SystemProperties.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/SystemProperties.kt index b003aa9f..898f0594 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/SystemProperties.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/SystemProperties.kt @@ -2,8 +2,10 @@ package com.beust.kobalt class SystemProperties { companion object { - val javaBase = System.getProperty("java.home") ?: - (System.getenv("JAVA_HOME") ?: throw IllegalArgumentException("JAVA_HOME not defined")) + val javaBase = + System.getenv("JAVA_HOME") + ?: System.getProperty("java.home") + ?: throw IllegalArgumentException("JAVA_HOME not defined") val javaVersion = System.getProperty("java.version") val homeDir = System.getProperty("user.home") val tmpDir = System.getProperty("java.io.tmpdir") diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/CompilerActionInfo.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/CompilerActionInfo.kt index d2521255..e323e474 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/CompilerActionInfo.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/CompilerActionInfo.kt @@ -12,4 +12,5 @@ data class CompilerActionInfo(val directory: String?, val outputDir: File, val compilerArgs: List, val friendPaths: List, - val forceRecompile: Boolean) + val forceRecompile: Boolean, + val compilerSeparateProcess: Boolean = false) diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/Kobalt.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/Kobalt.kt index 527d35b2..7d37a0b8 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/Kobalt.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/Kobalt.kt @@ -5,6 +5,7 @@ import com.beust.kobalt.HostConfig import com.beust.kobalt.Plugins import com.beust.kobalt.internal.PluginInfo import com.beust.kobalt.maven.DependencyManager +import com.beust.kobalt.maven.aether.KobaltMavenResolver import com.google.inject.Guice import com.google.inject.Injector import com.google.inject.Module @@ -55,6 +56,9 @@ class Kobalt { // Repos from the build file result.addAll(reposFromBuildFiles) + result.forEach { + KobaltMavenResolver.initAuthentication(it) + } return result.toHashSet() } @@ -131,6 +135,7 @@ class Kobalt { fun cleanUp() { buildSourceDirs.clear() + buildFileClasspath.clear() } } } diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/GenericRunner.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/GenericRunner.kt index 01836be1..fb2b0927 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/GenericRunner.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/GenericRunner.kt @@ -4,6 +4,7 @@ import com.beust.kobalt.* import com.beust.kobalt.api.* import com.beust.kobalt.misc.KFiles import com.google.common.annotations.VisibleForTesting +import com.google.inject.Inject import java.io.File import java.util.* @@ -19,6 +20,9 @@ abstract class GenericTestRunner: ITestRunnerContributor { open var shortMessage: String? = null open var longMessage: String? = null + @Inject + private lateinit var jvm: Jvm + abstract fun args(project: Project, context: KobaltContext, classpath: List, testConfig: TestConfig) : List @@ -26,7 +30,7 @@ abstract class GenericTestRunner: ITestRunnerContributor { open val extraClasspath: List = emptyList() - open fun filterTestClasses(classes: List) : List = classes + open fun filterTestClasses(project: Project, context: KobaltContext, classes: List) : List = classes override fun run(project: Project, context: KobaltContext, configName: String, classpath: List) : TaskResult { @@ -65,7 +69,7 @@ abstract class GenericTestRunner: ITestRunnerContributor { // } context.logger.log(project.name, 2, "Found ${result.size} test classes") - return filterTestClasses(result.map { it.second }) + return filterTestClasses(project, context, result.map { it.second }) } /** @@ -116,7 +120,7 @@ abstract class GenericTestRunner: ITestRunnerContributor { val args = args(project, context, classpath, testConfig) if (args.size > 0) { - val java = JavaInfo.create(File(SystemProperties.javaBase)).javaExecutable + val java = jvm.javaExecutable val jvmArgs = calculateAllJvmArgs(project, context, testConfig, classpath, Kobalt.INJECTOR.getInstance (PluginInfo::class.java)) val allArgs = arrayListOf().apply { diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/JUnitRunner.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/JUnitRunner.kt index bfe6d800..c5b36997 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/JUnitRunner.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/JUnitRunner.kt @@ -4,6 +4,10 @@ import com.beust.kobalt.TestConfig import com.beust.kobalt.api.IClasspathDependency import com.beust.kobalt.api.KobaltContext import com.beust.kobalt.api.Project +import com.beust.kobalt.maven.DependencyManager +import com.google.inject.Inject +import java.lang.reflect.Modifier +import java.net.URLClassLoader open class JUnitRunner() : GenericTestRunner() { @@ -14,5 +18,15 @@ open class JUnitRunner() : GenericTestRunner() { override fun args(project: Project, context: KobaltContext, classpath: List, testConfig: TestConfig) = findTestClasses(project, context, testConfig) + + @Inject + lateinit var dependencyManager: DependencyManager + + override fun filterTestClasses(project: Project, context: KobaltContext, classes: List) : List { + val deps = dependencyManager.testDependencies(project, context) + val cl = URLClassLoader(deps.map { it.jarFile.get().toURI().toURL() }.toTypedArray()) + return classes.filter { !Modifier.isAbstract(cl.loadClass(it).modifiers) } + } + } diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/KotlinTestRunner.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/KotlinTestRunner.kt index b78da1db..24e643d5 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/KotlinTestRunner.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/KotlinTestRunner.kt @@ -1,5 +1,8 @@ package com.beust.kobalt.internal +import com.beust.kobalt.api.KobaltContext +import com.beust.kobalt.api.Project + /** * KotlinTestRunner triggers if it finds a dependency on io.kotlintest but other than that, it just * uses the regular JUnitRunner. @@ -12,6 +15,7 @@ class KotlinTestRunner : JUnitRunner() { * KotlinTestRunner runs tests in the init{} initializer, so ignore all the extra * classes generated by the Kotlin compiler. */ - override fun filterTestClasses(classes: List) = classes.filter { ! it.contains("$") } + override fun filterTestClasses(projet: Project, context: KobaltContext, classes: List) + = classes.filter { !it.contains("$") } } diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/Kurl.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/Kurl.kt index 6b9c0a62..909c18c5 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/Kurl.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/Kurl.kt @@ -1,9 +1,8 @@ package com.beust.kobalt.maven import com.beust.kobalt.HostConfig -import com.beust.kobalt.KobaltException +import com.beust.kobalt.maven.aether.KobaltMavenResolver import com.beust.kobalt.maven.dependency.FileDependency -import com.beust.kobalt.misc.LocalProperties import java.io.* import java.net.HttpURLConnection import java.net.URL @@ -21,27 +20,7 @@ class Kurl(val hostInfo: HostConfig) { } init { - // See if the URL needs to be authenticated. Look in local.properties for keys - // of the format authUrl..user=xxx and authUrl..password=xxx - val properties = LocalProperties().localProperties - val host = java.net.URL(hostInfo.url).host - properties.entries.forEach { - val key = it.key.toString() - if (key == "$KEY.$host.$VALUE_USER") { - hostInfo.username = properties.getProperty(key) - } else if (key == "$KEY.$host.$VALUE_PASSWORD") { - hostInfo.password = properties.getProperty(key) - } - } - fun error(s1: String, s2: String) { - throw KobaltException("Found \"$s1\" but not \"$s2\" in local.properties for $KEY.$host", - docUrl = "http://beust.com/kobalt/documentation/index.html#maven-repos-authenticated") - } - if (! hostInfo.username.isNullOrBlank() && hostInfo.password.isNullOrBlank()) { - error("username", "password") - } else if(hostInfo.username.isNullOrBlank() && ! hostInfo.password.isNullOrBlank()) { - error("password", "username") - } + KobaltMavenResolver.initAuthentication(hostInfo) } override fun toString() = hostInfo.toString() diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/KobaltMavenResolver.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/KobaltMavenResolver.kt index 376081df..18ed6659 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/KobaltMavenResolver.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/aether/KobaltMavenResolver.kt @@ -2,11 +2,14 @@ package com.beust.kobalt.maven.aether import com.beust.kobalt.Args import com.beust.kobalt.HostConfig +import com.beust.kobalt.KobaltException import com.beust.kobalt.api.Kobalt import com.beust.kobalt.internal.KobaltSettings import com.beust.kobalt.internal.getProxy +import com.beust.kobalt.maven.Kurl import com.beust.kobalt.maven.LocalRepo import com.beust.kobalt.maven.MavenId +import com.beust.kobalt.misc.LocalProperties import com.google.common.eventbus.EventBus import com.google.inject.Inject import org.eclipse.aether.artifact.Artifact @@ -21,6 +24,7 @@ import org.eclipse.aether.resolution.DependencyRequest import org.eclipse.aether.resolution.DependencyResult import org.eclipse.aether.resolution.VersionRangeRequest import org.eclipse.aether.resolution.VersionRangeResult +import org.eclipse.aether.util.repository.AuthenticationBuilder import java.util.* class KobaltMavenResolver @Inject constructor(val settings: KobaltSettings, @@ -32,6 +36,31 @@ class KobaltMavenResolver @Inject constructor(val settings: KobaltSettings, MavenId.toId(it.groupId, it.artifactId, it.extension, it.classifier, it.version) } fun isRangeVersion(id: String) = id.contains(",") + + fun initAuthentication(hostInfo: HostConfig) { + // See if the URL needs to be authenticated. Look in local.properties for keys + // of the format authUrl..user=xxx and authUrl..password=xxx + val properties = LocalProperties().localProperties + val host = java.net.URL(hostInfo.url).host + properties.entries.forEach { + val key = it.key.toString() + if (key == "${Kurl.KEY}.$host.${Kurl.VALUE_USER}") { + hostInfo.username = properties.getProperty(key) + } else if (key == "${Kurl.KEY}.$host.${Kurl.VALUE_PASSWORD}") { + hostInfo.password = properties.getProperty(key) + } + } + fun error(s1: String, s2: String) { + throw KobaltException("Found \"$s1\" but not \"$s2\" in local.properties for ${Kurl.KEY}.$host", + docUrl = "http://beust.com/kobalt/documentation/index.html#maven-repos-authenticated") + } + if (! hostInfo.username.isNullOrBlank() && hostInfo.password.isNullOrBlank()) { + error("username", "password") + } else if(hostInfo.username.isNullOrBlank() && ! hostInfo.password.isNullOrBlank()) { + error("password", "username") + } + + } } fun resolveToArtifact(id: String, scope: Scope? = null, @@ -110,8 +139,17 @@ class KobaltMavenResolver @Inject constructor(val settings: KobaltSettings, private val system = Booter.newRepositorySystem() private val session = Booter.newRepositorySystemSession(system, localRepo.localRepo, settings, eventBus) - private fun createRepo(hostConfig: HostConfig) = - RemoteRepository.Builder(hostConfig.name, "default", hostConfig.url).build() + private fun createRepo(hostConfig: HostConfig) : RemoteRepository { + val builder = RemoteRepository.Builder(hostConfig.name, "default", hostConfig.url) + if (hostConfig.hasAuth()) { + val auth = AuthenticationBuilder() + .addUsername(hostConfig.username) + .addPassword(hostConfig.password) + .build() + builder.setAuthentication(auth) + } + return builder.build() + } private val kobaltRepositories: List get() = Kobalt.repos.map { diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/NewRunCommand.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/NewRunCommand.kt index 67b666a6..7188cf10 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/NewRunCommand.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/NewRunCommand.kt @@ -79,10 +79,12 @@ open class NewRunCommand(val info: RunCommandInfo) { // Run the command and collect the return code and streams val returnCode = process.waitFor(30, TimeUnit.SECONDS) - val input = if (process.inputStream.available() > 0) fromStream(process.inputStream) - else listOf() - val error = if (process.errorStream.available() > 0) fromStream(process.errorStream) - else listOf() + val input = + if (process.inputStream.available() > 0) fromStream(process.inputStream) + else listOf() + val error = + if (process.errorStream.available() > 0) fromStream(process.errorStream) + else listOf() // Check to see if the command succeeded val isSuccess = @@ -105,10 +107,10 @@ open class NewRunCommand(val info: RunCommandInfo) { open protected fun isSuccess(isSuccess: Boolean, input: List, error: List) : Boolean { var hasErrors = ! isSuccess if (info.useErrorStreamAsErrorIndicator && ! hasErrors) { - hasErrors = hasErrors || error.size > 0 + hasErrors = hasErrors || error.isNotEmpty() } if (info.useInputStreamAsErrorIndicator && ! hasErrors) { - hasErrors = hasErrors || input.size > 0 + hasErrors = hasErrors || input.isNotEmpty() } return ! hasErrors diff --git a/src/main/kotlin/com/beust/kobalt/Options.kt b/src/main/kotlin/com/beust/kobalt/Options.kt index 16166e11..615b4d64 100644 --- a/src/main/kotlin/com/beust/kobalt/Options.kt +++ b/src/main/kotlin/com/beust/kobalt/Options.kt @@ -3,6 +3,7 @@ package com.beust.kobalt import com.beust.jcommander.JCommander import com.beust.kobalt.api.Kobalt import com.beust.kobalt.api.PluginTask +import com.beust.kobalt.api.Project import com.beust.kobalt.app.ProjectFinder import com.beust.kobalt.app.ProjectGenerator import com.beust.kobalt.app.Templates @@ -44,10 +45,26 @@ class Options @Inject constructor( val p = if (args.buildFile != null) File(args.buildFile) else File(".") // val buildFile = BuildFile(Paths.get(p.absolutePath), p.name) val buildSources = if (p.isDirectory) BuildSources(p.absoluteFile) else SingleFileBuildSources(p) - var pluginClassLoader = javaClass.classLoader + val pluginClassLoader = javaClass.classLoader - val allProjectResult = projectFinder.initForBuildFile(buildSources, args) - val allProjects = allProjectResult.projects + // + // Attempt to parse the build file in order to correctly set up repos, plug-ins, etc... + // If the build file can't be parsed, don't give up just yet since some options don't need + // a correct build file to work. + // + var buildError: Throwable? = null + val allProjects = + try { + projectFinder.initForBuildFile(buildSources, args).projects + } catch(ex: Exception) { + buildError = ex + listOf() + } + + fun runIfSuccessfulBuild(buildError: Throwable?, action: () -> Unit) { + buildError?.let { throw it } + action() + } // Modify `args` with options found in buildScript { kobaltOptions(...) }, if any addOptionsFromBuild(args, Kobalt.optionsFromBuild) @@ -77,9 +94,11 @@ class Options @Inject constructor( }), Option( { -> args.projectInfo }, { // --projectInfo - allProjects.forEach { - it.compileDependencies.filter { it.isMaven }.forEach { - resolveDependency.run(it.id) + runIfSuccessfulBuild(buildError) { + allProjects.forEach { + it.compileDependencies.filter { it.isMaven }.forEach { + resolveDependency.run(it.id) + } } } }), @@ -89,11 +108,15 @@ class Options @Inject constructor( }), Option( { args.tasks }, { // --tasks - displayTasks() + runIfSuccessfulBuild(buildError) { + displayTasks() + } }), Option( { args.checkVersions }, { // --checkVersions - checkVersions.run(allProjects) + runIfSuccessfulBuild(buildError) { + checkVersions.run(allProjects) + } }), Option( { args.download }, { // --download @@ -121,17 +144,19 @@ class Options @Inject constructor( if (! buildSources.exists()) { throw KobaltException("Could not find build file: " + buildSources) } - val runTargetResult = taskManager.runTargets(args.targets, allProjects) - if (result == 0) { - result = if (runTargetResult.taskResult.success) 0 else 1 - } + runIfSuccessfulBuild(buildError) { + val runTargetResult = taskManager.runTargets(args.targets, allProjects) + if (result == 0) { + result = if (runTargetResult.taskResult.success) 0 else 1 + } - // Shutdown all plug-ins - plugins.shutdownPlugins() + // Shutdown all plug-ins + plugins.shutdownPlugins() - // Run the build report contributors - pluginInfo.buildReportContributors.forEach { - it.generateReport(Kobalt.context!!) + // Run the build report contributors + pluginInfo.buildReportContributors.forEach { + it.generateReport(Kobalt.context!!) + } } } return result diff --git a/src/main/kotlin/com/beust/kobalt/app/MainModule.kt b/src/main/kotlin/com/beust/kobalt/app/MainModule.kt index 8181a3b9..1f9e07b2 100644 --- a/src/main/kotlin/com/beust/kobalt/app/MainModule.kt +++ b/src/main/kotlin/com/beust/kobalt/app/MainModule.kt @@ -1,6 +1,8 @@ package com.beust.kobalt.app import com.beust.kobalt.Args +import com.beust.kobalt.JavaInfo +import com.beust.kobalt.Jvm import com.beust.kobalt.app.remote.KobaltServer import com.beust.kobalt.internal.IncrementalManager import com.beust.kobalt.internal.KobaltSettings @@ -17,6 +19,7 @@ import com.google.inject.Provider import com.google.inject.Singleton import com.google.inject.TypeLiteral import com.google.inject.assistedinject.FactoryModuleBuilder +import java.io.File import java.util.concurrent.ExecutorService open class MainModule(val args: Args, val settings: KobaltSettings) : AbstractModule() { @@ -49,15 +52,14 @@ open class MainModule(val args: Args, val settings: KobaltSettings) : AbstractMo bind(Args::class.java).toProvider(Provider { args }) - EventBus().let { eventBus -> - bind(EventBus::class.java).toInstance(eventBus) - } + bind(EventBus::class.java).toInstance(EventBus()) bind(PluginInfo::class.java).toProvider(Provider { PluginInfo.readKobaltPluginXml() }).`in`(Singleton::class.java) bind(KobaltSettings::class.java).toProvider(Provider { settings }).`in`(Singleton::class.java) + bind(Jvm::class.java).toInstance(JavaInfo.create(File(com.beust.kobalt.SystemProperties.javaBase))) // bindListener(Matchers.any(), object: TypeListener { // override fun hear(typeLiteral: TypeLiteral?, typeEncounter: TypeEncounter?) { diff --git a/src/main/kotlin/com/beust/kobalt/app/remote/RemoteDependencyData.kt b/src/main/kotlin/com/beust/kobalt/app/remote/RemoteDependencyData.kt index bd1914ac..fcd0a80c 100644 --- a/src/main/kotlin/com/beust/kobalt/app/remote/RemoteDependencyData.kt +++ b/src/main/kotlin/com/beust/kobalt/app/remote/RemoteDependencyData.kt @@ -2,6 +2,7 @@ package com.beust.kobalt.app.remote import com.beust.kobalt.Args import com.beust.kobalt.api.IClasspathDependency +import com.beust.kobalt.api.Kobalt import com.beust.kobalt.api.Project import com.beust.kobalt.app.BuildFileCompiler import com.beust.kobalt.internal.DynamicGraph @@ -29,7 +30,7 @@ class RemoteDependencyData @Inject constructor(val executors: KobaltExecutors, v val taskManager: TaskManager) { fun dependenciesDataFor(buildSources: BuildSources, args: Args, - findProjectResult: BuildFileCompiler.FindProjectResult, + projectResult: BuildFileCompiler.FindProjectResult, progressListener: IProgressListener? = null, useGraph : Boolean = false): GetDependenciesData { val projectDatas = arrayListOf() @@ -42,9 +43,7 @@ class RemoteDependencyData @Inject constructor(val executors: KobaltExecutors, v fun allDeps(l: List, name: String) = dependencyManager.transitiveClosure(l, requiredBy = name) -// val buildFile = BuildFile(Paths.get(buildFilePath), "GetDependenciesCommand") - val buildFileCompiler = buildFileCompilerFactory.create(buildSources, pluginInfo) - val projectResult = buildFileCompiler.compileBuildFiles(args) + val buildFileDependencies = Kobalt.buildFileClasspath.map {toDependencyData(it, "compile")} val pluginDependencies = projectResult.pluginUrls.map { File(it.toURI()) }.map { DependencyData(it.name, "compile", it.absolutePath) @@ -176,8 +175,8 @@ class RemoteDependencyData @Inject constructor(val executors: KobaltExecutors, v }) } - return GetDependenciesData(projectDatas, allTasks, pluginDependencies, findProjectResult.buildContentRoots, - projectResult.taskResult.errorMessage) + return GetDependenciesData(projectDatas, allTasks, pluginDependencies, buildFileDependencies, + projectResult.buildContentRoots, projectResult.taskResult.errorMessage) } ///// @@ -202,6 +201,7 @@ class RemoteDependencyData @Inject constructor(val executors: KobaltExecutors, v class GetDependenciesData(val projects: List = emptyList(), val allTasks: Collection = emptySet(), val pluginDependencies: List = emptyList(), + val buildFileDependencies: List = emptyList(), val buildContentRoots: List = emptyList(), val errorMessage: String?) { companion object { diff --git a/src/main/kotlin/com/beust/kobalt/plugin/application/ApplicationPlugin.kt b/src/main/kotlin/com/beust/kobalt/plugin/application/ApplicationPlugin.kt index 032c466d..9fc0b027 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/application/ApplicationPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/application/ApplicationPlugin.kt @@ -1,6 +1,9 @@ package com.beust.kobalt.plugin.application -import com.beust.kobalt.* +import com.beust.kobalt.Jvm +import com.beust.kobalt.KobaltException +import com.beust.kobalt.Plugins +import com.beust.kobalt.TaskResult import com.beust.kobalt.api.* import com.beust.kobalt.api.annotation.Directive import com.beust.kobalt.api.annotation.Task @@ -42,7 +45,7 @@ fun Project.application(init: ApplicationConfig.() -> Unit): ApplicationConfig { @Singleton class ApplicationPlugin @Inject constructor(val configActor: ConfigActor, val executors: KobaltExecutors, val nativeManager: NativeManager, - val dependencyManager: DependencyManager, val taskContributor : TaskContributor) + val dependencyManager: DependencyManager, val taskContributor : TaskContributor, val jvm: Jvm) : BasePlugin(), IRunnerContributor, ITaskContributor, IConfigActor by configActor { companion object { @@ -111,7 +114,7 @@ class ApplicationPlugin @Inject constructor(val configActor: ConfigActor val allDeps = arrayListOf(jarName) - val java = JavaInfo.create(File(SystemProperties.javaBase)).javaExecutable!! + val java = jvm.javaExecutable!! if (! isFatJar(packages, jarName)) { @Suppress("UNCHECKED_CAST") // If the jar file is not fat, we need to add the transitive closure of all dependencies diff --git a/src/main/kotlin/com/beust/kobalt/plugin/apt/AptPlugin.kt b/src/main/kotlin/com/beust/kobalt/plugin/apt/AptPlugin.kt index b90c9f5a..ed743b0f 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/apt/AptPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/apt/AptPlugin.kt @@ -1,10 +1,20 @@ package com.beust.kobalt.plugin.apt +import com.beust.kobalt.Constants +import com.beust.kobalt.Jvm +import com.beust.kobalt.TaskResult import com.beust.kobalt.api.* +import com.beust.kobalt.api.annotation.AnnotationDefault import com.beust.kobalt.api.annotation.Directive +import com.beust.kobalt.internal.CompilerUtils import com.beust.kobalt.maven.DependencyManager +import com.beust.kobalt.maven.aether.Filters +import com.beust.kobalt.maven.aether.Scope +import com.beust.kobalt.maven.dependency.FileDependency import com.beust.kobalt.misc.KFiles +import com.beust.kobalt.misc.KobaltLogger import com.beust.kobalt.misc.warn +import com.beust.kobalt.plugin.kotlin.KotlinPlugin import com.google.common.collect.ArrayListMultimap import com.google.inject.Inject import java.io.File @@ -12,21 +22,62 @@ import java.util.* import javax.inject.Singleton /** - * The AptPlugin has two components: + * The AptPlugin manages both apt and kapt. Each of them has two components: * 1) A new apt directive inside a dependency{} block (similar to compile()) that declares where * the annotation processor is found * 2) An apt{} configuration on Project that lets the user configure how the annotation is performed * (outputDir, etc...). */ @Singleton -class AptPlugin @Inject constructor(val dependencyManager: DependencyManager) - : BasePlugin(), ICompilerFlagContributor, ISourceDirectoryContributor { +class AptPlugin @Inject constructor(val dependencyManager: DependencyManager, val kotlinPlugin: KotlinPlugin, + val compilerUtils: CompilerUtils, val jvm: Jvm) + : BasePlugin(), ICompilerFlagContributor, ISourceDirectoryContributor, IClasspathContributor, ITaskContributor { - // ISourceDirectoryContributor + companion object { + const val PLUGIN_NAME = "Apt" + const val KAPT_CONFIG = "kaptConfig" + const val APT_CONFIG = "aptConfig" + } + + override val name = PLUGIN_NAME + + var kaptConfig: KaptConfig? = null + + override fun apply(project: Project, context: KobaltContext) { + super.apply(project, context) + kaptConfig = kaptConfigs[project.name] + + // Delete the output directories + listOf(aptConfigs[project.name]?.outputDir, kaptConfig?.outputDir) + .filterNotNull() + .distinct() + .map { generatedDir(project, it) } + .forEach { + it.normalize().absolutePath.let { path -> + context.logger.log(project.name, 1, " Deleting " + path) + val success = it.deleteRecursively() + if (!success) warn(" Couldn't delete " + path) + } + } + } + + // IClasspathContributor + override fun classpathEntriesFor(project: Project?, context: KobaltContext): Collection { + val result = arrayListOf() + if (project != null && kaptConfig != null) { + kaptConfig?.let { config -> + val c = generatedClasses(project, context, config.outputDir) + File(c).mkdirs() + result.add(FileDependency(c)) + } + } + return result + } private fun generatedDir(project: Project, outputDir: String) : File - = File(KFiles.joinDir(project.directory, KFiles.KOBALT_BUILD_DIR, outputDir)) + = File(KFiles.joinDir(project.directory, KFiles.KOBALT_BUILD_DIR, outputDir)) + // ISourceDirectoryContributor override fun sourceDirectoriesFor(project: Project, context: KobaltContext): List { val result = arrayListOf() aptConfigs[project.name]?.let { config -> @@ -40,43 +91,157 @@ class AptPlugin @Inject constructor(val dependencyManager: DependencyManager) return result } - companion object { - const val PLUGIN_NAME = "Apt" - const val KAPT_CONFIG = "kaptConfig" - const val APT_CONFIG = "aptConfig" - } - - override val name = PLUGIN_NAME - - override fun apply(project: Project, context: KobaltContext) { - listOf(aptConfigs[project.name]?.outputDir, aptConfigs[project.name]?.outputDir) - .filterNotNull() - .distinct() - .map { generatedDir(project, it) } - .forEach { - it.normalize().absolutePath.let { path -> - context.logger.log(project.name, 1, " Deleting " + path) - val success = it.deleteRecursively() - if (!success) warn(" Couldn't delete " + path) - } - } - } - private fun generated(project: Project, context: KobaltContext, outputDir: String) = - KFiles.joinAndMakeDir(project.directory, project.buildDirectory, outputDir, - context.variant.toIntermediateDir()) + KFiles.joinAndMakeDir(project.directory, project.buildDirectory, outputDir) + + private fun generatedSources(project: Project, context: KobaltContext, outputDir: String) = + KFiles.joinDir(generated(project, context, outputDir), "sources") + private fun generatedStubs(project: Project, context: KobaltContext, outputDir: String) = + KFiles.joinDir(generated(project, context, outputDir), "stubs") + private fun generatedClasses(project: Project, context: KobaltContext, outputDir: String) = + KFiles.joinDir(generated(project, context, outputDir), "classes") + + // ITaskContributor + override fun tasksFor(project: Project, context: KobaltContext): List { + val result = + if (kaptConfig != null) { + listOf( + DynamicTask(this, "runKapt", "Run kapt", AnnotationDefault.GROUP, project, + reverseDependsOn = listOf("compile"), runAfter = listOf("clean"), + closure = {p: Project -> taskRunKapt(p)}), + DynamicTask(this, "compileKapt", "Compile the sources generated by kapt", + AnnotationDefault.GROUP, project, + dependsOn = listOf("runKapt"), reverseDependsOn = listOf("compile"), + closure = {p: Project -> taskCompileKapt(p)}) + ) + } else { + emptyList() + } + return result + } + + fun taskCompileKapt(project: Project) : TaskResult { + var success = true + kaptConfigs[project.name]?.let { config -> + val sourceDirs = listOf( + generatedStubs(project, context, config.outputDir), + generatedSources(project, context, config.outputDir)) + val sourceFiles = KFiles.findSourceFiles(project.directory, sourceDirs, listOf("kt")).toList() + val buildDirectory = File(KFiles.joinDir(project.directory, + generatedClasses(project, context, config.outputDir))) + val flags = listOf() + val cai = CompilerActionInfo(project.directory, allDependencies(project), sourceFiles, listOf(".kt"), + buildDirectory, flags, emptyList(), forceRecompile = true, compilerSeparateProcess = true) + + val cr = compilerUtils.invokeCompiler(project, context, kotlinPlugin.compiler, cai) + success = cr.failedResult == null + } + + return TaskResult(success) + } + + val annotationDependencyId = "org.jetbrains.kotlin:kotlin-annotation-processing:" + + Constants.KOTLIN_COMPILER_VERSION + + fun annotationProcessorDependency() = dependencyManager.create(annotationDependencyId) + + fun aptJarDependencies(project: Project) = aptDependencies[project.name].map { dependencyManager.create(it) } + + fun allDependencies(project: Project): List { + val allDeps = arrayListOf() + allDeps.add(annotationProcessorDependency()) + allDeps.addAll(aptJarDependencies(project)) + + return allDeps + } + + fun taskRunKapt(project: Project) : TaskResult { + var success = true + val flags = arrayListOf() + kaptConfig?.let { config -> + + + val generated = generated(project, context, config.outputDir) + val generatedSources = generatedSources(project, context, config.outputDir).replace("//", "/") + File(generatedSources).mkdirs() + + // + // Tell the Kotlin compiler to use the annotation plug-in + // + val allDeps = allDependencies(project) + flags.add("-Xplugin") + flags.add(annotationProcessorDependency().jarFile.get().absolutePath) + + // Also need tools.jar on the plug-in classpath + jvm.toolsJar?.let { toolsJar -> + flags.add("-Xplugin") + flags.add(toolsJar.absolutePath) + } + + aptJarDependencies(project).forEach { + flags.add("-Xplugin") + flags.add(it.jarFile.get().absolutePath) + } + + // + // Pass options to the annotation plugin + // + flags.add("-P") + fun kaptPluginFlag(flagValue: String) = "plugin:org.jetbrains.kotlin.kapt3:$flagValue" + val kaptPluginFlags = arrayListOf() + val verbose = KobaltLogger.LOG_LEVEL >= 2 + listOf("sources=" + generatedSources, + "classes=" + generatedClasses(project, context, config.outputDir), + "stubs=" + generatedStubs(project, context, config.outputDir), + "verbose=$verbose", + "aptOnly=true").forEach { + kaptPluginFlags.add(kaptPluginFlag(it)) + } + + // + // Dependencies for the annotation plug-in and the generation + // + val dependencies = dependencyManager.calculateDependencies(project, context, + Filters.EXCLUDE_OPTIONAL_FILTER, + listOf(Scope.COMPILE), + allDeps) + dependencies.forEach { + val jarFile = it.jarFile.get().absolutePath + kaptPluginFlags.add(kaptPluginFlag("apclasspath=$jarFile")) + } + + flags.add(kaptPluginFlags.joinToString(",")) + listOf("-language-version", "1.1", "-api-version", "1.1").forEach { + flags.add(it) + } + + val sourceFiles = + KFiles.findSourceFiles(project.directory, project.sourceDirectories, listOf("kt")) + .toList() + generatedSources + val buildDirectory = File(KFiles.joinDir(project.directory, generated)) + val cai = CompilerActionInfo(project.directory, allDeps, sourceFiles, listOf(".kt"), + buildDirectory, flags, emptyList(), forceRecompile = true, compilerSeparateProcess = true) + + context.logger.log(project.name, 2, " " + kaptPluginFlags.joinToString("\n ")) + val cr = compilerUtils.invokeCompiler(project, context, kotlinPlugin.compiler, cai) + success = cr.failedResult == null + } + + return TaskResult(success) + } // ICompilerFlagContributor override fun compilerFlagsFor(project: Project, context: KobaltContext, currentFlags: List, suffixesBeingCompiled: List): List { - if (!suffixesBeingCompiled.contains("java")) return emptyList() - val result = arrayListOf() + // Only run for Java files + if (!suffixesBeingCompiled.contains("java")) return emptyList() + fun addFlags(outputDir: String) { aptDependencies[project.name]?.let { result.add("-s") - result.add(generated(project, context, outputDir)) + result.add(generatedSources(project, context, outputDir)) } } @@ -84,10 +249,6 @@ class AptPlugin @Inject constructor(val dependencyManager: DependencyManager) addFlags(config.outputDir) } - kaptConfigs[project.name]?.let { config -> - addFlags(config.outputDir) - } - context.logger.log(project.name, 2, "New flags from apt: " + result.joinToString(" ")) return result } diff --git a/src/main/kotlin/com/beust/kobalt/plugin/java/JavaCompiler.kt b/src/main/kotlin/com/beust/kobalt/plugin/java/JavaCompiler.kt index 97d7644b..1044adf5 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/java/JavaCompiler.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/java/JavaCompiler.kt @@ -1,7 +1,6 @@ package com.beust.kobalt.plugin.java -import com.beust.kobalt.JavaInfo -import com.beust.kobalt.SystemProperties +import com.beust.kobalt.Jvm import com.beust.kobalt.TaskResult import com.beust.kobalt.api.* import com.beust.kobalt.internal.CompilerUtils @@ -22,7 +21,7 @@ import javax.tools.ToolProvider @Singleton class JavaCompiler @Inject constructor(val jvmCompiler: JvmCompiler, val kobaltLog: ParallelLogger, - val compilerUtils: CompilerUtils) : ICompiler { + val compilerUtils: CompilerUtils, val jvm: Jvm) : ICompiler { fun compilerAction(executable: File) = object : ICompilerAction { override fun compile(project: Project?, info: CompilerActionInfo): TaskResult { val projectName = project?.name @@ -119,7 +118,7 @@ class JavaCompiler @Inject constructor(val jvmCompiler: JvmCompiler, val kobaltL -> it.compilerFlagsFor(project, context, currentFlags, suffixesBeingCompiled) } FlagContributor(it.flagPriority, closure) } - return run(project, context, info, JavaInfo.create(File(SystemProperties.javaBase)).javacExecutable!!, + return run(project, context, info, jvm.javacExecutable!!, compilerUtils.compilerFlags(project, context, info, adapters)) } @@ -130,7 +129,7 @@ class JavaCompiler @Inject constructor(val jvmCompiler: JvmCompiler, val kobaltL -> it.docFlagsFor(project, context, currentFlags, suffixesBeingCompiled) } FlagContributor(it.flagPriority, closure) } - return run(project, context, info, JavaInfo.create(File(SystemProperties.javaBase)).javadocExecutable!!, + return run(project, context, info, jvm.javadocExecutable!!, compilerUtils.compilerFlags(project, context, info, adapters)) } } diff --git a/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinCompiler.kt b/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinCompiler.kt index 5fa6af71..93ad5601 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinCompiler.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinCompiler.kt @@ -35,7 +35,8 @@ class KotlinCompiler @Inject constructor( val settings: KobaltSettings, val jvmCompiler: JvmCompiler, val compilerUtils: CompilerUtils, - val kobaltLog: ParallelLogger) { + val kobaltLog: ParallelLogger, + val jvm: Jvm) { val compilerAction = object: ICompilerAction { override fun compile(project: Project?, info: CompilerActionInfo): TaskResult { @@ -44,14 +45,16 @@ class KotlinCompiler @Inject constructor( var filesToCompile = 0 if (! info.outputDir.path.endsWith("ript.jar")) { // Don't display the message if compiling Build.kt - filesToCompile = - info.sourceFiles.map(::File).map { - if (it.isDirectory) KFiles.findRecursively(it).size else 1 - }.reduce { a, b -> - a + b - } - kobaltLog.log(projectName ?: "", 1, - " Kotlin $version compiling " + Strings.pluralizeAll(filesToCompile, "file")) + if (info.sourceFiles.isNotEmpty()) { + filesToCompile = + info.sourceFiles.map(::File).map { + if (it.isDirectory) KFiles.findRecursively(it).size else 1 + }.reduce { a, b -> + a + b + } + kobaltLog.log(projectName ?: "", 1, + " Kotlin $version compiling " + Strings.pluralizeAll(filesToCompile, "file")) + } } val cp = compilerFirst(info.dependencies.map { it.jarFile.get() }) val infoDir = info.directory @@ -86,7 +89,8 @@ class KotlinCompiler @Inject constructor( // the K2JVMCompiler class directly val actualVersion = kotlinVersion(project) - if (settings.kobaltCompilerSeparateProcess || actualVersion != Constants.KOTLIN_COMPILER_VERSION) { + if (settings.kobaltCompilerSeparateProcess || actualVersion != Constants.KOTLIN_COMPILER_VERSION + || info.compilerSeparateProcess) { return invokeCompilerInSeparateProcess(classpath, info, actualVersion, project) } else { @@ -97,7 +101,7 @@ class KotlinCompiler @Inject constructor( private fun invokeCompilerInSeparateProcess(classpath: String, info: CompilerActionInfo, compilerVersion: String, project: Project?): TaskResult { - val java = JavaInfo.create(File(SystemProperties.javaBase)).javaExecutable + val java = jvm.javaExecutable val compilerClasspath = compilerDep(compilerVersion).jarFile.get().path + File.pathSeparator + compilerEmbeddableDependencies(null, compilerVersion).map { it.jarFile.get().path } @@ -111,20 +115,24 @@ class KotlinCompiler @Inject constructor( val newArgs = listOf( "-classpath", compilerClasspath, K2JVMCompiler::class.java.name, + *info.compilerArgs.toTypedArray(), "-classpath", classpath, "-d", info.outputDir.absolutePath, *xFlagsArray, *info.sourceFiles.toTypedArray()) .filter { ! it.isEmpty() } - log(2, " Invoking separate kotlinc:\n " + java!!.absolutePath + " " + newArgs.joinToString()) + log(2, " Invoking separate kotlinc:\n " + java!!.absolutePath + " " + newArgs.joinToString(" ")) val result = NewRunCommand(RunCommandInfo().apply { command = java.absolutePath args = newArgs directory = File(".") - // The Kotlin compiler issues warnings on stderr :-( - containsErrors = { errors: List -> errors.any { it.contains("rror")} } +// // The Kotlin compiler issues warnings on stderr :-( + useErrorStreamAsErrorIndicator = false +// containsErrors = { +// errors: List -> errors.any { it.contains("rror")} +// } }).invoke() return TaskResult(result == 0, errorMessage = "Error while compiling") } @@ -135,8 +143,9 @@ class KotlinCompiler @Inject constructor( val friends = info.friendPaths.toTypedArray() // Collect the compiler args from kotlinCompiler{} and from settings.xml and parse them - val args2 = (kotlinConfig(project)?.args ?: arrayListOf()) + - (settings.kobaltCompilerFlags?.split(" ") ?: listOf()) + val args2 = + info.compilerArgs + + (settings.kobaltCompilerFlags?.split(" ") ?: listOf()) val args = K2JVMCompilerArguments() val compiler = K2JVMCompiler() compiler.parseArguments(args2.toTypedArray(), args) @@ -185,13 +194,27 @@ class KotlinCompiler @Inject constructor( fun logk(level: Int, message: CharSequence) = kobaltLog.log(projectName, level, message) - logk(2, " Invoking K2JVMCompiler with arguments:" + fun pluginClasspaths(args: K2JVMCompilerArguments) : String { + var result = "" + args.pluginClasspaths?.forEach { + result += " -Xplugin " + it + } + args.pluginOptions?.let { + result += " -P " + result += it.joinToString(",") + } + return result + } + + logk(2, " Invoking K2JVMCompiler with arguments: kotlinc " + if (args.skipMetadataVersionCheck) " -Xskip-metadata-version-check" else "" - + " -moduleName " + args.moduleName + " -d " + args.destination - + " -friendPaths " + args.friendPaths.joinToString(";") + " -classpath " + args.classpath + + pluginClasspaths(args) + " " + sourceFiles.joinToString(" ")) + logk(2, " Additional kotlinc arguments: " + + " -moduleName " + args.moduleName + + " -friendPaths " + args.friendPaths.joinToString(";")) val collector = object : MessageCollector { override fun clear() { throw UnsupportedOperationException("not implemented") @@ -214,7 +237,6 @@ class KotlinCompiler @Inject constructor( message: String, location: CompilerMessageLocation) { if (severity.isError) { "Couldn't compile file: ${dump(location, message)}".let { fullMessage -> - System.err.println(fullMessage) throw KobaltException(fullMessage) } } else if (severity == CompilerMessageSeverity.WARNING && KobaltLogger.LOG_LEVEL >= 2) { @@ -224,28 +246,28 @@ class KotlinCompiler @Inject constructor( } } } - - System.setProperty("kotlin.incremental.compilation", "true") - // TODO: experimental should be removed as soon as it becomes standard - System.setProperty("kotlin.incremental.compilation.experimental", "true") +// +// System.setProperty("kotlin.incremental.compilation", "true") +// // TODO: experimental should be removed as soon as it becomes standard +// System.setProperty("kotlin.incremental.compilation.experimental", "true") val result = - if (cliArgs.noIncrementalKotlin || Kobalt.context?.internalContext?.noIncrementalKotlin ?: false) { - log(2, " Kotlin incremental compilation is disabled") - val duration = benchmarkMillis { - compiler.exec(collector, Services.Builder().build(), args) + if (cliArgs.noIncrementalKotlin || Kobalt.context?.internalContext?.noIncrementalKotlin ?: false) { + log(2, " Kotlin incremental compilation is disabled") + val duration = benchmarkMillis { + compiler.exec(collector, Services.Builder().build(), args) + } + log(1, " Regular compilation time: ${duration.first} ms") + TaskResult(duration.second == ExitCode.OK) + } else { + log(1, " Kotlin incremental compilation is enabled") + val start = System.currentTimeMillis() + val duration = benchmarkMillis { + compileIncrementally(filesToCompile, sourceFiles, outputDir, info, args, collector) + } + log(1, " Incremental compilation time: ${duration.first} ms") + TaskResult() } - log(1, " Regular compilation time: ${duration.first} ms") - TaskResult(duration.second == ExitCode.OK) - } else { - log(1, " Kotlin incremental compilation is enabled") - val start = System.currentTimeMillis() - val duration = benchmarkMillis { - compileIncrementally(filesToCompile, sourceFiles, outputDir, info, args, collector) - } - log(1, " Incremental compilation time: ${duration.first} ms") - TaskResult() - } return result } @@ -370,7 +392,8 @@ class KotlinCompiler @Inject constructor( * JvmCompilerPlugin#createCompilerActionInfo instead */ fun compile(project: Project?, context: KobaltContext?, compileDependencies: List, - otherClasspath: List, sourceFiles: List, outputDir: File, args: List) : TaskResult { + otherClasspath: List, sourceFiles: List, outputDir: File, args: List, + compilerSeparateProcess: Boolean) : TaskResult { val executor = executors.newExecutor("KotlinCompiler", 10) @@ -396,10 +419,12 @@ class KotlinCompiler @Inject constructor( emptyList() } val info = CompilerActionInfo(project?.directory, dependencies, sourceFiles, listOf("kt"), outputDir, args, - friendPaths, context?.internalContext?.forceRecompile ?: false) + friendPaths, context?.internalContext?.forceRecompile ?: false, compilerSeparateProcess) - return jvmCompiler.doCompile(project, context, compilerAction, info, - if (context != null) compilerUtils.sourceCompilerFlags(project, context, info) else emptyList()) + val compilerFlags = + if (context != null) compilerUtils.sourceCompilerFlags(project, context, info) + else emptyList() + return jvmCompiler.doCompile(project, context, compilerAction, info, compilerFlags) } } @@ -410,6 +435,7 @@ class KConfiguration @Inject constructor(val compiler: KotlinCompiler){ var output: File by Delegates.notNull() val args = arrayListOf() var noIncrementalKotlin = false + var compilerSeparateProcess = false fun sourceFiles(s: String) = source.add(s) @@ -424,7 +450,8 @@ class KConfiguration @Inject constructor(val compiler: KotlinCompiler){ fun compile(project: Project? = null, context: KobaltContext? = null) : TaskResult { val saved = context?.internalContext?.noIncrementalKotlin ?: false if (context != null) context.internalContext.noIncrementalKotlin = noIncrementalKotlin - val result = compiler.compile(project, context, dependencies, classpath, source, output, args) + val result = compiler.compile(project, context, dependencies, classpath, source, output, args, + compilerSeparateProcess) if (context != null) context.internalContext.noIncrementalKotlin = saved return result } diff --git a/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinPlugin.kt b/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinPlugin.kt index 220be8a7..3c437628 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinPlugin.kt @@ -83,6 +83,7 @@ class KotlinPlugin @Inject constructor(val executors: KobaltExecutors, val depen sourceFiles(info.sourceFiles) compilerArgs(info.compilerArgs) output = info.outputDir + compilerSeparateProcess = info.compilerSeparateProcess }.compile(project, context) } diff --git a/src/main/resources/kobalt.properties b/src/main/resources/kobalt.properties index f5e39865..4436f17d 100644 --- a/src/main/resources/kobalt.properties +++ b/src/main/resources/kobalt.properties @@ -1 +1 @@ -kobalt.version=1.0.62 +kobalt.version=1.0.72