1
0
Fork 0
mirror of https://github.com/ethauvin/kobalt.git synced 2025-04-26 08:27:12 -07:00

Merge branch 'master' of github.com:cbeust/kobalt

This commit is contained in:
Cedric Beust 2017-04-21 12:17:34 -07:00
commit 49e69d0964
22 changed files with 445 additions and 168 deletions

10
dist/kobaltw vendored
View file

@ -1,7 +1,11 @@
#!/usr/bin/env sh #!/usr/bin/env sh
DIRNAME=`dirname $(readlink -f "$0")` case "$(uname)" in
if [[ "$(uname)" == "CYGWIN"* ]]; then CYGWIN*) DIRNAME=$(cygpath -d "$(dirname "$(readlink -f "$0")")");;
DIRNAME=`cygpath -d "$DIRNAME"` Darwin*) DIRNAME=$(dirname "$(readlink "$0")");;
*) DIRNAME=$(dirname "$(readlink -f "$0")");;
esac
if [ "$DIRNAME" = "." ]; then
DIRNAME="$(dirname "$0")"
fi fi
java -jar "${DIRNAME}/../kobalt/wrapper/kobalt-wrapper.jar" $* java -jar "${DIRNAME}/../kobalt/wrapper/kobalt-wrapper.jar" $*

View file

@ -43,7 +43,6 @@ object Versions {
val junitVintageVersion = "$junit.0-M4" val junitVintageVersion = "$junit.0-M4"
} }
fun mavenResolver(vararg m: String) fun mavenResolver(vararg m: String)
= m.map { "org.apache.maven.resolver:maven-resolver-$it:${Versions.mavenResolver}" } = m.map { "org.apache.maven.resolver:maven-resolver-$it:${Versions.mavenResolver}" }
.toTypedArray() .toTypedArray()
@ -114,7 +113,7 @@ val kobaltPluginApi = project {
"org.slf4j:slf4j-simple:${Versions.slf4j}", "org.slf4j:slf4j-simple:${Versions.slf4j}",
*mavenResolver("api", "spi", "util", "impl", "connector-basic", "transport-http", "transport-file"), *mavenResolver("api", "spi", "util", "impl", "connector-basic", "transport-http", "transport-file"),
"org.apache.maven:maven-aether-provider:3.3.9", "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}", "org.testng:testng:${Versions.testng}",
"commons-io:commons-io:2.5", "commons-io:commons-io:2.5",
"org.junit.platform:junit-platform-surefire-provider:${Versions.junitPlatform}", "org.junit.platform:junit-platform-surefire-provider:${Versions.junitPlatform}",
@ -140,12 +139,8 @@ val kobaltPluginApi = project {
} }
} }
// install {
// libDir = "lib-test"
// }
kotlinCompiler { kotlinCompiler {
args("-nowarn") args("nowarn")
} }
bintray { bintray {
@ -233,7 +228,7 @@ val kobaltApp = project(kobaltPluginApi, wrapper) {
} }
kotlinCompiler { kotlinCompiler {
args("-nowarn") args("nowarn")
} }
bintray { bintray {

View file

@ -1 +1 @@
kobalt.version=1.0.62 kobalt.version=1.0.72

View file

@ -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 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, data class HostConfig(var url: String = "", var name: String = HostConfig.createRepoName(url),
var password: String? = null) { 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 { fun hasAuth() : Boolean {
return (! username.isNullOrBlank()) && (! password.isNullOrBlank()) return (! username.isNullOrBlank()) && (! password.isNullOrBlank())
} }
@ -106,6 +116,7 @@ fun buildFileClasspath(vararg deps: String) {
} }
fun newBuildFileClasspath(vararg deps: String) { fun newBuildFileClasspath(vararg deps: String) {
//FIXME newBuildFileClasspath called twice
deps.forEach { Kobalt.addBuildFileClasspath(it) } deps.forEach { Kobalt.addBuildFileClasspath(it) }
} }
@ -115,7 +126,7 @@ fun authRepos(vararg repos : HostConfig) {
} }
@Directive @Directive
fun authRepo(init: HostConfig.() -> Unit) = HostConfig().apply { init() } fun authRepo(init: HostConfig.() -> Unit) = HostConfig(name = "").apply { init() }
@Directive @Directive
fun glob(g: String) : IFileSpec.GlobSpec = IFileSpec.GlobSpec(g) fun glob(g: String) : IFileSpec.GlobSpec = IFileSpec.GlobSpec(g)

View file

@ -2,8 +2,10 @@ package com.beust.kobalt
class SystemProperties { class SystemProperties {
companion object { companion object {
val javaBase = System.getProperty("java.home") ?: val javaBase =
(System.getenv("JAVA_HOME") ?: throw IllegalArgumentException("JAVA_HOME not defined")) System.getenv("JAVA_HOME")
?: System.getProperty("java.home")
?: throw IllegalArgumentException("JAVA_HOME not defined")
val javaVersion = System.getProperty("java.version") val javaVersion = System.getProperty("java.version")
val homeDir = System.getProperty("user.home") val homeDir = System.getProperty("user.home")
val tmpDir = System.getProperty("java.io.tmpdir") val tmpDir = System.getProperty("java.io.tmpdir")

View file

@ -12,4 +12,5 @@ data class CompilerActionInfo(val directory: String?,
val outputDir: File, val outputDir: File,
val compilerArgs: List<String>, val compilerArgs: List<String>,
val friendPaths: List<String>, val friendPaths: List<String>,
val forceRecompile: Boolean) val forceRecompile: Boolean,
val compilerSeparateProcess: Boolean = false)

View file

@ -5,6 +5,7 @@ import com.beust.kobalt.HostConfig
import com.beust.kobalt.Plugins import com.beust.kobalt.Plugins
import com.beust.kobalt.internal.PluginInfo import com.beust.kobalt.internal.PluginInfo
import com.beust.kobalt.maven.DependencyManager import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.aether.KobaltMavenResolver
import com.google.inject.Guice import com.google.inject.Guice
import com.google.inject.Injector import com.google.inject.Injector
import com.google.inject.Module import com.google.inject.Module
@ -55,6 +56,9 @@ class Kobalt {
// Repos from the build file // Repos from the build file
result.addAll(reposFromBuildFiles) result.addAll(reposFromBuildFiles)
result.forEach {
KobaltMavenResolver.initAuthentication(it)
}
return result.toHashSet() return result.toHashSet()
} }
@ -131,6 +135,7 @@ class Kobalt {
fun cleanUp() { fun cleanUp() {
buildSourceDirs.clear() buildSourceDirs.clear()
buildFileClasspath.clear()
} }
} }
} }

View file

@ -4,6 +4,7 @@ import com.beust.kobalt.*
import com.beust.kobalt.api.* import com.beust.kobalt.api.*
import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.KFiles
import com.google.common.annotations.VisibleForTesting import com.google.common.annotations.VisibleForTesting
import com.google.inject.Inject
import java.io.File import java.io.File
import java.util.* import java.util.*
@ -19,6 +20,9 @@ abstract class GenericTestRunner: ITestRunnerContributor {
open var shortMessage: String? = null open var shortMessage: String? = null
open var longMessage: String? = null open var longMessage: String? = null
@Inject
private lateinit var jvm: Jvm
abstract fun args(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>, abstract fun args(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>,
testConfig: TestConfig) : List<String> testConfig: TestConfig) : List<String>
@ -26,7 +30,7 @@ abstract class GenericTestRunner: ITestRunnerContributor {
open val extraClasspath: List<String> = emptyList() open val extraClasspath: List<String> = emptyList()
open fun filterTestClasses(classes: List<String>) : List<String> = classes open fun filterTestClasses(project: Project, context: KobaltContext, classes: List<String>) : List<String> = classes
override fun run(project: Project, context: KobaltContext, configName: String, override fun run(project: Project, context: KobaltContext, configName: String,
classpath: List<IClasspathDependency>) : TaskResult { classpath: List<IClasspathDependency>) : TaskResult {
@ -65,7 +69,7 @@ abstract class GenericTestRunner: ITestRunnerContributor {
// } // }
context.logger.log(project.name, 2, "Found ${result.size} test classes") 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) val args = args(project, context, classpath, testConfig)
if (args.size > 0) { if (args.size > 0) {
val java = JavaInfo.create(File(SystemProperties.javaBase)).javaExecutable val java = jvm.javaExecutable
val jvmArgs = calculateAllJvmArgs(project, context, testConfig, classpath, val jvmArgs = calculateAllJvmArgs(project, context, testConfig, classpath,
Kobalt.INJECTOR.getInstance (PluginInfo::class.java)) Kobalt.INJECTOR.getInstance (PluginInfo::class.java))
val allArgs = arrayListOf<String>().apply { val allArgs = arrayListOf<String>().apply {

View file

@ -4,6 +4,10 @@ import com.beust.kobalt.TestConfig
import com.beust.kobalt.api.IClasspathDependency import com.beust.kobalt.api.IClasspathDependency
import com.beust.kobalt.api.KobaltContext import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project 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() { open class JUnitRunner() : GenericTestRunner() {
@ -14,5 +18,15 @@ open class JUnitRunner() : GenericTestRunner() {
override fun args(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>, override fun args(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>,
testConfig: TestConfig) = findTestClasses(project, context, testConfig) testConfig: TestConfig) = findTestClasses(project, context, testConfig)
@Inject
lateinit var dependencyManager: DependencyManager
override fun filterTestClasses(project: Project, context: KobaltContext, classes: List<String>) : List<String> {
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) }
}
} }

View file

@ -1,5 +1,8 @@
package com.beust.kobalt.internal 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 * KotlinTestRunner triggers if it finds a dependency on io.kotlintest but other than that, it just
* uses the regular JUnitRunner. * uses the regular JUnitRunner.
@ -12,6 +15,7 @@ class KotlinTestRunner : JUnitRunner() {
* KotlinTestRunner runs tests in the init{} initializer, so ignore all the extra * KotlinTestRunner runs tests in the init{} initializer, so ignore all the extra
* classes generated by the Kotlin compiler. * classes generated by the Kotlin compiler.
*/ */
override fun filterTestClasses(classes: List<String>) = classes.filter { ! it.contains("$") } override fun filterTestClasses(projet: Project, context: KobaltContext, classes: List<String>)
= classes.filter { !it.contains("$") }
} }

View file

@ -1,9 +1,8 @@
package com.beust.kobalt.maven package com.beust.kobalt.maven
import com.beust.kobalt.HostConfig 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.maven.dependency.FileDependency
import com.beust.kobalt.misc.LocalProperties
import java.io.* import java.io.*
import java.net.HttpURLConnection import java.net.HttpURLConnection
import java.net.URL import java.net.URL
@ -21,27 +20,7 @@ class Kurl(val hostInfo: HostConfig) {
} }
init { init {
// See if the URL needs to be authenticated. Look in local.properties for keys KobaltMavenResolver.initAuthentication(hostInfo)
// of the format authUrl.<host>.user=xxx and authUrl.<host>.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")
}
} }
override fun toString() = hostInfo.toString() override fun toString() = hostInfo.toString()

View file

@ -2,11 +2,14 @@ package com.beust.kobalt.maven.aether
import com.beust.kobalt.Args import com.beust.kobalt.Args
import com.beust.kobalt.HostConfig import com.beust.kobalt.HostConfig
import com.beust.kobalt.KobaltException
import com.beust.kobalt.api.Kobalt import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.internal.KobaltSettings import com.beust.kobalt.internal.KobaltSettings
import com.beust.kobalt.internal.getProxy import com.beust.kobalt.internal.getProxy
import com.beust.kobalt.maven.Kurl
import com.beust.kobalt.maven.LocalRepo import com.beust.kobalt.maven.LocalRepo
import com.beust.kobalt.maven.MavenId import com.beust.kobalt.maven.MavenId
import com.beust.kobalt.misc.LocalProperties
import com.google.common.eventbus.EventBus import com.google.common.eventbus.EventBus
import com.google.inject.Inject import com.google.inject.Inject
import org.eclipse.aether.artifact.Artifact 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.DependencyResult
import org.eclipse.aether.resolution.VersionRangeRequest import org.eclipse.aether.resolution.VersionRangeRequest
import org.eclipse.aether.resolution.VersionRangeResult import org.eclipse.aether.resolution.VersionRangeResult
import org.eclipse.aether.util.repository.AuthenticationBuilder
import java.util.* import java.util.*
class KobaltMavenResolver @Inject constructor(val settings: KobaltSettings, 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) MavenId.toId(it.groupId, it.artifactId, it.extension, it.classifier, it.version)
} }
fun isRangeVersion(id: String) = id.contains(",") 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.<host>.user=xxx and authUrl.<host>.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, 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 system = Booter.newRepositorySystem()
private val session = Booter.newRepositorySystemSession(system, localRepo.localRepo, settings, eventBus) private val session = Booter.newRepositorySystemSession(system, localRepo.localRepo, settings, eventBus)
private fun createRepo(hostConfig: HostConfig) = private fun createRepo(hostConfig: HostConfig) : RemoteRepository {
RemoteRepository.Builder(hostConfig.name, "default", hostConfig.url).build() 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<RemoteRepository> private val kobaltRepositories: List<RemoteRepository>
get() = Kobalt.repos.map { get() = Kobalt.repos.map {

View file

@ -79,9 +79,11 @@ open class NewRunCommand(val info: RunCommandInfo) {
// Run the command and collect the return code and streams // Run the command and collect the return code and streams
val returnCode = process.waitFor(30, TimeUnit.SECONDS) val returnCode = process.waitFor(30, TimeUnit.SECONDS)
val input = if (process.inputStream.available() > 0) fromStream(process.inputStream) val input =
if (process.inputStream.available() > 0) fromStream(process.inputStream)
else listOf() else listOf()
val error = if (process.errorStream.available() > 0) fromStream(process.errorStream) val error =
if (process.errorStream.available() > 0) fromStream(process.errorStream)
else listOf() else listOf()
// Check to see if the command succeeded // Check to see if the command succeeded
@ -105,10 +107,10 @@ open class NewRunCommand(val info: RunCommandInfo) {
open protected fun isSuccess(isSuccess: Boolean, input: List<String>, error: List<String>) : Boolean { open protected fun isSuccess(isSuccess: Boolean, input: List<String>, error: List<String>) : Boolean {
var hasErrors = ! isSuccess var hasErrors = ! isSuccess
if (info.useErrorStreamAsErrorIndicator && ! hasErrors) { if (info.useErrorStreamAsErrorIndicator && ! hasErrors) {
hasErrors = hasErrors || error.size > 0 hasErrors = hasErrors || error.isNotEmpty()
} }
if (info.useInputStreamAsErrorIndicator && ! hasErrors) { if (info.useInputStreamAsErrorIndicator && ! hasErrors) {
hasErrors = hasErrors || input.size > 0 hasErrors = hasErrors || input.isNotEmpty()
} }
return ! hasErrors return ! hasErrors

View file

@ -3,6 +3,7 @@ package com.beust.kobalt
import com.beust.jcommander.JCommander import com.beust.jcommander.JCommander
import com.beust.kobalt.api.Kobalt import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.api.PluginTask import com.beust.kobalt.api.PluginTask
import com.beust.kobalt.api.Project
import com.beust.kobalt.app.ProjectFinder import com.beust.kobalt.app.ProjectFinder
import com.beust.kobalt.app.ProjectGenerator import com.beust.kobalt.app.ProjectGenerator
import com.beust.kobalt.app.Templates 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 p = if (args.buildFile != null) File(args.buildFile) else File(".")
// val buildFile = BuildFile(Paths.get(p.absolutePath), p.name) // val buildFile = BuildFile(Paths.get(p.absolutePath), p.name)
val buildSources = if (p.isDirectory) BuildSources(p.absoluteFile) else SingleFileBuildSources(p) 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<Project>()
}
fun runIfSuccessfulBuild(buildError: Throwable?, action: () -> Unit) {
buildError?.let { throw it }
action()
}
// Modify `args` with options found in buildScript { kobaltOptions(...) }, if any // Modify `args` with options found in buildScript { kobaltOptions(...) }, if any
addOptionsFromBuild(args, Kobalt.optionsFromBuild) addOptionsFromBuild(args, Kobalt.optionsFromBuild)
@ -77,11 +94,13 @@ class Options @Inject constructor(
}), }),
Option( { -> args.projectInfo }, { Option( { -> args.projectInfo }, {
// --projectInfo // --projectInfo
runIfSuccessfulBuild(buildError) {
allProjects.forEach { allProjects.forEach {
it.compileDependencies.filter { it.isMaven }.forEach { it.compileDependencies.filter { it.isMaven }.forEach {
resolveDependency.run(it.id) resolveDependency.run(it.id)
} }
} }
}
}), }),
Option( { args.dependency != null }, { Option( { args.dependency != null }, {
// --resolve // --resolve
@ -89,11 +108,15 @@ class Options @Inject constructor(
}), }),
Option( { args.tasks }, { Option( { args.tasks }, {
// --tasks // --tasks
runIfSuccessfulBuild(buildError) {
displayTasks() displayTasks()
}
}), }),
Option( { args.checkVersions }, { Option( { args.checkVersions }, {
// --checkVersions // --checkVersions
runIfSuccessfulBuild(buildError) {
checkVersions.run(allProjects) checkVersions.run(allProjects)
}
}), }),
Option( { args.download }, { Option( { args.download }, {
// --download // --download
@ -121,6 +144,7 @@ class Options @Inject constructor(
if (! buildSources.exists()) { if (! buildSources.exists()) {
throw KobaltException("Could not find build file: " + buildSources) throw KobaltException("Could not find build file: " + buildSources)
} }
runIfSuccessfulBuild(buildError) {
val runTargetResult = taskManager.runTargets(args.targets, allProjects) val runTargetResult = taskManager.runTargets(args.targets, allProjects)
if (result == 0) { if (result == 0) {
result = if (runTargetResult.taskResult.success) 0 else 1 result = if (runTargetResult.taskResult.success) 0 else 1
@ -134,6 +158,7 @@ class Options @Inject constructor(
it.generateReport(Kobalt.context!!) it.generateReport(Kobalt.context!!)
} }
} }
}
return result return result
} }

View file

@ -1,6 +1,8 @@
package com.beust.kobalt.app package com.beust.kobalt.app
import com.beust.kobalt.Args 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.app.remote.KobaltServer
import com.beust.kobalt.internal.IncrementalManager import com.beust.kobalt.internal.IncrementalManager
import com.beust.kobalt.internal.KobaltSettings import com.beust.kobalt.internal.KobaltSettings
@ -17,6 +19,7 @@ import com.google.inject.Provider
import com.google.inject.Singleton import com.google.inject.Singleton
import com.google.inject.TypeLiteral import com.google.inject.TypeLiteral
import com.google.inject.assistedinject.FactoryModuleBuilder import com.google.inject.assistedinject.FactoryModuleBuilder
import java.io.File
import java.util.concurrent.ExecutorService import java.util.concurrent.ExecutorService
open class MainModule(val args: Args, val settings: KobaltSettings) : AbstractModule() { 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> { bind(Args::class.java).toProvider(Provider<Args> {
args args
}) })
EventBus().let { eventBus -> bind(EventBus::class.java).toInstance(EventBus())
bind(EventBus::class.java).toInstance(eventBus)
}
bind(PluginInfo::class.java).toProvider(Provider<PluginInfo> { bind(PluginInfo::class.java).toProvider(Provider<PluginInfo> {
PluginInfo.readKobaltPluginXml() PluginInfo.readKobaltPluginXml()
}).`in`(Singleton::class.java) }).`in`(Singleton::class.java)
bind(KobaltSettings::class.java).toProvider(Provider<KobaltSettings> { bind(KobaltSettings::class.java).toProvider(Provider<KobaltSettings> {
settings settings
}).`in`(Singleton::class.java) }).`in`(Singleton::class.java)
bind(Jvm::class.java).toInstance(JavaInfo.create(File(com.beust.kobalt.SystemProperties.javaBase)))
// bindListener(Matchers.any(), object: TypeListener { // bindListener(Matchers.any(), object: TypeListener {
// override fun <I> hear(typeLiteral: TypeLiteral<I>?, typeEncounter: TypeEncounter<I>?) { // override fun <I> hear(typeLiteral: TypeLiteral<I>?, typeEncounter: TypeEncounter<I>?) {

View file

@ -2,6 +2,7 @@ package com.beust.kobalt.app.remote
import com.beust.kobalt.Args import com.beust.kobalt.Args
import com.beust.kobalt.api.IClasspathDependency import com.beust.kobalt.api.IClasspathDependency
import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
import com.beust.kobalt.app.BuildFileCompiler import com.beust.kobalt.app.BuildFileCompiler
import com.beust.kobalt.internal.DynamicGraph import com.beust.kobalt.internal.DynamicGraph
@ -29,7 +30,7 @@ class RemoteDependencyData @Inject constructor(val executors: KobaltExecutors, v
val taskManager: TaskManager) { val taskManager: TaskManager) {
fun dependenciesDataFor(buildSources: BuildSources, args: Args, fun dependenciesDataFor(buildSources: BuildSources, args: Args,
findProjectResult: BuildFileCompiler.FindProjectResult, projectResult: BuildFileCompiler.FindProjectResult,
progressListener: IProgressListener? = null, progressListener: IProgressListener? = null,
useGraph : Boolean = false): GetDependenciesData { useGraph : Boolean = false): GetDependenciesData {
val projectDatas = arrayListOf<ProjectData>() val projectDatas = arrayListOf<ProjectData>()
@ -42,9 +43,7 @@ class RemoteDependencyData @Inject constructor(val executors: KobaltExecutors, v
fun allDeps(l: List<IClasspathDependency>, name: String) = dependencyManager.transitiveClosure(l, fun allDeps(l: List<IClasspathDependency>, name: String) = dependencyManager.transitiveClosure(l,
requiredBy = name) requiredBy = name)
// val buildFile = BuildFile(Paths.get(buildFilePath), "GetDependenciesCommand") val buildFileDependencies = Kobalt.buildFileClasspath.map {toDependencyData(it, "compile")}
val buildFileCompiler = buildFileCompilerFactory.create(buildSources, pluginInfo)
val projectResult = buildFileCompiler.compileBuildFiles(args)
val pluginDependencies = projectResult.pluginUrls.map { File(it.toURI()) }.map { val pluginDependencies = projectResult.pluginUrls.map { File(it.toURI()) }.map {
DependencyData(it.name, "compile", it.absolutePath) 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, return GetDependenciesData(projectDatas, allTasks, pluginDependencies, buildFileDependencies,
projectResult.taskResult.errorMessage) projectResult.buildContentRoots, projectResult.taskResult.errorMessage)
} }
///// /////
@ -202,6 +201,7 @@ class RemoteDependencyData @Inject constructor(val executors: KobaltExecutors, v
class GetDependenciesData(val projects: List<ProjectData> = emptyList(), class GetDependenciesData(val projects: List<ProjectData> = emptyList(),
val allTasks: Collection<TaskData> = emptySet(), val allTasks: Collection<TaskData> = emptySet(),
val pluginDependencies: List<DependencyData> = emptyList(), val pluginDependencies: List<DependencyData> = emptyList(),
val buildFileDependencies: List<DependencyData> = emptyList(),
val buildContentRoots: List<String> = emptyList(), val buildContentRoots: List<String> = emptyList(),
val errorMessage: String?) { val errorMessage: String?) {
companion object { companion object {

View file

@ -1,6 +1,9 @@
package com.beust.kobalt.plugin.application 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.*
import com.beust.kobalt.api.annotation.Directive import com.beust.kobalt.api.annotation.Directive
import com.beust.kobalt.api.annotation.Task import com.beust.kobalt.api.annotation.Task
@ -42,7 +45,7 @@ fun Project.application(init: ApplicationConfig.() -> Unit): ApplicationConfig {
@Singleton @Singleton
class ApplicationPlugin @Inject constructor(val configActor: ConfigActor<ApplicationConfig>, class ApplicationPlugin @Inject constructor(val configActor: ConfigActor<ApplicationConfig>,
val executors: KobaltExecutors, val nativeManager: NativeManager, 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<ApplicationConfig> by configActor { : BasePlugin(), IRunnerContributor, ITaskContributor, IConfigActor<ApplicationConfig> by configActor {
companion object { companion object {
@ -111,7 +114,7 @@ class ApplicationPlugin @Inject constructor(val configActor: ConfigActor<Applica
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val packages = project.projectProperties.get(PackagingPlugin.PACKAGES) as List<PackageConfig> val packages = project.projectProperties.get(PackagingPlugin.PACKAGES) as List<PackageConfig>
val allDeps = arrayListOf(jarName) val allDeps = arrayListOf(jarName)
val java = JavaInfo.create(File(SystemProperties.javaBase)).javaExecutable!! val java = jvm.javaExecutable!!
if (! isFatJar(packages, jarName)) { if (! isFatJar(packages, jarName)) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
// If the jar file is not fat, we need to add the transitive closure of all dependencies // If the jar file is not fat, we need to add the transitive closure of all dependencies

View file

@ -1,10 +1,20 @@
package com.beust.kobalt.plugin.apt 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.*
import com.beust.kobalt.api.annotation.AnnotationDefault
import com.beust.kobalt.api.annotation.Directive import com.beust.kobalt.api.annotation.Directive
import com.beust.kobalt.internal.CompilerUtils
import com.beust.kobalt.maven.DependencyManager 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.KFiles
import com.beust.kobalt.misc.KobaltLogger
import com.beust.kobalt.misc.warn import com.beust.kobalt.misc.warn
import com.beust.kobalt.plugin.kotlin.KotlinPlugin
import com.google.common.collect.ArrayListMultimap import com.google.common.collect.ArrayListMultimap
import com.google.inject.Inject import com.google.inject.Inject
import java.io.File import java.io.File
@ -12,21 +22,62 @@ import java.util.*
import javax.inject.Singleton 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 * 1) A new apt directive inside a dependency{} block (similar to compile()) that declares where
* the annotation processor is found * the annotation processor is found
* 2) An apt{} configuration on Project that lets the user configure how the annotation is performed * 2) An apt{} configuration on Project that lets the user configure how the annotation is performed
* (outputDir, etc...). * (outputDir, etc...).
*/ */
@Singleton @Singleton
class AptPlugin @Inject constructor(val dependencyManager: DependencyManager) class AptPlugin @Inject constructor(val dependencyManager: DependencyManager, val kotlinPlugin: KotlinPlugin,
: BasePlugin(), ICompilerFlagContributor, ISourceDirectoryContributor { 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<IClasspathDependency> {
val result = arrayListOf<IClasspathDependency>()
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 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<File> { override fun sourceDirectoriesFor(project: Project, context: KobaltContext): List<File> {
val result = arrayListOf<File>() val result = arrayListOf<File>()
aptConfigs[project.name]?.let { config -> aptConfigs[project.name]?.let { config ->
@ -40,43 +91,157 @@ class AptPlugin @Inject constructor(val dependencyManager: DependencyManager)
return result 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) = private fun generated(project: Project, context: KobaltContext, outputDir: String) =
KFiles.joinAndMakeDir(project.directory, project.buildDirectory, outputDir, KFiles.joinAndMakeDir(project.directory, project.buildDirectory, outputDir)
context.variant.toIntermediateDir())
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<DynamicTask> {
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<String>()
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<IClasspathDependency> {
val allDeps = arrayListOf<IClasspathDependency>()
allDeps.add(annotationProcessorDependency())
allDeps.addAll(aptJarDependencies(project))
return allDeps
}
fun taskRunKapt(project: Project) : TaskResult {
var success = true
val flags = arrayListOf<String>()
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<String>()
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 // ICompilerFlagContributor
override fun compilerFlagsFor(project: Project, context: KobaltContext, currentFlags: List<String>, override fun compilerFlagsFor(project: Project, context: KobaltContext, currentFlags: List<String>,
suffixesBeingCompiled: List<String>): List<String> { suffixesBeingCompiled: List<String>): List<String> {
if (!suffixesBeingCompiled.contains("java")) return emptyList()
val result = arrayListOf<String>() val result = arrayListOf<String>()
// Only run for Java files
if (!suffixesBeingCompiled.contains("java")) return emptyList()
fun addFlags(outputDir: String) { fun addFlags(outputDir: String) {
aptDependencies[project.name]?.let { aptDependencies[project.name]?.let {
result.add("-s") 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) addFlags(config.outputDir)
} }
kaptConfigs[project.name]?.let { config ->
addFlags(config.outputDir)
}
context.logger.log(project.name, 2, "New flags from apt: " + result.joinToString(" ")) context.logger.log(project.name, 2, "New flags from apt: " + result.joinToString(" "))
return result return result
} }

View file

@ -1,7 +1,6 @@
package com.beust.kobalt.plugin.java package com.beust.kobalt.plugin.java
import com.beust.kobalt.JavaInfo import com.beust.kobalt.Jvm
import com.beust.kobalt.SystemProperties
import com.beust.kobalt.TaskResult import com.beust.kobalt.TaskResult
import com.beust.kobalt.api.* import com.beust.kobalt.api.*
import com.beust.kobalt.internal.CompilerUtils import com.beust.kobalt.internal.CompilerUtils
@ -22,7 +21,7 @@ import javax.tools.ToolProvider
@Singleton @Singleton
class JavaCompiler @Inject constructor(val jvmCompiler: JvmCompiler, val kobaltLog: ParallelLogger, 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 { fun compilerAction(executable: File) = object : ICompilerAction {
override fun compile(project: Project?, info: CompilerActionInfo): TaskResult { override fun compile(project: Project?, info: CompilerActionInfo): TaskResult {
val projectName = project?.name val projectName = project?.name
@ -119,7 +118,7 @@ class JavaCompiler @Inject constructor(val jvmCompiler: JvmCompiler, val kobaltL
-> it.compilerFlagsFor(project, context, currentFlags, suffixesBeingCompiled) } -> it.compilerFlagsFor(project, context, currentFlags, suffixesBeingCompiled) }
FlagContributor(it.flagPriority, closure) 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)) 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) } -> it.docFlagsFor(project, context, currentFlags, suffixesBeingCompiled) }
FlagContributor(it.flagPriority, closure) 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)) compilerUtils.compilerFlags(project, context, info, adapters))
} }
} }

View file

@ -35,7 +35,8 @@ class KotlinCompiler @Inject constructor(
val settings: KobaltSettings, val settings: KobaltSettings,
val jvmCompiler: JvmCompiler, val jvmCompiler: JvmCompiler,
val compilerUtils: CompilerUtils, val compilerUtils: CompilerUtils,
val kobaltLog: ParallelLogger) { val kobaltLog: ParallelLogger,
val jvm: Jvm) {
val compilerAction = object: ICompilerAction { val compilerAction = object: ICompilerAction {
override fun compile(project: Project?, info: CompilerActionInfo): TaskResult { override fun compile(project: Project?, info: CompilerActionInfo): TaskResult {
@ -44,6 +45,7 @@ class KotlinCompiler @Inject constructor(
var filesToCompile = 0 var filesToCompile = 0
if (! info.outputDir.path.endsWith("ript.jar")) { if (! info.outputDir.path.endsWith("ript.jar")) {
// Don't display the message if compiling Build.kt // Don't display the message if compiling Build.kt
if (info.sourceFiles.isNotEmpty()) {
filesToCompile = filesToCompile =
info.sourceFiles.map(::File).map { info.sourceFiles.map(::File).map {
if (it.isDirectory) KFiles.findRecursively(it).size else 1 if (it.isDirectory) KFiles.findRecursively(it).size else 1
@ -53,6 +55,7 @@ class KotlinCompiler @Inject constructor(
kobaltLog.log(projectName ?: "", 1, kobaltLog.log(projectName ?: "", 1,
" Kotlin $version compiling " + Strings.pluralizeAll(filesToCompile, "file")) " Kotlin $version compiling " + Strings.pluralizeAll(filesToCompile, "file"))
} }
}
val cp = compilerFirst(info.dependencies.map { it.jarFile.get() }) val cp = compilerFirst(info.dependencies.map { it.jarFile.get() })
val infoDir = info.directory val infoDir = info.directory
val outputDir = val outputDir =
@ -86,7 +89,8 @@ class KotlinCompiler @Inject constructor(
// the K2JVMCompiler class directly // the K2JVMCompiler class directly
val actualVersion = kotlinVersion(project) 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) return invokeCompilerInSeparateProcess(classpath, info, actualVersion, project)
} else { } else {
@ -97,7 +101,7 @@ class KotlinCompiler @Inject constructor(
private fun invokeCompilerInSeparateProcess(classpath: String, info: CompilerActionInfo, private fun invokeCompilerInSeparateProcess(classpath: String, info: CompilerActionInfo,
compilerVersion: String, project: Project?): TaskResult { 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 + val compilerClasspath = compilerDep(compilerVersion).jarFile.get().path + File.pathSeparator +
compilerEmbeddableDependencies(null, compilerVersion).map { it.jarFile.get().path } compilerEmbeddableDependencies(null, compilerVersion).map { it.jarFile.get().path }
@ -111,20 +115,24 @@ class KotlinCompiler @Inject constructor(
val newArgs = listOf( val newArgs = listOf(
"-classpath", compilerClasspath, "-classpath", compilerClasspath,
K2JVMCompiler::class.java.name, K2JVMCompiler::class.java.name,
*info.compilerArgs.toTypedArray(),
"-classpath", classpath, "-classpath", classpath,
"-d", info.outputDir.absolutePath, "-d", info.outputDir.absolutePath,
*xFlagsArray, *xFlagsArray,
*info.sourceFiles.toTypedArray()) *info.sourceFiles.toTypedArray())
.filter { ! it.isEmpty() } .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 { val result = NewRunCommand(RunCommandInfo().apply {
command = java.absolutePath command = java.absolutePath
args = newArgs args = newArgs
directory = File(".") directory = File(".")
// The Kotlin compiler issues warnings on stderr :-( // // The Kotlin compiler issues warnings on stderr :-(
containsErrors = { errors: List<String> -> errors.any { it.contains("rror")} } useErrorStreamAsErrorIndicator = false
// containsErrors = {
// errors: List<String> -> errors.any { it.contains("rror")}
// }
}).invoke() }).invoke()
return TaskResult(result == 0, errorMessage = "Error while compiling") return TaskResult(result == 0, errorMessage = "Error while compiling")
} }
@ -135,7 +143,8 @@ class KotlinCompiler @Inject constructor(
val friends = info.friendPaths.toTypedArray() val friends = info.friendPaths.toTypedArray()
// Collect the compiler args from kotlinCompiler{} and from settings.xml and parse them // Collect the compiler args from kotlinCompiler{} and from settings.xml and parse them
val args2 = (kotlinConfig(project)?.args ?: arrayListOf<String>()) + val args2 =
info.compilerArgs +
(settings.kobaltCompilerFlags?.split(" ") ?: listOf<String>()) (settings.kobaltCompilerFlags?.split(" ") ?: listOf<String>())
val args = K2JVMCompilerArguments() val args = K2JVMCompilerArguments()
val compiler = K2JVMCompiler() val compiler = K2JVMCompiler()
@ -185,13 +194,27 @@ class KotlinCompiler @Inject constructor(
fun logk(level: Int, message: CharSequence) = kobaltLog.log(projectName, level, message) 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 "" + if (args.skipMetadataVersionCheck) " -Xskip-metadata-version-check" else ""
+ " -moduleName " + args.moduleName
+ " -d " + args.destination + " -d " + args.destination
+ " -friendPaths " + args.friendPaths.joinToString(";")
+ " -classpath " + args.classpath + " -classpath " + args.classpath
+ pluginClasspaths(args)
+ " " + sourceFiles.joinToString(" ")) + " " + sourceFiles.joinToString(" "))
logk(2, " Additional kotlinc arguments: "
+ " -moduleName " + args.moduleName
+ " -friendPaths " + args.friendPaths.joinToString(";"))
val collector = object : MessageCollector { val collector = object : MessageCollector {
override fun clear() { override fun clear() {
throw UnsupportedOperationException("not implemented") throw UnsupportedOperationException("not implemented")
@ -214,7 +237,6 @@ class KotlinCompiler @Inject constructor(
message: String, location: CompilerMessageLocation) { message: String, location: CompilerMessageLocation) {
if (severity.isError) { if (severity.isError) {
"Couldn't compile file: ${dump(location, message)}".let { fullMessage -> "Couldn't compile file: ${dump(location, message)}".let { fullMessage ->
System.err.println(fullMessage)
throw KobaltException(fullMessage) throw KobaltException(fullMessage)
} }
} else if (severity == CompilerMessageSeverity.WARNING && KobaltLogger.LOG_LEVEL >= 2) { } else if (severity == CompilerMessageSeverity.WARNING && KobaltLogger.LOG_LEVEL >= 2) {
@ -224,10 +246,10 @@ class KotlinCompiler @Inject constructor(
} }
} }
} }
//
System.setProperty("kotlin.incremental.compilation", "true") // System.setProperty("kotlin.incremental.compilation", "true")
// TODO: experimental should be removed as soon as it becomes standard // // TODO: experimental should be removed as soon as it becomes standard
System.setProperty("kotlin.incremental.compilation.experimental", "true") // System.setProperty("kotlin.incremental.compilation.experimental", "true")
val result = val result =
if (cliArgs.noIncrementalKotlin || Kobalt.context?.internalContext?.noIncrementalKotlin ?: false) { if (cliArgs.noIncrementalKotlin || Kobalt.context?.internalContext?.noIncrementalKotlin ?: false) {
@ -370,7 +392,8 @@ class KotlinCompiler @Inject constructor(
* JvmCompilerPlugin#createCompilerActionInfo instead * JvmCompilerPlugin#createCompilerActionInfo instead
*/ */
fun compile(project: Project?, context: KobaltContext?, compileDependencies: List<IClasspathDependency>, fun compile(project: Project?, context: KobaltContext?, compileDependencies: List<IClasspathDependency>,
otherClasspath: List<String>, sourceFiles: List<String>, outputDir: File, args: List<String>) : TaskResult { otherClasspath: List<String>, sourceFiles: List<String>, outputDir: File, args: List<String>,
compilerSeparateProcess: Boolean) : TaskResult {
val executor = executors.newExecutor("KotlinCompiler", 10) val executor = executors.newExecutor("KotlinCompiler", 10)
@ -396,10 +419,12 @@ class KotlinCompiler @Inject constructor(
emptyList<String>() emptyList<String>()
} }
val info = CompilerActionInfo(project?.directory, dependencies, sourceFiles, listOf("kt"), outputDir, args, 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, val compilerFlags =
if (context != null) compilerUtils.sourceCompilerFlags(project, context, info) else emptyList()) 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() var output: File by Delegates.notNull()
val args = arrayListOf<String>() val args = arrayListOf<String>()
var noIncrementalKotlin = false var noIncrementalKotlin = false
var compilerSeparateProcess = false
fun sourceFiles(s: String) = source.add(s) 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 { fun compile(project: Project? = null, context: KobaltContext? = null) : TaskResult {
val saved = context?.internalContext?.noIncrementalKotlin ?: false val saved = context?.internalContext?.noIncrementalKotlin ?: false
if (context != null) context.internalContext.noIncrementalKotlin = noIncrementalKotlin 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 if (context != null) context.internalContext.noIncrementalKotlin = saved
return result return result
} }

View file

@ -83,6 +83,7 @@ class KotlinPlugin @Inject constructor(val executors: KobaltExecutors, val depen
sourceFiles(info.sourceFiles) sourceFiles(info.sourceFiles)
compilerArgs(info.compilerArgs) compilerArgs(info.compilerArgs)
output = info.outputDir output = info.outputDir
compilerSeparateProcess = info.compilerSeparateProcess
}.compile(project, context) }.compile(project, context)
} }

View file

@ -1 +1 @@
kobalt.version=1.0.62 kobalt.version=1.0.72