Support the -Xexport-library option in the K/N Gradle plugin
This commit is contained in:
committed by
Ilya Matveev
parent
b7d5452c1d
commit
1ef76cf289
+6
-1
@@ -107,7 +107,12 @@ interface KotlinNativeLibrary : KotlinNativeBinary,
|
||||
/**
|
||||
* Represents an Objective C framework compiled from Kotlin/Native sources.
|
||||
*/
|
||||
interface KotlinNativeFramework : KotlinNativeBinary
|
||||
interface KotlinNativeFramework : KotlinNativeBinary {
|
||||
/**
|
||||
* Klibs exported in the framework.
|
||||
*/
|
||||
val export: FileCollection
|
||||
}
|
||||
|
||||
/**
|
||||
* A shared library compiled from Kotlin/Native sources.
|
||||
|
||||
+7
@@ -20,6 +20,7 @@ import groovy.lang.Closure
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.NamedDomainObjectContainer
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.Dependency
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.provider.SetProperty
|
||||
import org.gradle.api.publish.maven.MavenPom
|
||||
@@ -37,6 +38,12 @@ interface KotlinNativeDependencies: ComponentDependencies {
|
||||
fun cinterop(name: String, action: CInterop.() -> Unit)
|
||||
fun cinterop(name: String, action: Closure<Unit>)
|
||||
fun cinterop(name: String, action: Action<CInterop>)
|
||||
|
||||
fun export(notation: Any)
|
||||
fun export(notation: Any, configure: Closure<*>)
|
||||
fun export(notation: Any, configure: Action<in Dependency>)
|
||||
|
||||
var transitiveExport: Boolean
|
||||
}
|
||||
|
||||
interface TargetSettings {
|
||||
|
||||
+2
-2
@@ -64,7 +64,7 @@ abstract class AbstractKotlinNativeBinary(
|
||||
val projectLayout: ProjectLayout,
|
||||
override val kind: CompilerOutputKind,
|
||||
objects: ObjectFactory,
|
||||
componentImplementation: Configuration,
|
||||
componentDependencies: KotlinNativeDependenciesImpl,
|
||||
configurations: ConfigurationContainer,
|
||||
val fileOperations: FileOperations
|
||||
) : KotlinNativeBinary,
|
||||
@@ -101,7 +101,7 @@ abstract class AbstractKotlinNativeBinary(
|
||||
DefaultComponentDependencies::class.java,
|
||||
name + "Implementation"
|
||||
).apply {
|
||||
implementationDependencies.extendsFrom(componentImplementation)
|
||||
implementationDependencies.extendsFrom(componentDependencies.implementationDependencies)
|
||||
}
|
||||
|
||||
override fun getDependencies(): ComponentDependencies = dependencies
|
||||
|
||||
+3
-1
@@ -80,7 +80,9 @@ abstract class AbstractKotlinNativeComponent @Inject constructor(
|
||||
private val dependencies: KotlinNativeDependenciesImpl = objectFactory.newInstance(
|
||||
KotlinNativeDependenciesImpl::class.java,
|
||||
project,
|
||||
names.withSuffix("implementation"))
|
||||
names.withSuffix("implementation"),
|
||||
names.withSuffix("export")
|
||||
)
|
||||
internal val poms = mutableListOf<Action<MavenPom>>()
|
||||
|
||||
override fun getDependencies() = dependencies
|
||||
|
||||
+32
-1
@@ -20,6 +20,7 @@ import groovy.lang.Closure
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.ConfigurationContainer
|
||||
import org.gradle.api.artifacts.Dependency
|
||||
import org.gradle.language.internal.DefaultComponentDependencies
|
||||
import org.gradle.util.ConfigureUtil
|
||||
import org.jetbrains.kotlin.gradle.plugin.experimental.CInterop
|
||||
@@ -30,10 +31,40 @@ import javax.inject.Inject
|
||||
open class KotlinNativeDependenciesImpl @Inject constructor(
|
||||
private val project: Project,
|
||||
configurations: ConfigurationContainer,
|
||||
implementationName: String
|
||||
implementationName: String,
|
||||
exportName: String
|
||||
) : DefaultComponentDependencies(configurations, implementationName),
|
||||
KotlinNativeDependencies {
|
||||
|
||||
internal val exportDependencies = configurations.create(exportName).apply {
|
||||
isCanBeConsumed = false
|
||||
isCanBeResolved = false
|
||||
isTransitive = false
|
||||
implementationDependencies.extendsFrom(this)
|
||||
}
|
||||
|
||||
override var transitiveExport: Boolean
|
||||
get() = exportDependencies.isTransitive
|
||||
set(value) {
|
||||
exportDependencies.isTransitive = value
|
||||
}
|
||||
|
||||
override fun export(notation: Any) {
|
||||
exportDependencies.dependencies.add(dependencyHandler.create(notation))
|
||||
}
|
||||
|
||||
override fun export(notation: Any, configure: Closure<*>) {
|
||||
val dependency = dependencyHandler.create(notation)
|
||||
ConfigureUtil.configure(configure, dependency)
|
||||
exportDependencies.dependencies.add(dependency)
|
||||
}
|
||||
|
||||
override fun export(notation: Any, configure: Action<in Dependency>) {
|
||||
val dependency = dependencyHandler.create(notation)
|
||||
configure.execute(dependency)
|
||||
exportDependencies.dependencies.add(dependency)
|
||||
}
|
||||
|
||||
override val cinterops = project.container(CInteropImpl::class.java) { name ->
|
||||
CInteropImpl(project, name).apply {
|
||||
dependencies.implementationDependencies.extendsFrom(
|
||||
|
||||
+2
-2
@@ -29,7 +29,7 @@ import javax.inject.Inject
|
||||
open class KotlinNativeDynamicImpl @Inject constructor(
|
||||
name: String,
|
||||
baseName: Provider<String>,
|
||||
componentImplementation: Configuration,
|
||||
componentDependencies: KotlinNativeDependenciesImpl,
|
||||
component: KotlinNativeMainComponent,
|
||||
identity: KotlinNativeVariantIdentity,
|
||||
projectLayout: ProjectLayout,
|
||||
@@ -44,7 +44,7 @@ open class KotlinNativeDynamicImpl @Inject constructor(
|
||||
projectLayout,
|
||||
CompilerOutputKind.DYNAMIC,
|
||||
objects,
|
||||
componentImplementation,
|
||||
componentDependencies,
|
||||
configurations,
|
||||
fileOperations
|
||||
), KotlinNativeDynamic {
|
||||
|
||||
+2
-2
@@ -38,7 +38,7 @@ import javax.inject.Inject
|
||||
open class KotlinNativeExecutableImpl @Inject constructor(
|
||||
name: String,
|
||||
baseName: Provider<String>,
|
||||
componentImplementation: Configuration,
|
||||
componentDependencies: KotlinNativeDependenciesImpl,
|
||||
component: KotlinNativeMainComponent,
|
||||
identity: KotlinNativeVariantIdentity,
|
||||
objects: ObjectFactory,
|
||||
@@ -52,7 +52,7 @@ open class KotlinNativeExecutableImpl @Inject constructor(
|
||||
projectLayout,
|
||||
CompilerOutputKind.PROGRAM,
|
||||
objects,
|
||||
componentImplementation,
|
||||
componentDependencies,
|
||||
configurations,
|
||||
fileOperations),
|
||||
KotlinNativeExecutable,
|
||||
|
||||
+22
-3
@@ -16,13 +16,18 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.experimental.internal
|
||||
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ConfigurationContainer
|
||||
import org.gradle.api.attributes.Usage
|
||||
import org.gradle.api.file.ProjectLayout
|
||||
import org.gradle.api.internal.file.FileOperations
|
||||
import org.gradle.api.model.ObjectFactory
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.language.cpp.CppBinary
|
||||
import org.gradle.nativeplatform.OperatingSystemFamily
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||
import org.jetbrains.kotlin.gradle.plugin.experimental.KotlinNativeBinary
|
||||
import org.jetbrains.kotlin.gradle.plugin.experimental.KotlinNativeFramework
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -30,7 +35,7 @@ import javax.inject.Inject
|
||||
open class KotlinNativeFrameworkImpl @Inject constructor(
|
||||
name: String,
|
||||
baseName: Provider<String>,
|
||||
componentImplementation: Configuration,
|
||||
componentDependencies: KotlinNativeDependenciesImpl,
|
||||
component: KotlinNativeMainComponent,
|
||||
identity: KotlinNativeVariantIdentity,
|
||||
projectLayout: ProjectLayout,
|
||||
@@ -45,9 +50,23 @@ open class KotlinNativeFrameworkImpl @Inject constructor(
|
||||
projectLayout,
|
||||
CompilerOutputKind.FRAMEWORK,
|
||||
objects,
|
||||
componentImplementation,
|
||||
componentDependencies,
|
||||
configurations,
|
||||
fileOperations
|
||||
), KotlinNativeFramework {
|
||||
override val outputRootName: String = "lib"
|
||||
|
||||
// A configuration containing exported klibs.
|
||||
override val export = configurations.create(names.withPrefix("export")).apply {
|
||||
isCanBeConsumed = false
|
||||
attributes.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage::class.java, KotlinUsages.KOTLIN_API))
|
||||
attributes.attribute(CppBinary.DEBUGGABLE_ATTRIBUTE, debuggable)
|
||||
attributes.attribute(CppBinary.OPTIMIZED_ATTRIBUTE, optimized)
|
||||
attributes.attribute(KotlinPlatformType.attribute, KotlinPlatformType.native)
|
||||
attributes.attribute(KotlinNativeBinary.KONAN_TARGET_ATTRIBUTE, konanTarget.name)
|
||||
attributes.attribute(KotlinNativeBinary.OLD_KONAN_TARGET_ATTRIBUTE, konanTarget.name)
|
||||
attributes.attribute(OperatingSystemFamily.OPERATING_SYSTEM_ATTRIBUTE, konanTarget.getGradleOSFamily(objects))
|
||||
extendsFrom(componentDependencies.exportDependencies)
|
||||
getImplementationDependencies().extendsFrom(this)
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -38,7 +38,7 @@ import javax.inject.Inject
|
||||
open class KotlinNativeLibraryImpl @Inject constructor(
|
||||
name: String,
|
||||
baseName: Provider<String>,
|
||||
componentImplementation: Configuration,
|
||||
componentDependencies: KotlinNativeDependenciesImpl,
|
||||
component: KotlinNativeMainComponent,
|
||||
identity: KotlinNativeVariantIdentity,
|
||||
projectLayout: ProjectLayout,
|
||||
@@ -52,7 +52,7 @@ open class KotlinNativeLibraryImpl @Inject constructor(
|
||||
projectLayout,
|
||||
CompilerOutputKind.LIBRARY,
|
||||
objects,
|
||||
componentImplementation,
|
||||
componentDependencies,
|
||||
configurations,
|
||||
fileOperations),
|
||||
KotlinNativeLibrary,
|
||||
|
||||
+1
-1
@@ -75,7 +75,7 @@ open class KotlinNativeMainComponent @Inject constructor(
|
||||
type,
|
||||
"$name${identity.name.capitalize()}",
|
||||
baseName,
|
||||
getImplementationDependencies(),
|
||||
dependencies,
|
||||
this,
|
||||
identity
|
||||
).apply {
|
||||
|
||||
+2
-2
@@ -30,7 +30,7 @@ import javax.inject.Inject
|
||||
open class KotlinNativeStaticImpl @Inject constructor(
|
||||
name: String,
|
||||
baseName: Provider<String>,
|
||||
componentImplementation: Configuration,
|
||||
componentDependencies: KotlinNativeDependenciesImpl,
|
||||
component: KotlinNativeMainComponent,
|
||||
identity: KotlinNativeVariantIdentity,
|
||||
projectLayout: ProjectLayout,
|
||||
@@ -45,7 +45,7 @@ open class KotlinNativeStaticImpl @Inject constructor(
|
||||
projectLayout,
|
||||
CompilerOutputKind.STATIC,
|
||||
objects,
|
||||
componentImplementation,
|
||||
componentDependencies,
|
||||
configurations,
|
||||
fileOperations
|
||||
), KotlinNativeStatic {
|
||||
|
||||
+2
-2
@@ -34,7 +34,7 @@ import javax.inject.Inject
|
||||
open class KotlinNativeTestExecutableImpl @Inject constructor(
|
||||
name: String,
|
||||
baseName: Provider<String>,
|
||||
componentImplementation: Configuration,
|
||||
componentDependencies: KotlinNativeDependenciesImpl,
|
||||
val testComponent: KotlinNativeTestSuite,
|
||||
val mainSources: KotlinNativeSourceSet,
|
||||
identity: KotlinNativeVariantIdentity,
|
||||
@@ -49,7 +49,7 @@ open class KotlinNativeTestExecutableImpl @Inject constructor(
|
||||
projectLayout,
|
||||
CompilerOutputKind.PROGRAM,
|
||||
objects,
|
||||
componentImplementation,
|
||||
componentDependencies,
|
||||
configurations,
|
||||
fileOperations),
|
||||
KotlinNativeTestExecutable {
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ open class KotlinNativeTestSuite @Inject constructor(
|
||||
KotlinNativeTestExecutableImpl::class.java,
|
||||
"$name${identity.name.capitalize()}",
|
||||
getBaseName(),
|
||||
getImplementationDependencies(),
|
||||
dependencies,
|
||||
this,
|
||||
testedComponent.sources,
|
||||
identity
|
||||
|
||||
+19
-2
@@ -26,6 +26,7 @@ import org.gradle.api.tasks.InputFiles
|
||||
import org.gradle.api.tasks.Optional
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.jetbrains.kotlin.gradle.plugin.experimental.KotlinNativeFramework
|
||||
import org.jetbrains.kotlin.gradle.plugin.experimental.internal.AbstractKotlinNativeBinary
|
||||
import org.jetbrains.kotlin.gradle.plugin.konan.*
|
||||
import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions
|
||||
@@ -54,6 +55,14 @@ open class KotlinNativeCompile @Inject constructor(internal val binary: Abstract
|
||||
val libraries: Configuration
|
||||
@InputFiles get() = binary.klibs
|
||||
|
||||
@get:InputFiles
|
||||
val exportLibraries: FileCollection
|
||||
get() = if (binary is KotlinNativeFramework) {
|
||||
binary.export
|
||||
} else {
|
||||
project.files()
|
||||
}
|
||||
|
||||
override fun getClasspath(): FileCollection = libraries
|
||||
|
||||
override fun setClasspath(configuration: FileCollection?) {
|
||||
@@ -158,12 +167,20 @@ open class KotlinNativeCompile @Inject constructor(internal val binary: Abstract
|
||||
|
||||
addAll(additionalCompilerOptions)
|
||||
|
||||
libraries.files.filter {
|
||||
fun Set<File>.filterKlibs() = filter {
|
||||
it.extension == "klib"
|
||||
}.forEach {
|
||||
}
|
||||
|
||||
libraries.files.filterKlibs().forEach {
|
||||
addArg("-l", it.absolutePath)
|
||||
}
|
||||
|
||||
// There is no need to check that all exported dependencies are passed with -l option
|
||||
// because export configuration extends the libraries one.
|
||||
exportLibraries.files.filterKlibs().forEach {
|
||||
add("-Xexport-library=${it.absolutePath}")
|
||||
}
|
||||
|
||||
addListArg("-linker-options", linkerOpts)
|
||||
|
||||
addAll(sources.files.map { it.absolutePath })
|
||||
|
||||
@@ -1131,4 +1131,43 @@ class ExperimentalPluginTests {
|
||||
val result = project.createRunner().withArguments("build").build()
|
||||
assertTrue(result.output.contains("A.a"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Plugin should support symbol exporting for frameworks`() {
|
||||
assumeTrue(HostManager.hostIsMac)
|
||||
val libraryDir = tmpFolder.newFolder("library")
|
||||
val libraryProject = KonanProject.createEmpty(libraryDir).apply {
|
||||
buildFile.writeText("""
|
||||
plugins { id 'kotlin-native' }
|
||||
""".trimIndent())
|
||||
generateSrcFile("library.kt", "fun foo() = 42")
|
||||
}
|
||||
|
||||
val project = KonanProject.createEmpty(projectDirectory).apply {
|
||||
settingsFile.writeText("""
|
||||
include ':library'
|
||||
rootProject.name = 'test'
|
||||
""".trimIndent())
|
||||
buildFile.writeText("""
|
||||
plugins { id 'kotlin-native' }
|
||||
|
||||
dependencies {
|
||||
export project(':library')
|
||||
}
|
||||
|
||||
sourceSets.main.component {
|
||||
outputKinds = [ FRAMEWORK ]
|
||||
}
|
||||
""".trimIndent())
|
||||
generateSrcFile("main.kt", "fun main(args: Array<String>) { println(foo()) }")
|
||||
}
|
||||
|
||||
val compileDebugResult = project.createRunner().withArguments("compileDebugKotlinNative").build()
|
||||
assertEquals(TaskOutcome.SUCCESS, compileDebugResult.task(":compileDebugKotlinNative")?.outcome)
|
||||
assertEquals(TaskOutcome.SUCCESS, compileDebugResult.task(":library:compileDebugKotlinNative")?.outcome)
|
||||
assertTrue(projectDirectory.resolve("build/lib/main/debug/test.framework").exists())
|
||||
val header = projectDirectory.resolve("build/lib/main/debug/test.framework/Headers/test.h")
|
||||
assertTrue(header.exists())
|
||||
assertTrue(header.readText().contains("+ (int32_t)foo "))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user