Support cinterop in the native part of kotlin-multiplatform
This commit is contained in:
committed by
Ilya Matveev
parent
f7949a2131
commit
3269c0e51b
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.Named
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.tasks.SourceSetOutput
|
||||
|
||||
interface CInteropSettings: Named {
|
||||
|
||||
interface IncludeDirectories {
|
||||
fun allHeaders(vararg includeDirs: Any)
|
||||
fun allHeaders(includeDirs: Collection<Any>)
|
||||
|
||||
fun headerFilterOnly(vararg includeDirs: Any)
|
||||
fun headerFilterOnly(includeDirs: Collection<Any>)
|
||||
}
|
||||
|
||||
// TODO: Provide an interface for native compilations.
|
||||
val compilation: KotlinCompilation
|
||||
|
||||
// DSL.
|
||||
fun defFile(file: Any)
|
||||
|
||||
fun packageName(value: String)
|
||||
|
||||
fun header(file: Any) = headers(file)
|
||||
fun headers(vararg files: Any)
|
||||
fun headers(files: FileCollection)
|
||||
|
||||
fun includeDirs(vararg values: Any)
|
||||
fun includeDirs(closure: Closure<Unit>)
|
||||
fun includeDirs(action: Action<IncludeDirectories>)
|
||||
fun includeDirs(configure: IncludeDirectories.() -> Unit)
|
||||
|
||||
fun compilerOpts(vararg values: String)
|
||||
fun compilerOpts(values: List<String>)
|
||||
|
||||
fun linkerOpts(vararg values: String)
|
||||
fun linkerOpts(values: List<String>)
|
||||
|
||||
fun extraOpts(vararg values: Any)
|
||||
fun extraOpts(values: List<Any>)
|
||||
}
|
||||
+26
-1
@@ -551,4 +551,29 @@ class NewMultiplatformIT : BaseGradleIT() {
|
||||
assertTasksExecuted(hostTestTask)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCinterop() = with(Project("new-mpp-native-cinterop", gradleVersion)) {
|
||||
val host = nativeHostTargetName
|
||||
build(":projectLibrary:build") {
|
||||
assertSuccessful()
|
||||
assertTasksExecuted(":projectLibrary:cinteropStdio${host.capitalize()}")
|
||||
assertTrue(output.contains("Project test"), "No test output found")
|
||||
assertFileExists("projectLibrary/build/classes/kotlin/$host/main/projectLibrary-cinterop-stdio.klib")
|
||||
}
|
||||
|
||||
build(":publishedLibrary:build", ":publishedLibrary:publish") {
|
||||
assertSuccessful()
|
||||
assertTasksExecuted(":publishedLibrary:cinteropStdio${host.capitalize()}")
|
||||
assertTrue(output.contains("Published test"), "No test output found")
|
||||
assertFileExists("publishedLibrary/build/classes/kotlin/$host/main/publishedLibrary-cinterop-stdio.klib")
|
||||
assertFileExists("repo/org/example/publishedLibrary-$host/1.0/publishedLibrary-$host-1.0-cinterop-stdio.klib")
|
||||
}
|
||||
|
||||
build(":build") {
|
||||
assertSuccessful()
|
||||
assertTrue(output.contains("Dependent: Project print"), "No test output found")
|
||||
assertTrue(output.contains("Dependent: Published print"), "No test output found")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
apply plugin: 'kotlin-multiplatform'
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
jcenter()
|
||||
maven { url "http://dl.bintray.com/kotlin/kotlinx.html/" }
|
||||
maven { url 'repo' }
|
||||
}
|
||||
|
||||
kotlin {
|
||||
sourceSets {
|
||||
allNative {
|
||||
dependencies {
|
||||
implementation project(':projectLibrary')
|
||||
implementation 'org.example:publishedLibrary:1.0'
|
||||
}
|
||||
}
|
||||
nativeTest
|
||||
|
||||
macos64Main { dependsOn sourceSets.allNative }
|
||||
linux64Main { dependsOn sourceSets.allNative }
|
||||
mingw64Main { dependsOn sourceSets.allNative }
|
||||
|
||||
macos64Test { dependsOn sourceSets.nativeTest }
|
||||
linux64Test { dependsOn sourceSets.nativeTest }
|
||||
mingw64Test { dependsOn sourceSets.nativeTest }
|
||||
}
|
||||
|
||||
targets {
|
||||
fromPreset(presets.macosX64, 'macos64')
|
||||
fromPreset(presets.linuxX64, 'linux64')
|
||||
fromPreset(presets.mingwX64, 'mingw64')
|
||||
|
||||
configure([macos64, linux64, mingw64]) {
|
||||
compilations.main.outputKinds ['EXECUTABLE']
|
||||
}
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
apply plugin: 'kotlin-multiplatform'
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
jcenter()
|
||||
maven { url "http://dl.bintray.com/kotlin/kotlinx.html/" }
|
||||
}
|
||||
|
||||
kotlin {
|
||||
sourceSets {
|
||||
allNative
|
||||
nativeTest
|
||||
|
||||
macos64Main { dependsOn sourceSets.allNative }
|
||||
linux64Main { dependsOn sourceSets.allNative }
|
||||
mingw64Main { dependsOn sourceSets.allNative }
|
||||
|
||||
macos64Test { dependsOn sourceSets.nativeTest }
|
||||
linux64Test { dependsOn sourceSets.nativeTest }
|
||||
mingw64Test { dependsOn sourceSets.nativeTest }
|
||||
}
|
||||
|
||||
targets {
|
||||
fromPreset(presets.macosX64, 'macos64')
|
||||
fromPreset(presets.linuxX64, 'linux64')
|
||||
fromPreset(presets.mingwX64, 'mingw64')
|
||||
|
||||
configure([macos64, linux64, mingw64]) {
|
||||
compilations.main.cinterops {
|
||||
stdio {
|
||||
packageName 'example.cinterop.project.stdio'
|
||||
extraOpts '-nodefaultlibs'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package example.cinterop.project
|
||||
|
||||
import example.cinterop.project.stdio.*
|
||||
|
||||
fun projectPrint(str: String) {
|
||||
printf(str + '\n')
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
headers = stdio.h
|
||||
compilerOpts.osx = -D_ANSI_SOURCE
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
package example.cinterop.project
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
@Test
|
||||
fun projectTest() {
|
||||
projectPrint("Project test")
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
apply plugin: 'kotlin-multiplatform'
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
group = 'org.example'
|
||||
version = '1.0'
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
jcenter()
|
||||
maven { url "http://dl.bintray.com/kotlin/kotlinx.html/" }
|
||||
}
|
||||
|
||||
kotlin {
|
||||
sourceSets {
|
||||
allNative
|
||||
nativeTest
|
||||
|
||||
macos64Main { dependsOn sourceSets.allNative }
|
||||
linux64Main { dependsOn sourceSets.allNative }
|
||||
mingw64Main { dependsOn sourceSets.allNative }
|
||||
|
||||
macos64Test { dependsOn sourceSets.nativeTest }
|
||||
linux64Test { dependsOn sourceSets.nativeTest }
|
||||
mingw64Test { dependsOn sourceSets.nativeTest }
|
||||
}
|
||||
|
||||
targets {
|
||||
fromPreset(presets.macosX64, 'macos64')
|
||||
fromPreset(presets.linuxX64, 'linux64')
|
||||
fromPreset(presets.mingwX64, 'mingw64')
|
||||
|
||||
configure([macos64, linux64, mingw64]) {
|
||||
compilations.main.cinterops {
|
||||
stdio {
|
||||
packageName 'example.cinterop.published.stdio'
|
||||
extraOpts '-nodefaultlibs'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
publishing {
|
||||
repositories {
|
||||
maven {
|
||||
url = '../repo'
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package example.cinterop.published
|
||||
|
||||
import example.cinterop.published.stdio.*
|
||||
|
||||
fun publishedPrint(str: String) {
|
||||
printf(str + '\n')
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
headers = stdio.h
|
||||
compilerOpts.osx = -D_ANSI_SOURCE
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
package example.cinterop.published
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
@Test
|
||||
fun publishedTest() {
|
||||
publishedPrint("Published test")
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
enableFeaturePreview('GRADLE_METADATA')
|
||||
|
||||
rootProject.name = 'native-cinterop'
|
||||
|
||||
include 'projectLibrary'
|
||||
include 'publishedLibrary'
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import example.cinterop.project.*
|
||||
import example.cinterop.published.*
|
||||
|
||||
fun dependentProject() {
|
||||
projectPrint("Dependent: Project print")
|
||||
publishedPrint("Dependent: Published print")
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
@Test
|
||||
fun dependentTest() {
|
||||
dependentProject()
|
||||
}
|
||||
+51
-10
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.getSourceSetHierarchy
|
||||
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.tasks.CInteropProcess
|
||||
import org.jetbrains.kotlin.gradle.tasks.KonanCompilerDownloadTask
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile
|
||||
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
|
||||
@@ -387,9 +388,6 @@ open class KotlinNativeTargetConfigurator(
|
||||
private val Collection<*>.isDimensionVisible: Boolean
|
||||
get() = size > 1
|
||||
|
||||
private val KotlinNativeCompilation.isMainCompilation: Boolean
|
||||
get() = name == KotlinCompilation.MAIN_COMPILATION_NAME
|
||||
|
||||
private fun Project.createTestTask(compilation: KotlinNativeCompilation, testExecutableLinkTask: KotlinNativeCompile) {
|
||||
val compilationSuffix = compilation.name.takeIf { it != KotlinCompilation.TEST_COMPILATION_NAME }.orEmpty()
|
||||
val taskName = lowerCamelCaseName(compilation.target.targetName, compilationSuffix, testTaskNameSuffix)
|
||||
@@ -430,7 +428,7 @@ open class KotlinNativeTargetConfigurator(
|
||||
return buildDir.resolve("bin/$targetSubDirectory${compilation.name}/$buildTypeSubDirectory/$kindSubDirectory")
|
||||
}
|
||||
|
||||
private fun Project.klibOutputDirectory(
|
||||
private fun Project. klibOutputDirectory(
|
||||
compilation: KotlinNativeCompilation
|
||||
): File {
|
||||
val targetSubDirectory = compilation.target.disambiguationClassifier?.let { "$it/" }.orEmpty()
|
||||
@@ -481,7 +479,6 @@ open class KotlinNativeTargetConfigurator(
|
||||
|
||||
private fun Project.createBinaryLinkTasks(compilation: KotlinNativeCompilation) = whenEvaluated {
|
||||
val konanTarget = compilation.target.konanTarget
|
||||
val buildTypes = compilation.buildTypes
|
||||
val availableOutputKinds = compilation.outputKinds.filter { it.availableFor(konanTarget) }
|
||||
val linkAll = project.tasks.maybeCreate(compilation.linkAllTaskName)
|
||||
|
||||
@@ -506,6 +503,7 @@ open class KotlinNativeTargetConfigurator(
|
||||
registerOutputFiles(binaryOutputDirectory(buildType, kind, compilation))
|
||||
addCompilerPlugins()
|
||||
|
||||
dependsOn(compilation.compileKotlinTaskName)
|
||||
dependsOnCompilerDownloading()
|
||||
linkAll.dependsOn(this)
|
||||
}
|
||||
@@ -523,7 +521,12 @@ open class KotlinNativeTargetConfigurator(
|
||||
}
|
||||
}
|
||||
|
||||
private fun Project.createKlibPublishableArtifact(compilation: KotlinNativeCompilation, compileTask: KotlinNativeCompile) {
|
||||
private fun Project.createKlibArtifact(
|
||||
compilation: KotlinNativeCompilation,
|
||||
artifactFile: File,
|
||||
classifier: String?,
|
||||
producingTask: Task
|
||||
) {
|
||||
if (!compilation.target.konanTarget.enabledOnCurrentHost) {
|
||||
return
|
||||
}
|
||||
@@ -533,10 +536,10 @@ open class KotlinNativeTargetConfigurator(
|
||||
compilation.name,
|
||||
"klib",
|
||||
"klib",
|
||||
null,
|
||||
classifier,
|
||||
Date(),
|
||||
compileTask.outputFile.get(),
|
||||
compileTask
|
||||
artifactFile,
|
||||
producingTask
|
||||
)
|
||||
project.extensions.getByType(DefaultArtifactPublicationSet::class.java).addCandidate(klibArtifact)
|
||||
|
||||
@@ -546,6 +549,17 @@ open class KotlinNativeTargetConfigurator(
|
||||
}
|
||||
}
|
||||
|
||||
private fun Project.createRegularKlibArtifact(
|
||||
compilation: KotlinNativeCompilation,
|
||||
compileTask: KotlinNativeCompile
|
||||
) = createKlibArtifact(compilation, compileTask.outputFile.get(), null, compileTask)
|
||||
|
||||
private fun Project.createCInteropKlibArtifact(
|
||||
interop: DefaultCInteropSettings,
|
||||
interopTask: CInteropProcess
|
||||
) = createKlibArtifact(interop.compilation, interopTask.outputFile, "cinterop-${interop.name}", interopTask)
|
||||
|
||||
|
||||
private fun Project.createKlibCompilationTask(compilation: KotlinNativeCompilation) {
|
||||
val compileTask = tasks.create(
|
||||
compilation.compileKotlinTaskName,
|
||||
@@ -577,7 +591,29 @@ open class KotlinNativeTargetConfigurator(
|
||||
dependsOn(compileTask)
|
||||
dependsOn(compilation.linkAllTaskName)
|
||||
}
|
||||
createKlibPublishableArtifact(compilation, compileTask)
|
||||
createRegularKlibArtifact(compilation, compileTask)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Project.createCInteropTasks(compilation: KotlinNativeCompilation) {
|
||||
compilation.cinterops.all { interop ->
|
||||
val interopTask = tasks.create(interop.interopProcessingTaskName, CInteropProcess::class.java).apply {
|
||||
settings = interop
|
||||
destinationDir = provider { klibOutputDirectory(compilation) }
|
||||
group = INTEROP_GROUP
|
||||
description = "Generates Kotlin/Native interop library '${interop.name}' " +
|
||||
"for compilation '${compilation.name}'" +
|
||||
"of target '${konanTarget.name}'."
|
||||
enabled = compilation.target.konanTarget.enabledOnCurrentHost
|
||||
|
||||
dependsOnCompilerDownloading()
|
||||
val interopOutput = project.files(outputFileProvider).builtBy(this)
|
||||
with(compilation) {
|
||||
interopFiles += interopOutput
|
||||
output.tryAddClassesDir { interopOutput }
|
||||
}
|
||||
}
|
||||
createCInteropKlibArtifact(interop, interopTask)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -585,6 +621,7 @@ open class KotlinNativeTargetConfigurator(
|
||||
tasks.create(target.artifactsTaskName)
|
||||
target.compilations.all {
|
||||
createKlibCompilationTask(it)
|
||||
createCInteropTasks(it)
|
||||
createBinaryLinkTasks(it)
|
||||
}
|
||||
|
||||
@@ -599,6 +636,10 @@ open class KotlinNativeTargetConfigurator(
|
||||
object NativeArtifactFormat {
|
||||
const val KLIB = "org.jetbrains.kotlin.klib"
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val INTEROP_GROUP = "interop"
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Project.usageByName(usageName: String): Usage =
|
||||
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.tasks.SourceSetOutput
|
||||
import org.gradle.util.ConfigureUtil
|
||||
import org.jetbrains.kotlin.gradle.plugin.CInteropSettings
|
||||
import org.jetbrains.kotlin.gradle.plugin.CInteropSettings.IncludeDirectories
|
||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
open class DefaultCInteropSettings @Inject constructor(
|
||||
private val project: Project,
|
||||
private val name: String,
|
||||
override val compilation: KotlinNativeCompilation
|
||||
) : CInteropSettings {
|
||||
|
||||
inner class DefaultIncludeDirectories: CInteropSettings.IncludeDirectories {
|
||||
var allHeadersDirs: FileCollection = project.files()
|
||||
var headerFilterDirs: FileCollection = project.files()
|
||||
|
||||
override fun allHeaders(vararg includeDirs: Any) = allHeaders(includeDirs.toList())
|
||||
override fun allHeaders(includeDirs: Collection<Any>) {
|
||||
allHeadersDirs += project.files(*includeDirs.toTypedArray())
|
||||
}
|
||||
|
||||
override fun headerFilterOnly(vararg includeDirs: Any) = headerFilterOnly(includeDirs.toList())
|
||||
override fun headerFilterOnly(includeDirs: Collection<Any>) {
|
||||
headerFilterDirs += project.files(*includeDirs.toTypedArray())
|
||||
}
|
||||
}
|
||||
|
||||
override fun getName(): String = name
|
||||
|
||||
val target: KotlinNativeTarget
|
||||
get() = compilation.target
|
||||
|
||||
val interopProcessingTaskName: String
|
||||
get() = lowerCamelCaseName(
|
||||
"cinterop",
|
||||
compilation.compilationName.takeIf { it != "main" }.orEmpty(),
|
||||
name,
|
||||
target.disambiguationClassifier
|
||||
)
|
||||
|
||||
var defFile: File = project.projectDir.resolve("src/nativeInterop/cinterop/$name.def")
|
||||
var packageName: String? = null
|
||||
|
||||
val compilerOpts = mutableListOf<String>()
|
||||
val linkerOpts = mutableListOf<String>()
|
||||
val extraOpts = mutableListOf<String>()
|
||||
|
||||
val includeDirs = DefaultIncludeDirectories()
|
||||
var headers: FileCollection = project.files()
|
||||
|
||||
// DSL methods.
|
||||
|
||||
override fun defFile(file: Any) {
|
||||
defFile = project.file(file)
|
||||
}
|
||||
|
||||
override fun packageName(value: String) {
|
||||
packageName = value
|
||||
}
|
||||
|
||||
override fun header(file: Any) = headers(file)
|
||||
override fun headers(vararg files: Any) = headers(project.files(files))
|
||||
override fun headers(files: FileCollection) {
|
||||
headers += files
|
||||
}
|
||||
|
||||
override fun includeDirs(vararg values: Any) = includeDirs.allHeaders(values.toList())
|
||||
override fun includeDirs(closure: Closure<Unit>) = includeDirs(ConfigureUtil.configureUsing(closure))
|
||||
override fun includeDirs(action: Action<IncludeDirectories>) = includeDirs { action.execute(this) }
|
||||
override fun includeDirs(configure: IncludeDirectories.() -> Unit) = includeDirs.configure()
|
||||
|
||||
override fun compilerOpts(vararg values: String) = compilerOpts(values.toList())
|
||||
override fun compilerOpts(values: List<String>) {
|
||||
compilerOpts.addAll(values)
|
||||
}
|
||||
|
||||
override fun linkerOpts(vararg values: String) = linkerOpts(values.toList())
|
||||
override fun linkerOpts(values: List<String>) {
|
||||
linkerOpts.addAll(values)
|
||||
}
|
||||
|
||||
override fun extraOpts(vararg values: Any) = extraOpts(values.toList())
|
||||
override fun extraOpts(values: List<Any>) {
|
||||
extraOpts.addAll(values.map { it.toString() })
|
||||
}
|
||||
}
|
||||
+25
-1
@@ -6,6 +6,8 @@
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.NamedDomainObjectContainer
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.attributes.AttributeContainer
|
||||
import org.gradle.api.file.FileCollection
|
||||
@@ -269,6 +271,9 @@ class KotlinNativeCompilation(
|
||||
override val output: SourceSetOutput
|
||||
) : AbstractKotlinCompilation(target, name) {
|
||||
|
||||
private val project: Project
|
||||
get() = target.project
|
||||
|
||||
// A FileCollection containing source files from all source sets used by this compilation
|
||||
// (taking into account dependencies between source sets). Used by both compilation
|
||||
// and linking tasks.
|
||||
@@ -279,6 +284,8 @@ class KotlinNativeCompilation(
|
||||
|
||||
var friendCompilationName: String? = null
|
||||
|
||||
var interopFiles: FileCollection = project.files()
|
||||
|
||||
internal val friendCompilation: KotlinNativeCompilation?
|
||||
get() = friendCompilationName?.let {
|
||||
target.compilations.getByName(it)
|
||||
@@ -320,6 +327,24 @@ class KotlinNativeCompilation(
|
||||
var entryPoint: String? = null
|
||||
fun entryPoint(value: String) { entryPoint = value }
|
||||
|
||||
// Interop DSL.
|
||||
val cinterops = project.container(DefaultCInteropSettings::class.java) { cinteropName ->
|
||||
DefaultCInteropSettings(project, cinteropName,this)
|
||||
}
|
||||
|
||||
var linkerOpts = mutableListOf<String>()
|
||||
|
||||
fun cinterops(action: NamedDomainObjectContainer<DefaultCInteropSettings>.() -> Unit) = cinterops.action()
|
||||
fun cinterops(action: Closure<Unit>) = cinterops(ConfigureUtil.configureUsing(action))
|
||||
fun cinterops(action: Action<NamedDomainObjectContainer<DefaultCInteropSettings>>) = action.execute(cinterops)
|
||||
|
||||
fun linkerOpts(vararg values: String) = linkerOpts(values.toList())
|
||||
fun linkerOpts(values: List<String>) {
|
||||
linkerOpts.addAll(values)
|
||||
}
|
||||
|
||||
// Task accessors.
|
||||
|
||||
fun findLinkTask(kind: NativeOutputKind, buildType: NativeBuildType): KotlinNativeCompile? = binaryTasks[kind to buildType]
|
||||
|
||||
fun getLinkTask(kind: NativeOutputKind, buildType: NativeBuildType): KotlinNativeCompile =
|
||||
@@ -381,7 +406,6 @@ class KotlinNativeCompilation(
|
||||
// TODO: support optional expectations
|
||||
allSources += sourceSet.kotlin
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private object CompilationSourceSetUtil {
|
||||
|
||||
+3
@@ -302,3 +302,6 @@ internal val KonanTarget.presetName: String
|
||||
KonanTarget.ANDROID_ARM64 -> "androidNativeArm64"
|
||||
else -> lowerCamelCaseName(*this.name.split('_').toTypedArray())
|
||||
}
|
||||
|
||||
internal val KotlinNativeCompilation.isMainCompilation: Boolean
|
||||
get() = name == KotlinCompilation.MAIN_COMPILATION_NAME
|
||||
|
||||
+159
-50
@@ -1,27 +1,78 @@
|
||||
package org.jetbrains.kotlin.gradle.tasks
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.repositories.ArtifactRepository
|
||||
import org.gradle.api.artifacts.repositories.IvyPatternRepositoryLayout
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.file.FileTree
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.jetbrains.kotlin.compilerRunner.*
|
||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultCInteropSettings
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.defaultSourceSetName
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.isMainCompilation
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.konan.KonanVersionImpl
|
||||
import org.jetbrains.kotlin.konan.MetaVersion
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.util.DependencyDirectories
|
||||
import java.io.File
|
||||
|
||||
// TODO: It's just temporary tasks used while KN isn't integrated with Big Kotlin compilation infrastructure.
|
||||
// region Useful extensions
|
||||
internal fun MutableList<String>.addArg(parameter: String, value: String) {
|
||||
add(parameter)
|
||||
add(value)
|
||||
}
|
||||
|
||||
internal fun MutableList<String>.addArgs(parameter: String, values: Iterable<String>) {
|
||||
values.forEach {
|
||||
addArg(parameter, it)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun MutableList<String>.addArgIfNotNull(parameter: String, value: String?) {
|
||||
if (value != null) {
|
||||
addArg(parameter, value)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun MutableList<String>.addKey(key: String, enabled: Boolean) {
|
||||
if (enabled) {
|
||||
add(key)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun MutableList<String>.addFileArgs(parameter: String, values: FileCollection) {
|
||||
values.files.forEach {
|
||||
addArg(parameter, it.canonicalPath)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun MutableList<String>.addFileArgs(parameter: String, values: Collection<FileCollection>) {
|
||||
values.forEach {
|
||||
addFileArgs(parameter, it)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun MutableList<String>.addListArg(parameter: String, values: List<String>) {
|
||||
if (values.isNotEmpty()) {
|
||||
addArg(parameter, values.joinToString(separator = " "))
|
||||
}
|
||||
}
|
||||
|
||||
private fun File.providedByCompiler(project: Project): Boolean =
|
||||
toPath().startsWith(project.file(project.konanHome).toPath())
|
||||
// endregion
|
||||
|
||||
|
||||
open class KotlinNativeCompile : AbstractCompile() {
|
||||
|
||||
@@ -55,7 +106,7 @@ open class KotlinNativeCompile : AbstractCompile() {
|
||||
get() = compilation.allSources
|
||||
|
||||
val libraries: FileCollection
|
||||
@InputFiles get() = compilation.compileDependencyFiles
|
||||
@InputFiles get() = compilation.compileDependencyFiles + compilation.interopFiles
|
||||
|
||||
private val friendModule: FileCollection?
|
||||
// It's already taken into account in libraries
|
||||
@@ -63,7 +114,7 @@ open class KotlinNativeCompile : AbstractCompile() {
|
||||
|
||||
override fun getClasspath(): FileCollection = libraries
|
||||
override fun setClasspath(configuration: FileCollection?) {
|
||||
throw UnsupportedOperationException("Setting class path directly is unsupported.")
|
||||
throw UnsupportedOperationException("Setting classpath directly is unsupported.")
|
||||
}
|
||||
|
||||
@Input
|
||||
@@ -80,6 +131,9 @@ open class KotlinNativeCompile : AbstractCompile() {
|
||||
val entryPoint: String?
|
||||
@Optional @Input get() = compilation.entryPoint
|
||||
|
||||
val linkerOpts: List<String>
|
||||
@Input get() = compilation.linkerOpts
|
||||
|
||||
val additionalCompilerOptions: Collection<String>
|
||||
@Input get() = compilation.extraOpts
|
||||
|
||||
@@ -117,52 +171,6 @@ open class KotlinNativeCompile : AbstractCompile() {
|
||||
@Optional @InputFiles
|
||||
var compilerPluginClasspath: FileCollection? = null
|
||||
|
||||
// region Useful extensions
|
||||
internal fun MutableList<String>.addArg(parameter: String, value: String) {
|
||||
add(parameter)
|
||||
add(value)
|
||||
}
|
||||
|
||||
internal fun MutableList<String>.addArgs(parameter: String, values: Iterable<String>) {
|
||||
values.forEach {
|
||||
addArg(parameter, it)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun MutableList<String>.addArgIfNotNull(parameter: String, value: String?) {
|
||||
if (value != null) {
|
||||
addArg(parameter, value)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun MutableList<String>.addKey(key: String, enabled: Boolean) {
|
||||
if (enabled) {
|
||||
add(key)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun MutableList<String>.addFileArgs(parameter: String, values: FileCollection) {
|
||||
values.files.forEach {
|
||||
addArg(parameter, it.canonicalPath)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun MutableList<String>.addFileArgs(parameter: String, values: Collection<FileCollection>) {
|
||||
values.forEach {
|
||||
addFileArgs(parameter, it)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun MutableList<String>.addListArg(parameter: String, values: List<String>) {
|
||||
if (values.isNotEmpty()) {
|
||||
addArg(parameter, values.joinToString(separator = " "))
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
|
||||
private val File.providedByCompiler: Boolean
|
||||
get() = toPath().startsWith(project.file(project.konanHome).toPath())
|
||||
|
||||
@TaskAction
|
||||
override fun compile() {
|
||||
val output = outputFile.get()
|
||||
@@ -204,7 +212,7 @@ open class KotlinNativeCompile : AbstractCompile() {
|
||||
// Libraries.
|
||||
libraries.files.filter {
|
||||
// Support only klib files for now.
|
||||
it.extension == "klib" && !it.providedByCompiler
|
||||
it.extension == "klib" && !it.providedByCompiler(project)
|
||||
}.forEach { library ->
|
||||
library.parent?.let { addArg("-r", it) }
|
||||
addArg("-l", library.nameWithoutExtension)
|
||||
@@ -215,6 +223,8 @@ open class KotlinNativeCompile : AbstractCompile() {
|
||||
addArg("-friend-modules", friends.map { it.absolutePath }.joinToString(File.pathSeparator))
|
||||
}
|
||||
|
||||
addListArg("-linkerOpts", linkerOpts)
|
||||
|
||||
// Sources.
|
||||
// TODO: Filter only kt files?
|
||||
addAll(sources.files.map { it.absolutePath })
|
||||
@@ -224,6 +234,106 @@ open class KotlinNativeCompile : AbstractCompile() {
|
||||
}
|
||||
}
|
||||
|
||||
open class CInteropProcess: DefaultTask() {
|
||||
|
||||
@Internal
|
||||
lateinit var settings: DefaultCInteropSettings
|
||||
|
||||
@Internal // Taken into account in the outputFileProvider property
|
||||
lateinit var destinationDir: Provider<File>
|
||||
|
||||
val konanTarget: KonanTarget
|
||||
@Internal get() = settings.compilation.target.konanTarget
|
||||
|
||||
val interopName: String
|
||||
@Internal get() = settings.name
|
||||
|
||||
val outputFileName: String
|
||||
@Internal get() = with(CompilerOutputKind.LIBRARY) {
|
||||
val baseName = settings.compilation.let {
|
||||
if (it.isMainCompilation) project.name else it.name
|
||||
}
|
||||
val suffix = suffix(konanTarget)
|
||||
return "$baseName-cinterop-$interopName$suffix"
|
||||
}
|
||||
|
||||
val outputFile: File
|
||||
@Internal get() = outputFileProvider.get().asFile
|
||||
|
||||
// Inputs and outputs.
|
||||
|
||||
@OutputFile
|
||||
val outputFileProvider = newOutputFile().apply {
|
||||
set { destinationDir.get().resolve(outputFileName) }
|
||||
}
|
||||
|
||||
val defFile: File
|
||||
@InputFile get() = settings.defFile
|
||||
|
||||
val packageName: String?
|
||||
@Optional @Input get() = settings.packageName
|
||||
|
||||
val compilerOpts: List<String>
|
||||
@Input get() = settings.compilerOpts
|
||||
|
||||
val linkerOpts: List<String>
|
||||
@Input get() = settings.linkerOpts
|
||||
|
||||
val headers: FileCollection
|
||||
@InputFiles get() = settings.headers
|
||||
|
||||
val allHeadersDirs: Set<File>
|
||||
@Input get() = settings.includeDirs.allHeadersDirs.files
|
||||
|
||||
val headerFilterDirs: Set<File>
|
||||
@Input get() = settings.includeDirs.headerFilterDirs.files
|
||||
|
||||
val libraries: FileCollection
|
||||
@InputFiles get() = settings.compilation.compileDependencyFiles
|
||||
|
||||
val extraOpts: List<String>
|
||||
@Input get() = settings.extraOpts
|
||||
|
||||
|
||||
// Task action.
|
||||
@TaskAction
|
||||
fun processInterop() {
|
||||
val args = mutableListOf<String>().apply {
|
||||
addArg("-o", outputFile.absolutePath)
|
||||
|
||||
addArgIfNotNull("-target", konanTarget.visibleName)
|
||||
addArgIfNotNull("-def", defFile.canonicalPath)
|
||||
addArgIfNotNull("-pkg", packageName)
|
||||
|
||||
addFileArgs("-h", headers)
|
||||
|
||||
compilerOpts.forEach {
|
||||
addArg("-copt", it)
|
||||
}
|
||||
|
||||
linkerOpts.forEach {
|
||||
addArg("-lopt", it)
|
||||
}
|
||||
|
||||
libraries.files.filter {
|
||||
// Support only klib files for now.
|
||||
it.extension == "klib" && !it.providedByCompiler(project)
|
||||
}.forEach { library ->
|
||||
library.parent?.let { addArg("-r", it) }
|
||||
addArg("-l", library.nameWithoutExtension)
|
||||
}
|
||||
|
||||
addArgs("-copt", allHeadersDirs.map { "-I${it.absolutePath}" })
|
||||
addArgs("-headerFilterAdditionalSearchPrefix", headerFilterDirs.map { it.absolutePath })
|
||||
|
||||
addAll(extraOpts)
|
||||
}
|
||||
|
||||
outputFile.parentFile.mkdirs()
|
||||
KonanInteropRunner(project).run(args)
|
||||
}
|
||||
}
|
||||
|
||||
open class KonanCompilerDownloadTask : DefaultTask() {
|
||||
|
||||
internal companion object {
|
||||
@@ -319,5 +429,4 @@ open class KonanCompilerDownloadTask : DefaultTask() {
|
||||
logger.info("Use Kotlin/Native distribution: $compilerDirectory")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user