Add gradle plugin with simple DSL for Compilator and Stub generator
This commit is contained in:
@@ -24,3 +24,4 @@ include ':runtime'
|
||||
include ':common'
|
||||
include ':backend.native:tests'
|
||||
include ':tools:helpers'
|
||||
include ':tools:gradle-plugin'
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: "java"
|
||||
apply plugin: "kotlin"
|
||||
|
||||
// TODO: move this code to top level (the same for backend.native)
|
||||
// Copied from backend.native
|
||||
allprojects {
|
||||
repositories {
|
||||
maven {
|
||||
url 'http://oss.sonatype.org/content/repositories/snapshots'
|
||||
}
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
// kotlin-compiler module includes Kotlin runtime bundled;
|
||||
// make Gradle aware of this to avoid multiple Kotlin runtimes in classpath:
|
||||
resolutionStrategy.dependencySubstitution {
|
||||
substitute module('org.jetbrains.kotlin:kotlin-runtime') with module(kotlinCompilerModule)
|
||||
substitute module('org.jetbrains.kotlin:kotlin-stdlib') with module(kotlinCompilerModule)
|
||||
substitute module('org.jetbrains.kotlin:kotlin-reflect') with module(kotlinCompilerModule)
|
||||
}
|
||||
// TODO: probably we should use kotlin-compiler without bundled runtime
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
configurations {
|
||||
konanCompiler
|
||||
}
|
||||
|
||||
evaluationDependsOn(':tools:helpers')
|
||||
dependencies {
|
||||
// TODO: do we need it?
|
||||
konanCompiler project(':backend.native')
|
||||
|
||||
compile project(':tools:helpers')
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
compile gradleApi()
|
||||
}
|
||||
|
||||
jar {
|
||||
dependsOn(':tools:helpers:jar')
|
||||
from (rootProject.findProject(':tools:helpers').sourceSets.main.output)
|
||||
}
|
||||
|
||||
task dist(type: Copy) {
|
||||
dependsOn(jar)
|
||||
destinationDir project.file('dist')
|
||||
from jar.outputs.files
|
||||
}
|
||||
|
||||
task copy_to_samples(type: Copy) {
|
||||
dependsOn(dist)
|
||||
destinationDir rootProject.file('samples')
|
||||
from dist.outputs.files
|
||||
}
|
||||
|
||||
clean {
|
||||
doFirst {
|
||||
delete project.file('dist')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.GradleScriptException
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.jetbrains.kotlin.konan.DependencyDownloader
|
||||
import java.io.File
|
||||
|
||||
open class CompilerDownloadTask: DefaultTask() {
|
||||
|
||||
internal companion object {
|
||||
internal const val DOWNLOAD_URL = "http://download.jetbrains.com/kotlin/native"
|
||||
|
||||
internal val KONAN_NAME = "kotlin-native-${simpleOsName()}-${KonanPlugin.KONAN_VERSION}"
|
||||
private val KONAN_PARENT_DIR = "${System.getProperty("user.home")}/.konan"
|
||||
|
||||
internal fun simpleOsName(): String {
|
||||
val osName = System.getProperty("os.name")
|
||||
return when (osName) {
|
||||
"Mac OS X" -> "macos"
|
||||
"Linux" -> "linux"
|
||||
else -> throw IllegalStateException("Unsupported platform: $osName")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun downloadAndExtract() {
|
||||
if (project.hasProperty(KonanPlugin.KONAN_HOME_PROPERTY_NAME)) {
|
||||
val konanHome = project.property(KonanPlugin.KONAN_HOME_PROPERTY_NAME)
|
||||
logger.info("Use a user-defined compiler path: $konanHome")
|
||||
return
|
||||
}
|
||||
try {
|
||||
logger.info("Downloading Kotlin Native compiler from $DOWNLOAD_URL into $KONAN_PARENT_DIR")
|
||||
DependencyDownloader(File(KONAN_PARENT_DIR), DOWNLOAD_URL, listOf(KONAN_NAME)).run()
|
||||
project.extensions.extraProperties.set(KonanPlugin.KONAN_HOME_PROPERTY_NAME, "$KONAN_PARENT_DIR/$KONAN_NAME")
|
||||
} catch (e: RuntimeException) {
|
||||
throw GradleScriptException("Cannot download Kotlin Native compiler", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.Named
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.internal.project.ProjectInternal
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* We can the following:
|
||||
*
|
||||
* konanArtifacts {
|
||||
*
|
||||
* artifactName1 {
|
||||
*
|
||||
* inputDir "path/to/files"
|
||||
* inputFiles "files" "to" "be" "compiled"
|
||||
*
|
||||
* outputDir "path/to/output/dir"
|
||||
*
|
||||
* library "path/to/library"
|
||||
* library File("Library")
|
||||
*
|
||||
* nativeLibrary "path/to/library"
|
||||
* nativeLibrary File("Library")
|
||||
*
|
||||
* noStdLib
|
||||
* noLink
|
||||
* enableOptimization
|
||||
*
|
||||
* linkerOpts "linker" "args"
|
||||
* target "target"
|
||||
*
|
||||
* languageVersion "version"
|
||||
* apiVersion "version"
|
||||
*
|
||||
* }
|
||||
*
|
||||
* artifactName2 {
|
||||
*
|
||||
* extends artifactName1
|
||||
*
|
||||
* inputDir "someDir"
|
||||
* outputDir "someDir"
|
||||
* }
|
||||
*
|
||||
* }
|
||||
|
||||
*/
|
||||
// TODO: check debug outputs
|
||||
// TODO: Use +=/-= syntax for libraries and inputFiles
|
||||
open class KonanCompilerConfig(
|
||||
val configName: String,
|
||||
val project: ProjectInternal,
|
||||
taskNamePrefix: String = "compileKonan"): Named {
|
||||
|
||||
override fun getName() = configName
|
||||
|
||||
val compilationTask: KonanCompileTask = project.tasks.create(
|
||||
"$taskNamePrefix${configName.capitalize()}",
|
||||
KonanCompileTask::class.java
|
||||
) { it.initialize(this@KonanCompilerConfig.name) }
|
||||
|
||||
protected fun String.toAbsolutePath() = project.file(this).canonicalPath
|
||||
|
||||
// DSL methods --------------------------------------------------
|
||||
|
||||
// TODO: Check if we copied all data or not
|
||||
fun extendsFrom(anotherConfig: KonanCompilerConfig) = with(compilationTask) {
|
||||
val anotherTask = anotherConfig.compilationTask
|
||||
|
||||
outputDir(anotherTask.outputDir.absolutePath)
|
||||
|
||||
linkerOpts(anotherTask.linkerOpts)
|
||||
|
||||
anotherTask.target?.let { target(it) }
|
||||
anotherTask.languageVersion?.let { languageVersion(it) }
|
||||
anotherTask.apiVersion?.let { apiVersion(it) }
|
||||
|
||||
if (anotherTask.noStdLib) noStdLib()
|
||||
if (anotherTask.noLink) noLink()
|
||||
if (anotherTask.noMain) noMain()
|
||||
if (anotherTask.enableOptimization) enableOptimization()
|
||||
if (anotherTask.enableAssertions) enableAssertions()
|
||||
}
|
||||
|
||||
fun useInterop(interopConfig: KonanInteropConfig) {
|
||||
var generateStubsTask = interopConfig.generateStubsTask
|
||||
var compileStubsTask = interopConfig.compileStubsTask
|
||||
|
||||
compilationTask.dependsOn(compileStubsTask)
|
||||
compilationTask.dependsOn(generateStubsTask)
|
||||
|
||||
linkerOpts(generateStubsTask.linkerOpts)
|
||||
libraries(project.fileTree(compileStubsTask.outputDir).apply {
|
||||
builtBy(compileStubsTask)
|
||||
include("**/*.bc")
|
||||
})
|
||||
nativeLibraries(project.fileTree(generateStubsTask.libsDir).apply {
|
||||
builtBy(generateStubsTask)
|
||||
include("**/*.bc")
|
||||
})
|
||||
}
|
||||
fun useInterop(interop: String) = useInterop(project.konanInteropContainer.getByName(interop))
|
||||
|
||||
// DSL. Input/output files
|
||||
|
||||
fun inputDir(dir: String) = with(compilationTask) {
|
||||
inputFiles.add(project.fileTree(dir))
|
||||
}
|
||||
fun inputFiles(vararg files: Any) = with(compilationTask) {
|
||||
inputFiles.add(project.files(files))
|
||||
}
|
||||
fun inputFiles(files: FileCollection) = compilationTask.inputFiles.add(files)
|
||||
fun inputFiles(files: Collection<FileCollection>) = compilationTask.inputFiles.addAll(files)
|
||||
|
||||
|
||||
fun outputDir(dir: Any) = with(compilationTask) {
|
||||
outputDir = project.file(dir)
|
||||
}
|
||||
|
||||
// DSL. Libraries.
|
||||
|
||||
fun library(lib: Any) = libraries(lib)
|
||||
fun libraries(vararg libs: Any) = with(compilationTask) {
|
||||
libraries.add(project.files(*libs))
|
||||
}
|
||||
fun libraries(libs: FileCollection) = with(compilationTask) {
|
||||
libraries.add(libs)
|
||||
}
|
||||
|
||||
fun nativeLibrary(lib: Any) = nativeLibraries(lib)
|
||||
fun nativeLibraries(vararg libs: Any) = with(compilationTask) {
|
||||
nativeLibraries.add(project.files(*libs))
|
||||
}
|
||||
fun nativeLibraries(libs: FileCollection) = with(compilationTask) {
|
||||
nativeLibraries.add(libs)
|
||||
}
|
||||
|
||||
// DSL. Other parameters.
|
||||
|
||||
fun linkerOpts(args: List<String>) = linkerOpts(*args.toTypedArray())
|
||||
fun linkerOpts(vararg args: String) = with(compilationTask) {
|
||||
linkerOpts.addAll(args)
|
||||
}
|
||||
|
||||
fun target(tgt: String) = with(compilationTask) {
|
||||
target = tgt
|
||||
}
|
||||
|
||||
fun languageVersion(version: String) = with(compilationTask) {
|
||||
languageVersion = version
|
||||
}
|
||||
|
||||
fun apiVersion(version: String) = with(compilationTask) {
|
||||
apiVersion = version
|
||||
}
|
||||
|
||||
fun noStdLib() = with(compilationTask) {
|
||||
noStdLib = true
|
||||
}
|
||||
|
||||
fun noLink() = with(compilationTask) {
|
||||
noLink = true
|
||||
}
|
||||
|
||||
fun noMain() = with(compilationTask) {
|
||||
noMain = true
|
||||
}
|
||||
|
||||
fun enableOptimization() = with(compilationTask) {
|
||||
enableOptimization = true
|
||||
}
|
||||
|
||||
fun enableAssertions() = with(compilationTask) {
|
||||
enableAssertions = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.tasks.*
|
||||
import java.io.File
|
||||
|
||||
// TODO: form groups for tasks
|
||||
// TODO: Make the task class nested for config with properties accessible for outer users.
|
||||
open class KonanCompileTask: DefaultTask() {
|
||||
|
||||
companion object {
|
||||
const val COMPILER_MAIN = "org.jetbrains.kotlin.cli.bc.K2NativeKt"
|
||||
}
|
||||
|
||||
val COMPILER_JVM_ARGS: List<String>
|
||||
get() = listOf("-Dkonan.home=${project.konanHome}", "-Djava.library.path=${project.konanHome}/konan/nativelib")
|
||||
val COMPILER_CLASSPATH: String
|
||||
get() = "${project.konanHome}/konan/lib/"
|
||||
|
||||
// Output artifact --------------------------------------------------------
|
||||
|
||||
protected lateinit var artifactName: String
|
||||
|
||||
@OutputDirectory
|
||||
lateinit var outputDir: File
|
||||
internal set
|
||||
|
||||
internal fun initialize(artifactName: String) {
|
||||
dependsOn(project.konanCompilerDownloadTask)
|
||||
this.artifactName = artifactName
|
||||
outputDir = project.file("${project.konanCompilerOutputDir}/$artifactName")
|
||||
}
|
||||
|
||||
val artifactPath: String
|
||||
get() = "${outputDir.absolutePath}/$artifactName.${ if (noLink) "bc" else "kexe" }"
|
||||
|
||||
// Other compilation parameters -------------------------------------------
|
||||
|
||||
@InputFiles var inputFiles = mutableSetOf<FileCollection>()
|
||||
internal set
|
||||
|
||||
@InputFiles var libraries = mutableSetOf<FileCollection>()
|
||||
internal set
|
||||
@InputFiles var nativeLibraries = mutableSetOf<FileCollection>()
|
||||
internal set
|
||||
|
||||
@Input var linkerOpts = mutableListOf<String>()
|
||||
internal set
|
||||
|
||||
@Input var noStdLib = false
|
||||
internal set
|
||||
@Input var noLink = false
|
||||
internal set
|
||||
@Input var noMain = false
|
||||
internal set
|
||||
@Input var enableOptimization = false
|
||||
internal set
|
||||
@Input var enableAssertions = false
|
||||
internal set
|
||||
|
||||
@Optional @Input var target : String? = null
|
||||
internal set
|
||||
@Optional @Input var languageVersion : String? = null
|
||||
internal set
|
||||
@Optional @Input var apiVersion : String? = null
|
||||
internal set
|
||||
|
||||
// Useful extensions and functions ---------------------------------------
|
||||
|
||||
protected fun MutableList<String>.addArg(parameter: String, value: String) {
|
||||
add(parameter)
|
||||
add(value)
|
||||
}
|
||||
|
||||
protected fun MutableList<String>.addArgIfNotNull(parameter: String, value: String?) {
|
||||
if (value != null) {
|
||||
addArg(parameter, value)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun MutableList<String>.addKey(key: String, enabled: Boolean) {
|
||||
if (enabled) {
|
||||
add(key)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun MutableList<String>.addFileArgs(parameter: String, values: FileCollection) {
|
||||
values.files.forEach {
|
||||
addArg(parameter, it.canonicalPath)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun MutableList<String>.addFileArgs(parameter: String, values: Collection<FileCollection>) {
|
||||
values.forEach {
|
||||
addFileArgs(parameter, it)
|
||||
}
|
||||
}
|
||||
|
||||
// Task action ------------------------------------------------------------
|
||||
|
||||
protected fun buildArgs() = mutableListOf<String>().apply {
|
||||
addArg("-output", artifactPath)
|
||||
|
||||
addFileArgs("-library", libraries)
|
||||
addFileArgs("-nativelibrary", nativeLibraries)
|
||||
|
||||
linkerOpts.forEach {
|
||||
addArg("-linkerArgs", it)
|
||||
}
|
||||
|
||||
addArgIfNotNull("-target", target)
|
||||
addArgIfNotNull("-language-version", languageVersion)
|
||||
addArgIfNotNull("-api-version", apiVersion)
|
||||
|
||||
addKey("-nostdlib", noStdLib)
|
||||
addKey("-nolink", noLink)
|
||||
addKey("-nomain", noMain)
|
||||
addKey("-opt", enableOptimization)
|
||||
addKey("-ea", enableAssertions)
|
||||
|
||||
inputFiles.forEach {
|
||||
it.files.filter { it.name.endsWith(".kt") }.mapTo(this) { it.canonicalPath }
|
||||
}
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun compile() {
|
||||
project.file(outputDir).mkdirs()
|
||||
|
||||
// TODO: Use compiler service.
|
||||
project.javaexec {
|
||||
with(it) {
|
||||
main = COMPILER_MAIN
|
||||
classpath = project.fileTree(COMPILER_CLASSPATH).apply { include("*.jar") }
|
||||
jvmArgs(COMPILER_JVM_ARGS)
|
||||
args(buildArgs())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.Named
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.internal.project.ProjectInternal
|
||||
|
||||
/**
|
||||
* What we can:
|
||||
*
|
||||
* konanInterop {
|
||||
* foo {
|
||||
* defFile <def-file>
|
||||
* pkg <package with stubs>
|
||||
* target <target: linux/macbook/iphone/iphone_sim>
|
||||
* compilerOpts <Options for native stubs compilation>
|
||||
* linkerOpts <Options for native stubs >
|
||||
* headers <headers to process>
|
||||
* includeDirs <directories where headers are located>
|
||||
* linkFiles <files which will be linked with native stubs>
|
||||
* }
|
||||
*
|
||||
* // TODO: add configuration for konan compiler
|
||||
* }
|
||||
*/
|
||||
|
||||
open class KonanInteropConfig(
|
||||
val configName: String,
|
||||
val project: ProjectInternal
|
||||
): Named {
|
||||
|
||||
override fun getName() = configName
|
||||
|
||||
// Child tasks ------------------------------------------------------------
|
||||
|
||||
// Task to process the library and generate stubs
|
||||
val generateStubsTask: KonanInteropTask = project.tasks.create(
|
||||
"gen${name.capitalize()}InteropStubs",
|
||||
KonanInteropTask::class.java
|
||||
)
|
||||
|
||||
// Config and task to compile *.kt stubs in a *.bc library
|
||||
internal val compileStubsConfig = KonanCompilerConfig("${name}InteropStubs", project, "compile").apply {
|
||||
compilationTask.dependsOn(generateStubsTask)
|
||||
outputDir(generateStubsTask.stubsDir.absolutePath)
|
||||
noLink()
|
||||
inputFiles(project.fileTree(generateStubsTask.stubsDir).apply { builtBy(generateStubsTask) })
|
||||
}
|
||||
val compileStubsTask = compileStubsConfig.compilationTask
|
||||
|
||||
// DSL methods ------------------------------------------------------------
|
||||
|
||||
fun defFile(file: Any) = with(generateStubsTask) {
|
||||
defFile = project.file(file)
|
||||
}
|
||||
|
||||
fun pkg(value: String) = with(generateStubsTask) {
|
||||
pkg = value
|
||||
}
|
||||
|
||||
fun target(value: String) = with(generateStubsTask) {
|
||||
target = value
|
||||
}
|
||||
|
||||
fun compilerOpts(vararg values: String) = with(generateStubsTask) {
|
||||
compilerOpts.addAll(values)
|
||||
}
|
||||
|
||||
fun header(file: Any) = headers(file)
|
||||
fun headers(vararg files: Any) = with(generateStubsTask) {
|
||||
headers.add(project.files(files))
|
||||
}
|
||||
fun headers(files: FileCollection) = with(generateStubsTask) {
|
||||
headers.add(files)
|
||||
}
|
||||
|
||||
|
||||
fun includeDirs(vararg values: String) = with(generateStubsTask) {
|
||||
compilerOpts.addAll(values.map { "-I$it" })
|
||||
}
|
||||
|
||||
fun linker(value: String) = with(generateStubsTask) {
|
||||
linker = value
|
||||
}
|
||||
|
||||
fun linkerOpts(vararg values: String) = linkerOpts(values.toList())
|
||||
fun linkerOpts(values: List<String>) = with(generateStubsTask) {
|
||||
linkerOpts.addAll(values)
|
||||
}
|
||||
|
||||
fun link(vararg files: Any) = with(generateStubsTask) {
|
||||
linkFiles.add(project.files(files))
|
||||
}
|
||||
fun link(files: FileCollection) = with(generateStubsTask) {
|
||||
linkFiles.add(files)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.tasks.*
|
||||
import java.io.File
|
||||
|
||||
|
||||
open class KonanInteropTask: DefaultTask() {
|
||||
|
||||
internal companion object {
|
||||
const val INTEROP_MAIN = "org.jetbrains.kotlin.native.interop.gen.jvm.MainKt"
|
||||
}
|
||||
|
||||
init {
|
||||
dependsOn(project.konanCompilerDownloadTask)
|
||||
}
|
||||
|
||||
internal val INTEROP_JVM_ARGS: List<String>
|
||||
get() = listOf("-Dkonan.home=${project.konanHome}", "-Djava.library.path=${project.konanHome}/konan/nativelib")
|
||||
internal val INTEROP_CLASSPATH: String
|
||||
get() = "${project.konanHome}/konan/lib/"
|
||||
|
||||
|
||||
// Output directories -----------------------------------------------------
|
||||
|
||||
/** Directory with autogenerated interop stubs (*.kt) */
|
||||
@OutputDirectory
|
||||
val stubsDir = project.file("${project.konanInteropStubsOutputDir}/$name")
|
||||
|
||||
/** Directory with library bitcodes (*.bc) */
|
||||
@OutputDirectory
|
||||
val libsDir = project.file("${project.konanInteropLibsOutputDir}/$name")
|
||||
|
||||
// Interop stub generator parameters -------------------------------------
|
||||
|
||||
@Optional @InputFile var defFile: File? = null
|
||||
internal set
|
||||
@Optional @Input var target: String? = null
|
||||
internal set
|
||||
@Optional @Input var pkg: String? = null
|
||||
internal set
|
||||
@Optional @Input var linker: String? = null
|
||||
internal set
|
||||
|
||||
@Input var compilerOpts = mutableListOf<String>()
|
||||
internal set
|
||||
@Input var linkerOpts = mutableListOf<String>()
|
||||
internal set
|
||||
|
||||
// TODO: Check if we can use only one FileCollection instead of set.
|
||||
@InputFiles var headers = mutableSetOf<FileCollection>()
|
||||
internal set
|
||||
@InputFiles var linkFiles = mutableSetOf<FileCollection>()
|
||||
internal set
|
||||
|
||||
@TaskAction
|
||||
fun exec() {
|
||||
project.javaexec {
|
||||
with(it) {
|
||||
main = INTEROP_MAIN
|
||||
classpath = project.fileTree(INTEROP_CLASSPATH).apply { include("*.jar") }
|
||||
jvmArgs(INTEROP_JVM_ARGS)
|
||||
environment("LIBCLANG_DISABLE_CRASH_RECOVERY", "1")
|
||||
environment("LD_LIBRARY_PATH", "${project.konanHome}/nativelib")
|
||||
environment("DYLD_LIBRARY_PATH", "${project.konanHome}/nativelib")
|
||||
|
||||
args(buildArgs())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun buildArgs() = mutableListOf<String>().apply {
|
||||
add("-properties:${project.konanHome}/konan/konan.properties")
|
||||
add("-flavor:native")
|
||||
add("-generated:$stubsDir")
|
||||
add("-natives:$libsDir")
|
||||
|
||||
target?.let { add("-target:$target") }
|
||||
defFile?.let { add("-def:$it") }
|
||||
pkg?.let { add("-pkg:$it") }
|
||||
linker?.let { add("-linker:$it") }
|
||||
|
||||
headers.forEach {
|
||||
add("-h:$it")
|
||||
}
|
||||
|
||||
compilerOpts.forEach {
|
||||
add("-copt:$it")
|
||||
}
|
||||
|
||||
val linkerOpts = mutableListOf<String>().apply { addAll(linkerOpts) }
|
||||
linkFiles.forEach {
|
||||
linkerOpts.addAll(it.files.map { it.canonicalPath })
|
||||
}
|
||||
linkerOpts.forEach {
|
||||
add("-lopt:$it")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.internal.AbstractNamedDomainObjectContainer
|
||||
import org.gradle.api.internal.project.ProjectInternal
|
||||
import org.gradle.internal.reflect.Instantiator
|
||||
|
||||
/**
|
||||
* We use the follwing properties:
|
||||
* kotlin.native.home - directory where compiler is located (aka dist in konan project output)
|
||||
*/
|
||||
|
||||
// konanHome extension is set by downloadKonanCompiler task.
|
||||
internal val Project.konanHome: String
|
||||
get() {
|
||||
assert(extensions.extraProperties.has(KonanPlugin.KONAN_HOME_PROPERTY_NAME))
|
||||
return extensions.extraProperties.get(KonanPlugin.KONAN_HOME_PROPERTY_NAME).toString()
|
||||
}
|
||||
|
||||
internal val Project.konanBuildRoot get() = "${buildDir.canonicalPath}/konan"
|
||||
internal val Project.konanCompilerOutputDir get() = "${konanBuildRoot}/bin"
|
||||
internal val Project.konanInteropStubsOutputDir get() = "${konanBuildRoot}/interopStubs"
|
||||
internal val Project.konanInteropLibsOutputDir get() = "${konanBuildRoot}/nativelibs"
|
||||
|
||||
internal val Project.konanArtifactsContainer: KonanArtifactsContainer
|
||||
get() = extensions.getByName(KonanPlugin.COMPILER_EXTENSION_NAME) as KonanArtifactsContainer
|
||||
internal val Project.konanInteropContainer: KonanInteropContainer
|
||||
get() = extensions.getByName(KonanPlugin.INTEROP_EXTENSION_NAME) as KonanInteropContainer
|
||||
|
||||
internal val Project.konanCompilerDownloadTask get() = tasks.getByName(KonanPlugin.KONAN_DOWNLOAD_TASK_NAME)
|
||||
|
||||
class KonanArtifactsContainer(val project: ProjectInternal): AbstractNamedDomainObjectContainer<KonanCompilerConfig>(
|
||||
KonanCompilerConfig::class.java,
|
||||
project.gradle.services.get(Instantiator::class.java)) {
|
||||
|
||||
override fun doCreate(name: String): KonanCompilerConfig =
|
||||
KonanCompilerConfig(name, project)
|
||||
}
|
||||
|
||||
class KonanInteropContainer(val project: ProjectInternal): AbstractNamedDomainObjectContainer<KonanInteropConfig>(
|
||||
KonanInteropConfig::class.java,
|
||||
project.gradle.services.get(Instantiator::class.java)) {
|
||||
|
||||
override fun doCreate(name: String): KonanInteropConfig =
|
||||
KonanInteropConfig(name, project)
|
||||
}
|
||||
|
||||
class KonanPlugin: Plugin<ProjectInternal> {
|
||||
|
||||
companion object {
|
||||
internal const val COMPILER_EXTENSION_NAME = "konanArtifacts"
|
||||
internal const val INTEROP_EXTENSION_NAME = "konanInterop"
|
||||
internal const val KONAN_HOME_PROPERTY_NAME = "kotlin.native.home"
|
||||
internal const val KONAN_DOWNLOAD_TASK_NAME = "downloadKonanCompiler"
|
||||
|
||||
// TODO: Move in config.
|
||||
internal const val KONAN_VERSION = "0.1"
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks for task with given name in the given project.
|
||||
* If such task isn't found, will create it. Returns created/found task.
|
||||
*/
|
||||
private fun getTask(project: ProjectInternal, name: String): Task {
|
||||
var tasks = project.getTasksByName(name, false)
|
||||
assert(tasks.size <= 1)
|
||||
return if (tasks.isEmpty()) {
|
||||
project.tasks.create(name, DefaultTask::class.java)
|
||||
} else {
|
||||
tasks.single()
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Create default config? what about test sources?
|
||||
override fun apply(project: ProjectInternal?) {
|
||||
if (project == null) { return }
|
||||
project.tasks.create(KONAN_DOWNLOAD_TASK_NAME, CompilerDownloadTask::class.java)
|
||||
project.extensions.add(COMPILER_EXTENSION_NAME, KonanArtifactsContainer(project))
|
||||
project.extensions.add(INTEROP_EXTENSION_NAME, KonanInteropContainer(project))
|
||||
getTask(project, "clean").doLast {
|
||||
project.delete(project.konanBuildRoot)
|
||||
}
|
||||
getTask(project, "build").apply {
|
||||
dependsOn(project.tasks.withType(KonanCompileTask::class.java))
|
||||
dependsOn(project.tasks.withType(KonanInteropTask::class.java))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
# TODO: find a good name for the plugin
|
||||
implementation-class=org.jetbrains.kotlin.gradle.plugin.KonanPlugin
|
||||
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module relativePaths="true" type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output/>
|
||||
<orderEntry type="inheritedJdk"/>
|
||||
<content url="file://$MODULE_DIR$/">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/kotlin" isTestSource="false"/>
|
||||
<excludeFolder url="file://$MODULE_DIR$/.gradle"/>
|
||||
<excludeFolder url="file://$MODULE_DIR$/build"/>
|
||||
</content>
|
||||
<orderEntry type="sourceFolder" forTests="false"/>
|
||||
</component>
|
||||
<component name="ModuleRootManager"/>
|
||||
</module>
|
||||
Reference in New Issue
Block a user