From 1a3cf3b792587febae1cda445ea81a3335d9ac5d Mon Sep 17 00:00:00 2001 From: Yaroslav Chernyshev Date: Thu, 26 Dec 2019 15:25:50 +0300 Subject: [PATCH] [Gradle, Native] Added subspecs support in CocoaPods plugin #KT-32750 fixed --- .../jetbrains/kotlin/gradle/CocoaPodsIT.kt | 6 ++++-- .../new-mpp-cocoapods/ios-app/Podfile | 1 + .../ios-app/ios-app/ViewController.swift | 1 + .../kotlin-library/build.gradle.kts | 1 + .../kotlin-library/src/iosMain/kotlin/A.kt | 5 +++++ .../subspec_dependency/src/baz.h | 3 +++ .../subspec_dependency/src/baz.m | 5 +++++ .../subspec_dependency.podspec | 15 +++++++++++++++ .../native/cocoapods/CocoapodsExtension.kt | 2 +- .../native/cocoapods/KotlinCocoapodsPlugin.kt | 19 ++++++++++++------- .../targets/native/tasks/CocoapodsTasks.kt | 14 +++++++++----- 11 files changed, 57 insertions(+), 15 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/subspec_dependency/src/baz.h create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/subspec_dependency/src/baz.m create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/subspec_dependency/subspec_dependency.podspec diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CocoaPodsIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CocoaPodsIT.kt index 97ead78b3ce..d6356b7b9e7 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CocoaPodsIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CocoaPodsIT.kt @@ -58,6 +58,7 @@ class CocoaPodsIT : BaseGradleIT() { spec.module_name = "#{spec.name}_umbrella" spec.dependency 'pod_dependency', '1.0' + spec.dependency 'subspec_dependency/Core', '1.0' spec.pod_target_xcconfig = { 'KOTLIN_TARGET[sdk=iphonesimulator*]' => 'ios_x64', @@ -102,15 +103,16 @@ class CocoaPodsIT : BaseGradleIT() { // Check that a project with CocoaPods interop fails to be built from command line. build(":kotlin-library:build") { assertFailed() - assertContains("Cannot perform cinterop processing for pod_dependency: cannot determine headers location.") + assertContains("Cannot perform cinterop processing for module pod_dependency: cannot determine headers location.") } // Check that a project without CocoaPods interop can be built from command line. gradleBuildScript("kotlin-library").modify { - it.replace("""pod("pod_dependency", "1.0")""", "") + it.replace("""pod("pod_dependency", "1.0")""", "").replace("""pod("subspec_dependency/Core", "1.0")""", "") } projectDir.resolve("kotlin-library/src/iosMain/kotlin/A.kt").modify { it.replace("import cocoapods.pod_dependency.*", "").replace("println(foo())", "") + .replace("import cocoapods.subspec_dependency.*", "").replace("println(baz())", "") } build(":kotlin-library:linkReleaseFrameworkIOS") { assertSuccessful() diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/ios-app/Podfile b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/ios-app/Podfile index b7975e73bf9..8a8f0548f39 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/ios-app/Podfile +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/ios-app/Podfile @@ -4,5 +4,6 @@ platform :ios, '9.0' target 'ios-app' do pod 'pod_dependency', :path => '../pod_dependency' + pod 'subspec_dependency', :path => '../subspec_dependency' pod 'kotlin_library', :path => '../kotlin-library' end \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/ios-app/ios-app/ViewController.swift b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/ios-app/ios-app/ViewController.swift index c72b3fbd710..fe229eb4784 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/ios-app/ios-app/ViewController.swift +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/ios-app/ios-app/ViewController.swift @@ -5,6 +5,7 @@ class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() AKt.bar() + AKt.bazz() // Do any additional setup after loading the view. } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/kotlin-library/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/kotlin-library/build.gradle.kts index eb73ced1357..38e62ac03d2 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/kotlin-library/build.gradle.kts +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/kotlin-library/build.gradle.kts @@ -22,5 +22,6 @@ kotlin { summary = "CocoaPods test library" homepage = "https://github.com/JetBrains/kotlin" pod("pod_dependency", "1.0") + pod("subspec_dependency/Core", "1.0") } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/kotlin-library/src/iosMain/kotlin/A.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/kotlin-library/src/iosMain/kotlin/A.kt index 1893d664598..2577991a64f 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/kotlin-library/src/iosMain/kotlin/A.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/kotlin-library/src/iosMain/kotlin/A.kt @@ -1,5 +1,10 @@ import cocoapods.pod_dependency.* +import cocoapods.subspec_dependency.* fun bar() { println(foo()) } + +fun bazz() { + println(baz()) +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/subspec_dependency/src/baz.h b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/subspec_dependency/src/baz.h new file mode 100644 index 00000000000..27e21fcd4e8 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/subspec_dependency/src/baz.h @@ -0,0 +1,3 @@ +#import + +NSString* baz(void); \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/subspec_dependency/src/baz.m b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/subspec_dependency/src/baz.m new file mode 100644 index 00000000000..88de68533ba --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/subspec_dependency/src/baz.m @@ -0,0 +1,5 @@ +#include "baz.h" + +NSString* baz() { + return @"Baz"; +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/subspec_dependency/subspec_dependency.podspec b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/subspec_dependency/subspec_dependency.podspec new file mode 100644 index 00000000000..343c53ccc09 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-cocoapods/subspec_dependency/subspec_dependency.podspec @@ -0,0 +1,15 @@ +Pod::Spec.new do |spec| + spec.name = 'subspec_dependency' + spec.version = '1.0' + spec.homepage = 'baz' + spec.source = { :git => "Not Published", :tag => "Cocoapods/#{spec.name}/#{spec.version}" } + spec.authors = '' + spec.license = '' + spec.summary = 'baz' + spec.default_subspec = 'Core' + + spec.subspec 'Core' do |core| + core.source_files = "src/*" + core.public_header_files = "src/*.h" + end +end \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/CocoapodsExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/CocoapodsExtension.kt index 8fcce7545fd..210bb06559f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/CocoapodsExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/CocoapodsExtension.kt @@ -66,7 +66,7 @@ open class CocoapodsExtension(private val project: Project) { * Add a CocoaPods dependency to the pod built from this project. */ @JvmOverloads - fun pod(name: String, version: String? = null, moduleName: String = name) { + fun pod(name: String, version: String? = null, moduleName: String = name.split("/")[0]) { check(_pods.findByName(name) == null) { "Project already has a CocoaPods dependency with name $name" } _pods.add(CocoapodsDependency(name, version, moduleName)) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/KotlinCocoapodsPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/KotlinCocoapodsPlugin.kt index dc206cb1ec6..94d116bc3dd 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/KotlinCocoapodsPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/KotlinCocoapodsPlugin.kt @@ -42,7 +42,7 @@ internal class CocoapodsBuildDirs(val project: Project) { internal fun String.asValidFrameworkName() = replace('-', '_') -open class KotlinCocoapodsPlugin: Plugin { +open class KotlinCocoapodsPlugin : Plugin { private fun KotlinMultiplatformExtension.supportedTargets() = targets .withType(KotlinNativeTarget::class.java) @@ -175,19 +175,25 @@ open class KotlinCocoapodsPlugin: Plugin { kotlinExtension: KotlinMultiplatformExtension, cocoapodsExtension: CocoapodsExtension ) { + val moduleNames = mutableSetOf() cocoapodsExtension.pods.all { pod -> + if (moduleNames.contains(pod.moduleName)) { + return@all + } + moduleNames.add(pod.moduleName) + val defTask = project.tasks.create( - lowerCamelCaseName("generateDef", pod.name).asValidTaskName(), + lowerCamelCaseName("generateDef", pod.moduleName).asValidTaskName(), DefFileTask::class.java ) { it.pod = pod - it.description = "Generates a def file for CocoaPods dependency ${pod.name}" + 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. } kotlinExtension.supportedTargets().all { target -> - target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME).cinterops.create(pod.name) { interop -> + target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME).cinterops.create(pod.moduleName) { interop -> val interopTask = project.tasks.getByPath(interop.interopProcessingTaskName) interopTask.dependsOn(defTask) @@ -199,7 +205,7 @@ open class KotlinCocoapodsPlugin: Plugin { // Here and below we need to split such paths taking this into account. interop.compilerOpts.addAll(args.splitQuotedArgs()) } - project.findProperty(HEADER_PATHS_PROPERTY)?.toString()?.let { args-> + project.findProperty(HEADER_PATHS_PROPERTY)?.toString()?.let { args -> interop.compilerOpts.addAll(args.splitQuotedArgs().map { "-I$it" }) } project.findProperty(FRAMEWORK_PATHS_PROPERTY)?.toString()?.let { args -> @@ -216,7 +222,7 @@ open class KotlinCocoapodsPlugin: Plugin { check(hasCompilerOpts || hasHeaderSearchPath) { """ - |Cannot perform cinterop processing for ${pod.name}: cannot determine headers location. + |Cannot perform cinterop processing for module ${pod.moduleName}: cannot determine headers location. | |Probably the build is executed from command line. |Note that a Kotlin/Native module using CocoaPods dependencies can be built only from Xcode. @@ -225,7 +231,6 @@ open class KotlinCocoapodsPlugin: Plugin { """.trimMargin() } } - } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/CocoapodsTasks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/CocoapodsTasks.kt index 28ea5c15988..70f80bf8b83 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/CocoapodsTasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/CocoapodsTasks.kt @@ -57,7 +57,8 @@ open class PodspecTask : DefaultTask() { val syncTask = "${project.path}:$SYNC_TASK_NAME" - outputFile.writeText(""" + outputFile.writeText( + """ |Pod::Spec.new do |spec| | spec.name = '$specName' | spec.version = '${settings.version}' @@ -102,7 +103,8 @@ open class PodspecTask : DefaultTask() { | } | ] |end - """.trimMargin()) + """.trimMargin() + ) logger.quiet( """ @@ -204,14 +206,16 @@ open class DefFileTask : DefaultTask() { @get:OutputFile val outputFile: File - get() = project.cocoapodsBuildDirs.defs.resolve("${pod.name}.def") + get() = project.cocoapodsBuildDirs.defs.resolve("${pod.moduleName}.def") @TaskAction fun generate() { outputFile.parentFile.mkdirs() - outputFile.writeText(""" + outputFile.writeText( + """ language = Objective-C modules = ${pod.moduleName} - """.trimIndent()) + """.trimIndent() + ) } } \ No newline at end of file