[gradle-plugin] Support basic cinterop

This commit is contained in:
Ilya Matveev
2018-08-28 11:40:30 +07:00
committed by Ilya Matveev
parent 8092abc2b9
commit c012aa5d32
18 changed files with 552 additions and 32 deletions
@@ -0,0 +1,69 @@
/*
* Copyright 2010-2018 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.gradle.plugin.experimental
import groovy.lang.Closure
import org.gradle.api.Action
import org.gradle.api.Named
import org.gradle.api.file.FileCollection
import org.jetbrains.kotlin.konan.target.KonanTarget
interface CInteropSettings {
interface IncludeDirectories {
fun allHeaders(vararg includeDirs: Any)
fun allHeaders(includeDirs: Collection<Any>)
fun headerFilterOnly(vararg includeDirs: Any)
fun headerFilterOnly(includeDirs: Collection<Any>)
}
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>)
}
interface CInterop : Named, CInteropSettings {
fun target(target: String): CInteropSettings
fun target(target: KonanTarget): CInteropSettings
fun target(target: String, action: CInteropSettings.() -> Unit)
fun target(target: String, action: Closure<Unit>)
fun target(target: String, action: Action<CInteropSettings>)
fun target(target: KonanTarget, action: CInteropSettings.() -> Unit)
fun target(target: KonanTarget, action: Closure<Unit>)
fun target(target: KonanTarget, action: Action<CInteropSettings>)
}
@@ -16,22 +16,15 @@
package org.jetbrains.kotlin.gradle.plugin.experimental
import org.gradle.api.artifacts.Configuration
import org.gradle.api.attributes.Attribute
import org.gradle.api.attributes.AttributeContainer
import org.gradle.api.component.BuildableComponent
import org.gradle.api.component.PublishableComponent
import org.gradle.api.file.FileCollection
import org.gradle.api.file.RegularFile
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.gradle.language.ComponentWithDependencies
import org.gradle.language.ComponentWithOutputs
import org.gradle.language.nativeplatform.ComponentWithLinkUsage
import org.gradle.language.nativeplatform.internal.ComponentWithNames
import org.gradle.language.nativeplatform.internal.ConfigurableComponentWithLinkUsage
import org.gradle.language.nativeplatform.internal.ConfigurableComponentWithRuntimeUsage
import org.gradle.nativeplatform.Linkage
import org.gradle.nativeplatform.test.TestComponent
import org.jetbrains.kotlin.gradle.plugin.experimental.internal.KotlinNativePlatform
import org.jetbrains.kotlin.gradle.plugin.experimental.tasks.KotlinNativeCompile
@@ -16,18 +16,27 @@
package org.jetbrains.kotlin.gradle.plugin.experimental
import groovy.lang.Closure
import org.gradle.api.Action
import org.gradle.api.artifacts.Configuration
import org.gradle.api.provider.Provider
import org.gradle.api.provider.SetProperty
import org.gradle.api.publish.maven.MavenPom
import org.gradle.language.BinaryCollection
import org.gradle.language.ComponentDependencies
import org.gradle.language.ComponentWithBinaries
import org.gradle.language.ComponentWithDependencies
import org.gradle.nativeplatform.test.TestSuiteComponent
import org.jetbrains.kotlin.gradle.plugin.experimental.sourcesets.KotlinNativeSourceSet
import org.jetbrains.kotlin.konan.target.KonanTarget
interface KotlinNativeDependencies: ComponentDependencies {
fun cinterop(name: String): CInterop
fun cinterop(name: String, action: CInterop.() -> Unit)
fun cinterop(name: String, action: Closure<Unit>)
fun cinterop(name: String, action: Action<CInterop>)
}
/**
* Class representing a Kotlin/Native component: application or library (both klib and dynamic)
* built for different targets.
@@ -52,6 +61,13 @@ interface KotlinNativeComponent: ComponentWithBinaries, ComponentWithDependencie
// region DSL
/** Provides an access to component's dependencies including cinterop and jsinterop DSL */
override fun getDependencies(): KotlinNativeDependencies
fun dependencies(action: KotlinNativeDependencies.() -> Unit)
fun dependencies(action: Closure<Unit>)
fun dependencies(action: Action<KotlinNativeDependencies>)
/** Set native targets for this component. */
fun target(vararg targets: String)
@@ -37,7 +37,6 @@ import org.gradle.nativeplatform.OperatingSystemFamily
import org.gradle.nativeplatform.toolchain.NativeToolChain
import org.jetbrains.kotlin.gradle.plugin.experimental.ComponentWithBaseName
import org.jetbrains.kotlin.gradle.plugin.experimental.KotlinNativeBinary
import org.jetbrains.kotlin.gradle.plugin.experimental.KotlinNativeComponent
import org.jetbrains.kotlin.gradle.plugin.experimental.sourcesets.KotlinNativeSourceSet
import org.jetbrains.kotlin.gradle.plugin.experimental.tasks.KotlinNativeCompile
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
@@ -94,8 +93,8 @@ abstract class AbstractKotlinNativeBinary(
get() = sourceSet.getAllSources(konanTarget)
private val dependencies = objects.newInstance<DefaultComponentDependencies>(
DefaultComponentDependencies::class.java,
name + "Implementation"
DefaultComponentDependencies::class.java,
name + "Implementation"
).apply {
implementationDependencies.extendsFrom(componentImplementation)
}
@@ -16,7 +16,9 @@
package org.jetbrains.kotlin.gradle.plugin.experimental.internal
import groovy.lang.Closure
import org.gradle.api.Action
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.internal.file.FileOperations
import org.gradle.api.internal.provider.LockableSetProperty
@@ -24,20 +26,23 @@ import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.Property
import org.gradle.api.publish.maven.MavenPom
import org.gradle.language.internal.DefaultBinaryCollection
import org.gradle.language.internal.DefaultComponentDependencies
import org.gradle.language.nativeplatform.internal.ComponentWithNames
import org.gradle.language.nativeplatform.internal.DefaultNativeComponent
import org.gradle.language.nativeplatform.internal.Names
import org.gradle.util.ConfigureUtil
import org.jetbrains.kotlin.gradle.plugin.experimental.KotlinNativeBinary
import org.jetbrains.kotlin.gradle.plugin.experimental.KotlinNativeComponent
import org.jetbrains.kotlin.gradle.plugin.experimental.KotlinNativeDependencies
import org.jetbrains.kotlin.gradle.plugin.experimental.sourcesets.KotlinNativeSourceSetImpl
import org.jetbrains.kotlin.konan.target.HostManager
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
import javax.inject.Inject
abstract class AbstractKotlinNativeComponent @Inject constructor(
private val name: String,
override val sources: KotlinNativeSourceSetImpl,
val project: Project,
val objectFactory: ObjectFactory,
fileOperations: FileOperations
) : DefaultNativeComponent(fileOperations),
@@ -62,9 +67,10 @@ abstract class AbstractKotlinNativeComponent @Inject constructor(
private val names = Names.of(name)
override fun getNames(): Names = names
private val dependencies: DefaultComponentDependencies = objectFactory.newInstance(
DefaultComponentDependencies::class.java,
names.withSuffix("implementation"))
private val dependencies: KotlinNativeDependenciesImpl = objectFactory.newInstance(
KotlinNativeDependenciesImpl::class.java,
project,
names.withSuffix("implementation"))
internal val poms = mutableListOf<Action<MavenPom>>()
override fun getDependencies() = dependencies
@@ -92,5 +98,16 @@ abstract class AbstractKotlinNativeComponent @Inject constructor(
override var publishJavadoc: Boolean = true
override var publishSources: Boolean = true
override fun dependencies(action: KotlinNativeDependencies.() -> Unit) {
dependencies.action()
}
override fun dependencies(action: Closure<Unit>) =
dependencies(ConfigureUtil.configureUsing(action))
override fun dependencies(action: Action<KotlinNativeDependencies>) {
action.execute(dependencies)
}
// endregion
}
@@ -0,0 +1,54 @@
/*
* Copyright 2010-2018 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.gradle.plugin.experimental.internal
import groovy.lang.Closure
import org.gradle.api.Action
import org.gradle.api.Project
import org.gradle.api.artifacts.ConfigurationContainer
import org.gradle.language.internal.DefaultComponentDependencies
import org.gradle.util.ConfigureUtil
import org.jetbrains.kotlin.gradle.plugin.experimental.CInterop
import org.jetbrains.kotlin.gradle.plugin.experimental.KotlinNativeDependencies
import org.jetbrains.kotlin.gradle.plugin.experimental.internal.cinterop.CInteropImpl
import javax.inject.Inject
open class KotlinNativeDependenciesImpl @Inject constructor(
private val project: Project,
configurations: ConfigurationContainer,
implementationName: String
) : DefaultComponentDependencies(configurations, implementationName),
KotlinNativeDependencies {
internal val cinterops = project.container(CInteropImpl::class.java) { name ->
CInteropImpl(project, name)
}
override fun cinterop(name: String) = cinterops.maybeCreate(name)
override fun cinterop(name: String, action: CInterop.() -> Unit) {
cinterop(name).apply { action() }
}
override fun cinterop(name: String, action: Closure<Unit>) {
cinterop(name, ConfigureUtil.configureUsing(action))
}
override fun cinterop(name: String, action: Action<CInterop>) {
cinterop(name).apply { action.execute(this) }
}
}
@@ -32,7 +32,6 @@ import org.gradle.api.provider.Provider
import org.gradle.language.cpp.internal.DefaultUsageContext
import org.gradle.nativeplatform.Linkage
import org.jetbrains.kotlin.gradle.plugin.experimental.KotlinNativeExecutable
import org.jetbrains.kotlin.gradle.plugin.experimental.sourcesets.KotlinNativeSourceSet
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import javax.inject.Inject
@@ -31,7 +31,6 @@ import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.gradle.language.cpp.internal.DefaultUsageContext
import org.gradle.nativeplatform.Linkage
import org.jetbrains.kotlin.gradle.plugin.experimental.KotlinNativeFramework
import org.jetbrains.kotlin.gradle.plugin.experimental.KotlinNativeLibrary
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import javax.inject.Inject
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.gradle.plugin.experimental.internal
import org.gradle.api.Project
import org.gradle.api.component.ComponentWithVariants
import org.gradle.api.component.SoftwareComponent
import org.gradle.api.internal.component.SoftwareComponentInternal
@@ -36,9 +37,10 @@ import javax.inject.Inject
open class KotlinNativeMainComponent @Inject constructor(
name: String,
sources: KotlinNativeSourceSetImpl,
project: Project,
objectFactory: ObjectFactory,
fileOperations: FileOperations
) : AbstractKotlinNativeComponent(name, sources, objectFactory, fileOperations),
) : AbstractKotlinNativeComponent(name, sources, project, objectFactory, fileOperations),
PublicationAwareComponent,
ProductionComponent {
@@ -25,7 +25,6 @@ import org.gradle.api.internal.file.FileOperations
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.jetbrains.kotlin.gradle.plugin.experimental.KotlinNativeTestComponent
import org.jetbrains.kotlin.gradle.plugin.experimental.KotlinNativeTestExecutable
import org.jetbrains.kotlin.gradle.plugin.experimental.sourcesets.KotlinNativeSourceSet
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.gradle.plugin.experimental.internal
import org.gradle.api.Project
import org.gradle.api.internal.file.FileOperations
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.Property
@@ -29,12 +30,13 @@ import org.jetbrains.kotlin.gradle.plugin.experimental.sourcesets.KotlinNativeSo
import javax.inject.Inject
open class KotlinNativeTestSuite @Inject constructor(
name: String,
sources: KotlinNativeSourceSetImpl,
override val testedComponent: KotlinNativeComponent,
objectFactory: ObjectFactory,
fileOperations: FileOperations
) : AbstractKotlinNativeComponent(name, sources, objectFactory, fileOperations),
name: String,
sources: KotlinNativeSourceSetImpl,
override val testedComponent: KotlinNativeComponent,
project: Project,
objectFactory: ObjectFactory,
fileOperations: FileOperations
) : AbstractKotlinNativeComponent(name, sources, project, objectFactory, fileOperations),
KotlinNativeTestComponent {
init {
@@ -0,0 +1,96 @@
/*
* Copyright 2010-2018 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.gradle.plugin.experimental.internal.cinterop
import groovy.lang.Closure
import org.gradle.api.Action
import org.gradle.api.DomainObjectCollection
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
import org.gradle.api.file.FileCollection
import org.gradle.util.ConfigureUtil
import org.jetbrains.kotlin.gradle.plugin.experimental.CInterop
import org.jetbrains.kotlin.gradle.plugin.experimental.CInteropSettings
import org.jetbrains.kotlin.gradle.plugin.experimental.CInteropSettings.IncludeDirectories
import org.jetbrains.kotlin.konan.target.HostManager
import org.jetbrains.kotlin.konan.target.KonanTarget
import javax.inject.Inject
open class CInteropImpl @Inject constructor(
private val project: Project,
private val name: String
): CInterop {
private val String.konanTarget: KonanTarget
get() = HostManager().targetByName(this)
override fun getName(): String = name
private val platformSettings: DomainObjectCollection<CInteropSettingsImpl> =
project.container(CInteropSettingsImpl::class.java)
private val targetToSettings: MutableMap<KonanTarget, CInteropSettingsImpl> = mutableMapOf()
// DSL.
override fun target(target: String): CInteropSettings = target(target.konanTarget)
override fun target(target: KonanTarget): CInteropSettings =
targetToSettings.getOrPut(target) {
CInteropSettingsImpl(project, name, target).also {
platformSettings.add(it)
}
}
override fun target(target: String, action: CInteropSettings.() -> Unit) = target(target.konanTarget, action)
override fun target(target: String, action: Closure<Unit>) = target(target.konanTarget, action)
override fun target(target: String, action: Action<CInteropSettings>) = target(target.konanTarget, action)
override fun target(target: KonanTarget, action: CInteropSettings.() -> Unit) =
target(target).action()
override fun target(target: KonanTarget, action: Closure<Unit>) =
target(target, ConfigureUtil.configureUsing(action))
override fun target(target: KonanTarget, action: Action<CInteropSettings>) {
action.execute(target(target))
}
override fun defFile(file: Any) = platformSettings.all { it.defFile(file) }
override fun packageName(value: String) = platformSettings.all { it.packageName(value) }
override fun headers(vararg files: Any) = platformSettings.all { it.headers(*files) }
override fun headers(files: FileCollection) = platformSettings.all { it.headers(files) }
override fun includeDirs(vararg values: Any) =
platformSettings.all {it.includeDirs(*values) }
override fun includeDirs(closure: Closure<Unit>) =
platformSettings.all { it.includeDirs(closure) }
override fun includeDirs(action: Action<IncludeDirectories>) =
platformSettings.all { it.includeDirs(action) }
override fun includeDirs(configure: IncludeDirectories.() -> Unit) =
platformSettings.all { it.includeDirs(configure) }
override fun compilerOpts(vararg values: String) = platformSettings.all { it.compilerOpts(*values) }
override fun compilerOpts(values: List<String>) = platformSettings.all { it.compilerOpts(values) }
override fun linkerOpts(vararg values: String) = platformSettings.all { it.linkerOpts(*values) }
override fun linkerOpts(values: List<String>) = platformSettings.all { it.linkerOpts(values) }
override fun extraOpts(vararg values: Any) = platformSettings.all { it.extraOpts(*values) }
override fun extraOpts(values: List<Any>) = platformSettings.all { it.extraOpts(values) }
}
@@ -0,0 +1,100 @@
/*
* Copyright 2010-2018 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.gradle.plugin.experimental.internal.cinterop
import groovy.lang.Closure
import org.gradle.api.Action
import org.gradle.api.Named
import org.gradle.api.Project
import org.gradle.api.file.FileCollection
import org.gradle.util.ConfigureUtil
import org.jetbrains.kotlin.gradle.plugin.experimental.CInteropSettings
import org.jetbrains.kotlin.gradle.plugin.experimental.CInteropSettings.IncludeDirectories
import org.jetbrains.kotlin.konan.target.KonanTarget
import java.io.File
import javax.inject.Inject
open class CInteropSettingsImpl @Inject constructor(
private val project: Project,
val baseName: String,
val konanTarget: KonanTarget
) : CInteropSettings,
Named
{
inner class IncludeDirectoriesSpecImpl: 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 = "$baseName${konanTarget.name.capitalize()}"
var defFile: File = project.projectDir.resolve("src/main/c_interop/$baseName.def")
var packageName: String? = null
val compilerOpts = mutableListOf<String>()
val linkerOpts = mutableListOf<String>()
val extraOpts = mutableListOf<String>()
val includeDirs = IncludeDirectoriesSpecImpl()
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() })
}
}
@@ -20,23 +20,21 @@ import org.gradle.api.DefaultTask
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.component.SoftwareComponentContainer
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.RegularFile
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.internal.FeaturePreviews
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.api.plugins.BasePlugin
import org.gradle.api.plugins.HelpTasksPlugin
import org.gradle.api.provider.Provider
import org.gradle.api.provider.ProviderFactory
import org.gradle.api.tasks.TaskContainer
import org.gradle.language.base.plugins.LifecycleBasePlugin
import org.gradle.language.plugins.NativeBasePlugin
import org.gradle.nativeplatform.test.tasks.RunTestExecutable
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.plugin.KonanPlugin
import org.jetbrains.kotlin.gradle.plugin.experimental.CInteropSettings
import org.jetbrains.kotlin.gradle.plugin.experimental.internal.*
import org.jetbrains.kotlin.gradle.plugin.experimental.internal.cinterop.CInteropSettingsImpl
import org.jetbrains.kotlin.gradle.plugin.experimental.tasks.CInteropTask
import org.jetbrains.kotlin.gradle.plugin.experimental.tasks.KotlinNativeCompile
import org.jetbrains.kotlin.gradle.plugin.hasProperty
import org.jetbrains.kotlin.gradle.plugin.konanCompilerDownloadDir
@@ -45,7 +43,6 @@ import org.jetbrains.kotlin.gradle.plugin.tasks.KonanCompilerDownloadTask
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.konan.target.HostManager
import org.jetbrains.kotlin.konan.target.KonanTarget
import java.io.File
class KotlinNativeBasePlugin: Plugin<ProjectInternal> {
@@ -83,6 +80,18 @@ class KotlinNativeBasePlugin: Plugin<ProjectInternal> {
private val KonanTarget.canRunOnHost: Boolean
get() = this == HostManager.host
private fun lowerCamelCase(vararg components: String) =
if (components.isEmpty()) {
""
} else {
buildString {
append(components[0].decapitalize())
for (i in 1 until components.size) {
append(components[i].capitalize())
}
}
}
private fun Project.addTargetInfoTask() = tasks.create("targets").apply {
group = HelpTasksPlugin.HELP_GROUP
description = "Prints Kotlin/Native targets available for this project"
@@ -174,6 +183,31 @@ class KotlinNativeBasePlugin: Plugin<ProjectInternal> {
}
}
private fun Project.addInteropTasks() {
val settingsToTask = mutableMapOf<CInteropSettings, CInteropTask>()
components.withType(AbstractKotlinNativeBinary::class.java) { binary ->
binary.component.dependencies.cinterops.all { cinterop ->
val konanTarget = binary.konanTarget
val settings = cinterop.target(konanTarget)
val interopTask = settingsToTask.getOrPut(settings) {
tasks.create(
lowerCamelCase("cinterop", cinterop.name, konanTarget.name),
CInteropTask::class.java,
settings
).apply {
group = INTEROP_GROUP
description = "Generates Kotlin/Native interop library '${cinterop.name}' for target '${konanTarget.name}'"
}
}
binary.klibraries.dependencies.add(dependencies.create(files(interopTask.outputFileProvider)))
}
}
}
private fun ProjectInternal.checkGradleMetadataFeature() {
val metadataEnabled = gradle.services
.get(FeaturePreviews::class.java)
@@ -213,12 +247,15 @@ class KotlinNativeBasePlugin: Plugin<ProjectInternal> {
addCompilerDownloadingTask()
addCompilationTasks()
addInteropTasks()
addTargetInfoTask()
}
companion object {
const val LANGUAGE_NAME = "KotlinNative"
const val SOURCE_SETS_EXTENSION = "sourceSets"
const val INTEROP_GROUP = "interop"
}
}
@@ -265,7 +265,7 @@ class KotlinNativePlugin @Inject constructor(val attributesFactory: ImmutableAtt
val mainSourceSet = sourceSets.create(MAIN_SOURCE_SET_NAME).apply {
kotlin.srcDir("src/$MAIN_SOURCE_SET_NAME/kotlin")
component = objectFactory
.newInstance(KotlinNativeMainComponent::class.java, name, this)
.newInstance(KotlinNativeMainComponent::class.java, name, this, project)
.apply {
// Override the default component base name.
baseName.set(project.name)
@@ -276,7 +276,7 @@ class KotlinNativePlugin @Inject constructor(val attributesFactory: ImmutableAtt
sourceSets.create(TEST_SOURCE_SET_NAME).apply {
kotlin.srcDir("src/$TEST_SOURCE_SET_NAME/kotlin")
component = objectFactory
.newInstance(KotlinNativeTestSuite::class.java, name, this, mainSourceSet.component)
.newInstance(KotlinNativeTestSuite::class.java, name, this, mainSourceSet.component, project)
.apply {
project.components.add(this)
}
@@ -22,6 +22,7 @@ import org.gradle.api.Named
import org.gradle.api.file.FileCollection
import org.gradle.api.file.SourceDirectorySet
import org.jetbrains.kotlin.gradle.plugin.experimental.KotlinNativeComponent
import org.jetbrains.kotlin.gradle.plugin.experimental.KotlinNativeDependencies
import org.jetbrains.kotlin.gradle.plugin.experimental.internal.AbstractKotlinNativeComponent
import org.jetbrains.kotlin.konan.target.KonanTarget
@@ -59,4 +60,10 @@ interface KotlinNativeSourceSet: Named {
fun target(targets: Iterable<String>, configureClosure: Closure<*>): KotlinNativeSourceSet
fun target(targets: Iterable<String>, configureAction: Action<in SourceDirectorySet>): KotlinNativeSourceSet
fun target(targets: Iterable<String>, configureLambda: SourceDirectorySet.() -> Unit): KotlinNativeSourceSet
val dependencies: KotlinNativeDependencies
fun dependencies(action: KotlinNativeDependencies.() -> Unit)
fun dependencies(action: Closure<Unit>)
fun dependencies(action: Action<KotlinNativeDependencies>)
}
@@ -24,6 +24,7 @@ import org.gradle.api.file.SourceDirectorySet
import org.gradle.api.internal.file.SourceDirectorySetFactory
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.util.ConfigureUtil.configure
import org.jetbrains.kotlin.gradle.plugin.experimental.KotlinNativeDependencies
import org.jetbrains.kotlin.gradle.plugin.experimental.internal.AbstractKotlinNativeComponent
import org.jetbrains.kotlin.konan.target.HostManager
import org.jetbrains.kotlin.konan.target.KonanTarget
@@ -105,5 +106,13 @@ open class KotlinNativeSourceSetImpl @Inject constructor(
override fun target(vararg targets: String, configureAction: Action<in SourceDirectorySet>) =
target(targets.toList(), configureAction)
override val dependencies: KotlinNativeDependencies
get() = component.dependencies
override fun dependencies(action: KotlinNativeDependencies.() -> Unit) = component.dependencies(action)
override fun dependencies(action: Closure<Unit>) = component.dependencies(action)
override fun dependencies(action: Action<KotlinNativeDependencies>) = component.dependencies(action)
// endregion
}
@@ -0,0 +1,122 @@
/*
* Copyright 2010-2018 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.gradle.plugin.experimental.tasks
import org.gradle.api.DefaultTask
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.*
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.experimental.internal.cinterop.CInteropSettingsImpl
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.konan.target.KonanTarget
import java.io.File
import javax.inject.Inject
open class CInteropTask @Inject constructor(val settings: CInteropSettingsImpl): DefaultTask() {
val konanTarget: KonanTarget
@Internal get() = settings.konanTarget
val outputFileName: String
@Internal get() = with(CompilerOutputKind.LIBRARY) {
val prefix = prefix(konanTarget)
val suffix = suffix(konanTarget)
return "$prefix$baseName$suffix"
}
val outputFile: File
get() = outputFileProvider.get().asFile
// Inputs and outputs.
@OutputFile
val outputFileProvider = newOutputFile().apply {
set { project.buildDir.resolve("cinterop/$baseName/$targetName/$outputFileName") }
}
val baseName: String
@Input get() = settings.baseName
val targetName: String
@Input get() = konanTarget.name
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 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)
}
addArgs("-copt", allHeadersDirs.map { "-I${it.absolutePath}" })
addArgs("-headerFilterAdditionalSearchPrefix", headerFilterDirs.map { it.absolutePath })
/* TODO: Support dependencies
addArgs("-repo", libraries.repos.map { it.canonicalPath })
addFileArgs("-library", libraries.files)
addArgs("-library", libraries.namedKlibs)
addArgs("-library", libraries.artifacts.map { it.artifact.canonicalPath })
addKey("-nodefaultlibs", noDefaultLibs)
*/
addAll(extraOpts)
}
outputFile.parentFile.mkdirs()
KonanInteropRunner(project).run(args)
}
}