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:
@@ -14,6 +14,7 @@ konanArtifacts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
task compileCpp(type: Exec) {
|
task compileCpp(type: Exec) {
|
||||||
|
dependsOn 'downloadKonanCompiler'
|
||||||
workingDir project.getProjectDir()
|
workingDir project.getProjectDir()
|
||||||
commandLine './buildCpp.sh'
|
commandLine './buildCpp.sh'
|
||||||
}
|
}
|
||||||
@@ -21,3 +22,7 @@ task compileCpp(type: Exec) {
|
|||||||
compileKonanMessageChannel {
|
compileKonanMessageChannel {
|
||||||
dependsOn 'compileCpp'
|
dependsOn 'compileCpp'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
downloadKonanCompiler {
|
||||||
|
downloadDependencies = true
|
||||||
|
}
|
||||||
+1
-15
@@ -29,13 +29,6 @@ import java.io.File
|
|||||||
*/
|
*/
|
||||||
open class KonanCompileTask: KonanTargetableTask() {
|
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 --------------------------------------------------------
|
// Output artifact --------------------------------------------------------
|
||||||
|
|
||||||
internal lateinit var artifactName: String
|
internal lateinit var artifactName: String
|
||||||
@@ -146,14 +139,7 @@ open class KonanCompileTask: KonanTargetableTask() {
|
|||||||
if (dumpParameters) dumpProperties(this@KonanCompileTask)
|
if (dumpParameters) dumpProperties(this@KonanCompileTask)
|
||||||
|
|
||||||
// TODO: Use compiler service.
|
// TODO: Use compiler service.
|
||||||
project.javaexec {
|
KonanCompilerRunner(project).run(buildArgs())
|
||||||
with(it) {
|
|
||||||
main = COMPILER_MAIN
|
|
||||||
classpath = project.konanCompilerClasspath
|
|
||||||
jvmArgs(COMPILER_JVM_ARGS)
|
|
||||||
args(buildArgs().apply { logger.info("Compiler args: ${this.joinToString(separator = " ")}") })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+28
-20
@@ -18,9 +18,10 @@ package org.jetbrains.kotlin.gradle.plugin
|
|||||||
|
|
||||||
import org.gradle.api.DefaultTask
|
import org.gradle.api.DefaultTask
|
||||||
import org.gradle.api.GradleScriptException
|
import org.gradle.api.GradleScriptException
|
||||||
import org.gradle.api.tasks.TaskAction
|
import org.gradle.api.tasks.*
|
||||||
import org.jetbrains.kotlin.konan.util.DependencyProcessor
|
import org.jetbrains.kotlin.konan.util.DependencyProcessor
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
open class KonanCompilerDownloadTask : DefaultTask() {
|
open class KonanCompilerDownloadTask : DefaultTask() {
|
||||||
|
|
||||||
@@ -30,32 +31,39 @@ open class KonanCompilerDownloadTask : DefaultTask() {
|
|||||||
internal val KONAN_PARENT_DIR = "${System.getProperty("user.home")}/.konan"
|
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
|
@TaskAction
|
||||||
fun downloadAndExtract() {
|
fun downloadAndExtract() {
|
||||||
if (!project.hasProperty(KonanPlugin.ProjectProperty.DOWNLOAD_COMPILER)) {
|
if (!project.hasProperty(KonanPlugin.ProjectProperty.DOWNLOAD_COMPILER)) {
|
||||||
val konanHome = project.getProperty(KonanPlugin.ProjectProperty.KONAN_HOME)
|
val konanHome = project.getProperty(KonanPlugin.ProjectProperty.KONAN_HOME)
|
||||||
logger.info("Use a user-defined compiler path: $konanHome")
|
logger.info("Use a user-defined compiler path: $konanHome")
|
||||||
|
} else {
|
||||||
val interopClasspath = project.konanInteropClasspath
|
try {
|
||||||
if (interopClasspath.isEmpty) {
|
val konanCompiler = project.konanCompilerName()
|
||||||
throw IllegalStateException("Stub generator classpath is empty: ${interopClasspath.dir}\n" +
|
logger.info("Downloading Kotlin/Native compiler from $DOWNLOAD_URL/$konanCompiler into $KONAN_PARENT_DIR")
|
||||||
"Probably the 'konan.home' project property contains an incorrect path. Please change it to the compiler root directory and rerun the build.")
|
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()
|
// Download dependencies if a user said so.
|
||||||
logger.info("Downloading Kotlin/Native compiler from $DOWNLOAD_URL/$konanCompiler into $KONAN_PARENT_DIR")
|
if (downloadDependencies) {
|
||||||
DependencyProcessor(File(KONAN_PARENT_DIR), DOWNLOAD_URL, listOf(konanCompiler)).run()
|
val runner = KonanCompilerRunner(project)
|
||||||
} catch (e: RuntimeException) {
|
if (targets.isEmpty()) {
|
||||||
throw GradleScriptException("Cannot download Kotlin/Native compiler", e)
|
// Download for the host.
|
||||||
|
runner.run("--check_dependencies")
|
||||||
|
} else {
|
||||||
|
targets.forEach { runner.run("--check_dependencies", "-target", it) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-22
@@ -29,19 +29,12 @@ import java.io.File
|
|||||||
*/
|
*/
|
||||||
open class KonanInteropTask: KonanTargetableTask() {
|
open class KonanInteropTask: KonanTargetableTask() {
|
||||||
|
|
||||||
internal companion object {
|
|
||||||
const val INTEROP_MAIN = "org.jetbrains.kotlin.native.interop.gen.jvm.MainKt"
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun init(libName: String) {
|
internal fun init(libName: String) {
|
||||||
dependsOn(project.konanCompilerDownloadTask)
|
dependsOn(project.konanCompilerDownloadTask)
|
||||||
this.libName = libName
|
this.libName = libName
|
||||||
this.defFile = project.konanDefaultDefFile(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 -----------------------------------------------------
|
// Output directories -----------------------------------------------------
|
||||||
|
|
||||||
/** Directory with autogenerated interop stubs (*.kt) */
|
/** Directory with autogenerated interop stubs (*.kt) */
|
||||||
@@ -82,21 +75,7 @@ open class KonanInteropTask: KonanTargetableTask() {
|
|||||||
@TaskAction
|
@TaskAction
|
||||||
fun exec() {
|
fun exec() {
|
||||||
if (dumpParameters) dumpProperties(this@KonanInteropTask)
|
if (dumpParameters) dumpProperties(this@KonanInteropTask)
|
||||||
|
KonanInteropRunner(project).run(buildArgs())
|
||||||
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 = " ")}") })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun buildArgs() = mutableListOf<String>().apply {
|
protected fun buildArgs() = mutableListOf<String>().apply {
|
||||||
|
|||||||
-6
@@ -60,12 +60,6 @@ internal val Project.konanDefaultSrcFiles get() = fileTree("${projectDir
|
|||||||
internal fun Project.konanDefaultDefFile(libName: String)
|
internal fun Project.konanDefaultDefFile(libName: String)
|
||||||
= file("${projectDir.canonicalPath}/src/main/c_interop/$libName.def")
|
= 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")
|
@Suppress("UNCHECKED_CAST")
|
||||||
internal val Project.konanArtifactsContainer: NamedDomainObjectContainer<KonanCompileConfig>
|
internal val Project.konanArtifactsContainer: NamedDomainObjectContainer<KonanCompileConfig>
|
||||||
get() = extensions.getByName(KonanPlugin.ARTIFACTS_CONTAINER_NAME) as NamedDomainObjectContainer<KonanCompileConfig>
|
get() = extensions.getByName(KonanPlugin.ARTIFACTS_CONTAINER_NAME) as NamedDomainObjectContainer<KonanCompileConfig>
|
||||||
|
|||||||
+72
@@ -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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user