diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/CInterop.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/CInterop.kt new file mode 100644 index 00000000000..d39cc76f180 --- /dev/null +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/CInterop.kt @@ -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) + + fun headerFilterOnly(vararg includeDirs: Any) + fun headerFilterOnly(includeDirs: Collection) + } + + 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) + fun includeDirs(action: Action) + fun includeDirs(configure: IncludeDirectories.() -> Unit) + + fun compilerOpts(vararg values: String) + fun compilerOpts(values: List) + + fun linkerOpts(vararg values: String) + fun linkerOpts(values: List) + + fun extraOpts(vararg values: Any) + fun extraOpts(values: List) +} + +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) + fun target(target: String, action: Action) + + fun target(target: KonanTarget, action: CInteropSettings.() -> Unit) + fun target(target: KonanTarget, action: Closure) + fun target(target: KonanTarget, action: Action) +} \ No newline at end of file diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/KotlinNativeBinaries.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/KotlinNativeBinaries.kt index 6cae25ffbeb..ce0e8ebb433 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/KotlinNativeBinaries.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/KotlinNativeBinaries.kt @@ -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 diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/KotlinNativeComponent.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/KotlinNativeComponent.kt index 9a99182c10a..3f489eacc94 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/KotlinNativeComponent.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/KotlinNativeComponent.kt @@ -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) + fun cinterop(name: String, action: Action) +} + /** * 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) + fun dependencies(action: Action) + /** Set native targets for this component. */ fun target(vararg targets: String) diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/AbstractKotlinNativeBinary.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/AbstractKotlinNativeBinary.kt index 32828330c6e..0b34401b1e7 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/AbstractKotlinNativeBinary.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/AbstractKotlinNativeBinary.kt @@ -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::class.java, - name + "Implementation" + DefaultComponentDependencies::class.java, + name + "Implementation" ).apply { implementationDependencies.extendsFrom(componentImplementation) } diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/AbstractKotlinNativeComponent.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/AbstractKotlinNativeComponent.kt index d97d3b764e4..ed329c44e08 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/AbstractKotlinNativeComponent.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/AbstractKotlinNativeComponent.kt @@ -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>() 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) = + dependencies(ConfigureUtil.configureUsing(action)) + + override fun dependencies(action: Action) { + action.execute(dependencies) + } + // endregion } \ No newline at end of file diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeDependenciesImpl.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeDependenciesImpl.kt new file mode 100644 index 00000000000..b8199fdfb08 --- /dev/null +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeDependenciesImpl.kt @@ -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) { + cinterop(name, ConfigureUtil.configureUsing(action)) + } + + override fun cinterop(name: String, action: Action) { + cinterop(name).apply { action.execute(this) } + } +} \ No newline at end of file diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeExecutableImpl.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeExecutableImpl.kt index 8777e86129d..9799ae123a7 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeExecutableImpl.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeExecutableImpl.kt @@ -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 diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeLibraryImpl.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeLibraryImpl.kt index e76a2d5dd6a..560158d17d4 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeLibraryImpl.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeLibraryImpl.kt @@ -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 diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeMainComponent.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeMainComponent.kt index 39c53e7ee6b..6d789bd989f 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeMainComponent.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeMainComponent.kt @@ -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 { diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeTestExecutableImpl.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeTestExecutableImpl.kt index 46967e30480..06e377f18ca 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeTestExecutableImpl.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeTestExecutableImpl.kt @@ -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 diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeTestSuite.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeTestSuite.kt index 6576772f245..b7f9967bcd1 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeTestSuite.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeTestSuite.kt @@ -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 { diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/cinterop/CInteropImpl.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/cinterop/CInteropImpl.kt new file mode 100644 index 00000000000..a51a9cdee1e --- /dev/null +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/cinterop/CInteropImpl.kt @@ -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 = + project.container(CInteropSettingsImpl::class.java) + + private val targetToSettings: MutableMap = 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) = target(target.konanTarget, action) + override fun target(target: String, action: Action) = target(target.konanTarget, action) + + override fun target(target: KonanTarget, action: CInteropSettings.() -> Unit) = + target(target).action() + + override fun target(target: KonanTarget, action: Closure) = + target(target, ConfigureUtil.configureUsing(action)) + + override fun target(target: KonanTarget, action: Action) { + 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) = + platformSettings.all { it.includeDirs(closure) } + override fun includeDirs(action: Action) = + 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) = platformSettings.all { it.compilerOpts(values) } + + override fun linkerOpts(vararg values: String) = platformSettings.all { it.linkerOpts(*values) } + override fun linkerOpts(values: List) = platformSettings.all { it.linkerOpts(values) } + + override fun extraOpts(vararg values: Any) = platformSettings.all { it.extraOpts(*values) } + override fun extraOpts(values: List) = platformSettings.all { it.extraOpts(values) } +} \ No newline at end of file diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/cinterop/CInteropSettingsImpl.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/cinterop/CInteropSettingsImpl.kt new file mode 100644 index 00000000000..826f78a7cb4 --- /dev/null +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/cinterop/CInteropSettingsImpl.kt @@ -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) { + allHeadersDirs += project.files(*includeDirs.toTypedArray()) + } + + override fun headerFilterOnly(vararg includeDirs: Any) = headerFilterOnly(includeDirs.toList()) + override fun headerFilterOnly(includeDirs: Collection) { + 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() + val linkerOpts = mutableListOf() + val extraOpts = mutableListOf() + + 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) = includeDirs(ConfigureUtil.configureUsing(closure)) + override fun includeDirs(action: Action) = 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) { + compilerOpts.addAll(values) + } + + override fun linkerOpts(vararg values: String) = linkerOpts(values.toList()) + override fun linkerOpts(values: List) { + linkerOpts.addAll(values) + } + + override fun extraOpts(vararg values: Any) = extraOpts(values.toList()) + override fun extraOpts(values: List) { + extraOpts.addAll(values.map { it.toString() }) + } +} \ No newline at end of file diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/plugins/KotlinNativeBasePlugin.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/plugins/KotlinNativeBasePlugin.kt index e14ba821b77..dc5f136b6f9 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/plugins/KotlinNativeBasePlugin.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/plugins/KotlinNativeBasePlugin.kt @@ -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 { @@ -83,6 +80,18 @@ class KotlinNativeBasePlugin: Plugin { 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 { } } + private fun Project.addInteropTasks() { + + val settingsToTask = mutableMapOf() + + 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 { addCompilerDownloadingTask() addCompilationTasks() + addInteropTasks() addTargetInfoTask() } companion object { const val LANGUAGE_NAME = "KotlinNative" const val SOURCE_SETS_EXTENSION = "sourceSets" + + const val INTEROP_GROUP = "interop" } } diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/plugins/KotlinNativePlugin.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/plugins/KotlinNativePlugin.kt index 0689c047806..c1886d26cf3 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/plugins/KotlinNativePlugin.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/plugins/KotlinNativePlugin.kt @@ -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) } diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/sourcesets/KotlinNativeSourceSet.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/sourcesets/KotlinNativeSourceSet.kt index 368c12ff4cd..714f479b454 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/sourcesets/KotlinNativeSourceSet.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/sourcesets/KotlinNativeSourceSet.kt @@ -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, configureClosure: Closure<*>): KotlinNativeSourceSet fun target(targets: Iterable, configureAction: Action): KotlinNativeSourceSet fun target(targets: Iterable, configureLambda: SourceDirectorySet.() -> Unit): KotlinNativeSourceSet + + val dependencies: KotlinNativeDependencies + + fun dependencies(action: KotlinNativeDependencies.() -> Unit) + fun dependencies(action: Closure) + fun dependencies(action: Action) } diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/sourcesets/KotlinNativeSourceSetImpl.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/sourcesets/KotlinNativeSourceSetImpl.kt index c509d703651..d1a406f3b2e 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/sourcesets/KotlinNativeSourceSetImpl.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/sourcesets/KotlinNativeSourceSetImpl.kt @@ -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) = 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) = component.dependencies(action) + override fun dependencies(action: Action) = component.dependencies(action) + // endregion } \ No newline at end of file diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/tasks/CInteropTask.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/tasks/CInteropTask.kt new file mode 100644 index 00000000000..80c92c77308 --- /dev/null +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/tasks/CInteropTask.kt @@ -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 + @Input get() = settings.compilerOpts + + val linkerOpts: List + @Input get() = settings.linkerOpts + + val headers: FileCollection + @InputFiles get() = settings.headers + + val allHeadersDirs: Set + @Input get() = settings.includeDirs.allHeadersDirs.files + + val headerFilterDirs: Set + @Input get() = settings.includeDirs.headerFilterDirs.files + + val extraOpts: List + @Input get() = settings.extraOpts + + + // Task action. + @TaskAction + fun processInterop() { + val args = mutableListOf().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) + } + +} \ No newline at end of file