gradle-plugin: Allow 'manual' dependency downloading

This patch adds an ability to download native dependencies
(clang, sysroots etc) during execution of the `downloadKonanCompiler`
task. The feature can by enabled by setting the
`downloadDependencies` property of the `downloadKonanCompiler` task
to true. Targets for these dependencies may be specified as a string
list using `targets` property of the `downloadKonanCompiler` task.
This commit is contained in:
Ilya Matveev
2017-08-30 18:11:46 +07:00
committed by ilmat192
parent 68d0c9987b
commit 7ec167b5ca
6 changed files with 107 additions and 63 deletions
+5
View File
@@ -14,10 +14,15 @@ konanArtifacts {
}
task compileCpp(type: Exec) {
dependsOn 'downloadKonanCompiler'
workingDir project.getProjectDir()
commandLine './buildCpp.sh'
}
compileKonanMessageChannel {
dependsOn 'compileCpp'
}
downloadKonanCompiler {
downloadDependencies = true
}
@@ -29,13 +29,6 @@ import java.io.File
*/
open class KonanCompileTask: KonanTargetableTask() {
companion object {
const val COMPILER_MAIN = "org.jetbrains.kotlin.cli.bc.K2NativeKt"
}
val COMPILER_JVM_ARGS: List<String>
@Internal get() = listOf("-Dkonan.home=${project.konanHome}", "-Djava.library.path=${project.konanHome}/konan/nativelib")
// Output artifact --------------------------------------------------------
internal lateinit var artifactName: String
@@ -146,14 +139,7 @@ open class KonanCompileTask: KonanTargetableTask() {
if (dumpParameters) dumpProperties(this@KonanCompileTask)
// TODO: Use compiler service.
project.javaexec {
with(it) {
main = COMPILER_MAIN
classpath = project.konanCompilerClasspath
jvmArgs(COMPILER_JVM_ARGS)
args(buildArgs().apply { logger.info("Compiler args: ${this.joinToString(separator = " ")}") })
}
}
KonanCompilerRunner(project).run(buildArgs())
}
}
@@ -18,9 +18,10 @@ package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.DefaultTask
import org.gradle.api.GradleScriptException
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.*
import org.jetbrains.kotlin.konan.util.DependencyProcessor
import java.io.File
import java.io.IOException
open class KonanCompilerDownloadTask : DefaultTask() {
@@ -30,32 +31,39 @@ open class KonanCompilerDownloadTask : DefaultTask() {
internal val KONAN_PARENT_DIR = "${System.getProperty("user.home")}/.konan"
}
/**
* A list of tasks used to download dependencies. If empty then dependencies will be downloaded for the host.
* Isn't used if [downloadDependencies] is false.
*/
@Internal var targets: MutableCollection<String> = mutableSetOf<String>()
/** If true the task will also download dependencies for targets specified by [targets] property. */
@Internal var downloadDependencies: Boolean = false
@TaskAction
fun downloadAndExtract() {
if (!project.hasProperty(KonanPlugin.ProjectProperty.DOWNLOAD_COMPILER)) {
val konanHome = project.getProperty(KonanPlugin.ProjectProperty.KONAN_HOME)
logger.info("Use a user-defined compiler path: $konanHome")
val interopClasspath = project.konanInteropClasspath
if (interopClasspath.isEmpty) {
throw IllegalStateException("Stub generator classpath is empty: ${interopClasspath.dir}\n" +
"Probably the 'konan.home' project property contains an incorrect path. Please change it to the compiler root directory and rerun the build.")
} else {
try {
val konanCompiler = project.konanCompilerName()
logger.info("Downloading Kotlin/Native compiler from $DOWNLOAD_URL/$konanCompiler into $KONAN_PARENT_DIR")
DependencyProcessor(File(KONAN_PARENT_DIR), DOWNLOAD_URL, listOf(konanCompiler)).run()
} catch (e: IOException) {
throw GradleScriptException("Cannot download Kotlin/Native compiler", e)
}
val compilerClasspath = project.konanCompilerClasspath
if (compilerClasspath.isEmpty) {
throw IllegalStateException("Kotlin/Native compiler classpath is empty: ${compilerClasspath.dir}\n" +
"Probably the 'konan.home' project property contains an incorrect path. Please change it to the compiler root directory and rerun the build.")
}
return
}
try {
val konanCompiler = project.konanCompilerName()
logger.info("Downloading Kotlin/Native compiler from $DOWNLOAD_URL/$konanCompiler into $KONAN_PARENT_DIR")
DependencyProcessor(File(KONAN_PARENT_DIR), DOWNLOAD_URL, listOf(konanCompiler)).run()
} catch (e: RuntimeException) {
throw GradleScriptException("Cannot download Kotlin/Native compiler", e)
// Download dependencies if a user said so.
if (downloadDependencies) {
val runner = KonanCompilerRunner(project)
if (targets.isEmpty()) {
// Download for the host.
runner.run("--check_dependencies")
} else {
targets.forEach { runner.run("--check_dependencies", "-target", it) }
}
}
}
}
@@ -29,19 +29,12 @@ import java.io.File
*/
open class KonanInteropTask: KonanTargetableTask() {
internal companion object {
const val INTEROP_MAIN = "org.jetbrains.kotlin.native.interop.gen.jvm.MainKt"
}
internal fun init(libName: String) {
dependsOn(project.konanCompilerDownloadTask)
this.libName = libName
this.defFile = project.konanDefaultDefFile(libName)
}
internal val INTEROP_JVM_ARGS: List<String>
@Internal get() = listOf("-Dkonan.home=${project.konanHome}", "-Djava.library.path=${project.konanHome}/konan/nativelib")
// Output directories -----------------------------------------------------
/** Directory with autogenerated interop stubs (*.kt) */
@@ -82,21 +75,7 @@ open class KonanInteropTask: KonanTargetableTask() {
@TaskAction
fun exec() {
if (dumpParameters) dumpProperties(this@KonanInteropTask)
project.javaexec {
with(it) {
main = INTEROP_MAIN
classpath = project.konanInteropClasspath
jvmArgs(INTEROP_JVM_ARGS)
environment("LIBCLANG_DISABLE_CRASH_RECOVERY", "1")
// TODO: remove this hack.
if (project.host == "mingw") {
environment("PATH", "${project.konanHome}\\dependencies\\msys2-mingw-w64-x86_64-gcc-6.3.0-clang-llvm-3.9.1-windows-x86-64\\bin;${System.getenv("PATH")}")
}
args(buildArgs().apply { logger.info("Interop args: ${this.joinToString(separator = " ")}") })
}
}
KonanInteropRunner(project).run(buildArgs())
}
protected fun buildArgs() = mutableListOf<String>().apply {
@@ -60,12 +60,6 @@ internal val Project.konanDefaultSrcFiles get() = fileTree("${projectDir
internal fun Project.konanDefaultDefFile(libName: String)
= file("${projectDir.canonicalPath}/src/main/c_interop/$libName.def")
internal val Project.konanInteropClasspath
get() = project.fileTree("${project.konanHome}/konan/lib/").apply { include("*.jar") }
internal val Project.konanCompilerClasspath
get() = project.fileTree("${project.konanHome}/konan/lib/").apply { include("*.jar") }
@Suppress("UNCHECKED_CAST")
internal val Project.konanArtifactsContainer: NamedDomainObjectContainer<KonanCompileConfig>
get() = extensions.getByName(KonanPlugin.ARTIFACTS_CONTAINER_NAME) as NamedDomainObjectContainer<KonanCompileConfig>
@@ -0,0 +1,72 @@
package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.Project
import org.gradle.api.file.FileCollection
// Consider using JavaExecSPec
internal interface KonanToolRunner {
val mainClass: String
val classpath: FileCollection
val jvmArgs: List<String>
val environment: Map<String, Any>
fun run(args: List<String>)
fun run(vararg args: String) = run(args.toList())
}
internal abstract class KonanBaseRunner(val project: Project): KonanToolRunner {
abstract val toolName: String
override val classpath: FileCollection
get() = project.fileTree("${project.konanHome}/konan/lib/").apply { include("*.jar") }
override val jvmArgs: List<String>
get() = listOf("-Dkonan.home=${project.konanHome}", "-Djava.library.path=${project.konanHome}/konan/nativelib")
override val environment: Map<String, Any>
get() = emptyMap()
override fun run(args: List<String>) {
if (classpath.isEmpty) {
throw IllegalStateException("Classpath if the tool is empty: $toolName\n" +
"Probably the 'konan.home' project property contains an incorrect path.\n" +
"Please change it to the compiler root directory and rerun the build.")
}
project.javaexec {
it.main = mainClass
it.classpath = classpath
it.jvmArgs(jvmArgs)
it.args(args.apply {
project.logger.info("Run tool: $toolName with args: ${this.joinToString(separator = " ")}")
})
it.environment(environment)
}
}
}
internal class KonanInteropRunner(project: Project) : KonanBaseRunner(project){
internal companion object {
const val INTEROP_MAIN = "org.jetbrains.kotlin.native.interop.gen.jvm.MainKt"
}
override val toolName get() = "Kotlin/Native cinterop tool"
override val mainClass get() = INTEROP_MAIN
override val environment = mutableMapOf("LIBCLANG_DISABLE_CRASH_RECOVERY" to "1").apply {
if (project.host == "mingw") {
put("PATH", "${project.konanHome}\\dependencies" +
"\\msys2-mingw-w64-x86_64-gcc-6.3.0-clang-llvm-3.9.1-windows-x86-64" +
"\\bin;${System.getenv("PATH")}")
}
}
}
internal class KonanCompilerRunner(project: Project) : KonanBaseRunner(project) {
internal companion object {
const val COMPILER_MAIN = "org.jetbrains.kotlin.cli.bc.K2NativeKt"
}
override val toolName get() = "Kotlin/Native compiler"
override val mainClass get() = COMPILER_MAIN
}