diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/CocoaPodsIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/CocoaPodsIT.kt index 77fdcd88c9e..0be3435f78f 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/CocoaPodsIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/CocoaPodsIT.kt @@ -29,6 +29,8 @@ import java.io.File import java.io.IOException import java.util.* import java.util.concurrent.TimeUnit +import java.util.zip.ZipFile +import kotlin.test.assertContains import kotlin.test.assertEquals import kotlin.test.assertTrue import kotlin.test.fail @@ -68,7 +70,6 @@ class CocoaPodsIT : BaseGradleIT() { private val defaultPodRepo = "https://github.com/AFNetworking/AFNetworking" private val defaultPodName = "AFNetworking" - private val defaultLibraryPodName = "YandexMapKit" private val defaultTarget = "IOS" private val defaultFamily = "IOS" private val defaultSDK = "iphonesimulator" @@ -722,7 +723,22 @@ class CocoaPodsIT : BaseGradleIT() { fun testUseLibrariesMode() { with(project) { gradleBuildScript().appendToCocoapodsBlock("useLibraries()") - gradleBuildScript().addPod(defaultLibraryPodName) + gradleBuildScript().addPod("AFNetworking", configuration = "headers = \"AFNetworking/AFNetworking.h\"") + testImport() + } + } + + + @Test + fun testUseLibrariesModeWarnWhenPodIsAddedWithoutHeadersSpecified() { + with(project) { + gradleBuildScript().appendToCocoapodsBlock("useLibraries()") + gradleBuildScript().addPod("AFNetworking") + + hooks.addHook { + assertContains("w: Pod 'AFNetworking' should have 'headers' property specified when using 'useLibraries()'") + } + testImport() } } @@ -987,6 +1003,19 @@ class CocoaPodsIT : BaseGradleIT() { } } + @Test + fun testCinteropKlibsProvideLinkerOptsToFramework() = with(project) { + gradleBuildScript().addPod("AFNetworking") + testWithWrapper(":cinteropAFNetworkingIOS") + + val cinteropKlib = projectDir.resolve("build/classes/kotlin/iOS/main/cinterop/cocoapods-cinterop-AFNetworking.klib") + val manifestLines = ZipFile(cinteropKlib).use { zip -> + zip.getInputStream(zip.getEntry("default/manifest")).bufferedReader().use { it.readLines() } + } + + assertContains(manifestLines, "linkerOpts=-framework AFNetworking") + } + // test configuration phase private class CustomHooks { diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/KotlinCocoapodsPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/KotlinCocoapodsPlugin.kt index ed8663ad225..29e17e2f2e2 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/KotlinCocoapodsPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/KotlinCocoapodsPlugin.kt @@ -305,7 +305,8 @@ open class KotlinCocoapodsPlugin : Plugin { val defTask = project.registerTask( lowerCamelCaseName("generateDef", pod.moduleName).asValidTaskName() ) { - it.pod = project.provider { pod } + it.pod.set(pod) + it.useLibraries.set(cocoapodsExtension.useLibraries) it.description = "Generates a def file for CocoaPods dependencies with module ${pod.moduleName}" // This task is an implementation detail so we don't add it in any group // to avoid showing it in the `tasks` output. diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/CocoapodsTasks.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/CocoapodsTasks.kt index 8812fec0c1c..2a14b59fcc4 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/CocoapodsTasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/CocoapodsTasks.kt @@ -9,6 +9,7 @@ package org.jetbrains.kotlin.gradle.tasks import org.gradle.api.DefaultTask import org.gradle.api.Project import org.gradle.api.plugins.ExtensionAware +import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.gradle.api.tasks.wrapper.Wrapper @@ -318,10 +319,13 @@ open class DummyFrameworkTask : DefaultTask() { /** * Generates a def-file for the given CocoaPods dependency. */ -open class DefFileTask : DefaultTask() { +abstract class DefFileTask : DefaultTask() { @get:Nested - lateinit var pod: Provider + abstract val pod: Property + + @get:Input + abstract val useLibraries: Property @get:OutputFile val outputFile: File @@ -333,8 +337,22 @@ open class DefFileTask : DefaultTask() { outputFile.writeText(buildString { appendLine("language = Objective-C") with(pod.get()) { - if (headers != null) appendLine("headers = $headers") - else appendLine("modules = $moduleName") + when { + headers != null -> appendLine("headers = $headers") + useLibraries.get() -> logger.warn( + """ + w: Pod '$moduleName' should have 'headers' property specified when using 'useLibraries()'. + Otherwise code from this pod won't be accessible from Kotlin. + """.trimIndent() + ) + else -> { + appendLine("modules = $moduleName") + + // Linker opt with framework name is added so produced cinterop klib would have this flag inside its manifest + // This way error will be more obvious when someone will try to depend on a library with this cinterop + appendLine("linkerOpts = -framework $moduleName") + } + } } }) }