[Gradle, Native] Added subspecs support in CocoaPods plugin

#KT-32750 fixed
This commit is contained in:
Yaroslav Chernyshev
2019-12-26 15:25:50 +03:00
parent 8871c8b4fd
commit 1a3cf3b792
11 changed files with 57 additions and 15 deletions
@@ -58,6 +58,7 @@ class CocoaPodsIT : BaseGradleIT() {
spec.module_name = "#{spec.name}_umbrella" spec.module_name = "#{spec.name}_umbrella"
spec.dependency 'pod_dependency', '1.0' spec.dependency 'pod_dependency', '1.0'
spec.dependency 'subspec_dependency/Core', '1.0'
spec.pod_target_xcconfig = { spec.pod_target_xcconfig = {
'KOTLIN_TARGET[sdk=iphonesimulator*]' => 'ios_x64', '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. // Check that a project with CocoaPods interop fails to be built from command line.
build(":kotlin-library:build") { build(":kotlin-library:build") {
assertFailed() 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. // Check that a project without CocoaPods interop can be built from command line.
gradleBuildScript("kotlin-library").modify { 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 { projectDir.resolve("kotlin-library/src/iosMain/kotlin/A.kt").modify {
it.replace("import cocoapods.pod_dependency.*", "").replace("println(foo())", "") it.replace("import cocoapods.pod_dependency.*", "").replace("println(foo())", "")
.replace("import cocoapods.subspec_dependency.*", "").replace("println(baz())", "")
} }
build(":kotlin-library:linkReleaseFrameworkIOS") { build(":kotlin-library:linkReleaseFrameworkIOS") {
assertSuccessful() assertSuccessful()
@@ -4,5 +4,6 @@ platform :ios, '9.0'
target 'ios-app' do target 'ios-app' do
pod 'pod_dependency', :path => '../pod_dependency' pod 'pod_dependency', :path => '../pod_dependency'
pod 'subspec_dependency', :path => '../subspec_dependency'
pod 'kotlin_library', :path => '../kotlin-library' pod 'kotlin_library', :path => '../kotlin-library'
end end
@@ -5,6 +5,7 @@ class ViewController: UIViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
AKt.bar() AKt.bar()
AKt.bazz()
// Do any additional setup after loading the view. // Do any additional setup after loading the view.
} }
} }
@@ -22,5 +22,6 @@ kotlin {
summary = "CocoaPods test library" summary = "CocoaPods test library"
homepage = "https://github.com/JetBrains/kotlin" homepage = "https://github.com/JetBrains/kotlin"
pod("pod_dependency", "1.0") pod("pod_dependency", "1.0")
pod("subspec_dependency/Core", "1.0")
} }
} }
@@ -1,5 +1,10 @@
import cocoapods.pod_dependency.* import cocoapods.pod_dependency.*
import cocoapods.subspec_dependency.*
fun bar() { fun bar() {
println(foo()) println(foo())
} }
fun bazz() {
println(baz())
}
@@ -0,0 +1,3 @@
#import <Foundation/Foundation.h>
NSString* baz(void);
@@ -0,0 +1,5 @@
#include "baz.h"
NSString* baz() {
return @"Baz";
}
@@ -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
@@ -66,7 +66,7 @@ open class CocoapodsExtension(private val project: Project) {
* Add a CocoaPods dependency to the pod built from this project. * Add a CocoaPods dependency to the pod built from this project.
*/ */
@JvmOverloads @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" } check(_pods.findByName(name) == null) { "Project already has a CocoaPods dependency with name $name" }
_pods.add(CocoapodsDependency(name, version, moduleName)) _pods.add(CocoapodsDependency(name, version, moduleName))
} }
@@ -42,7 +42,7 @@ internal class CocoapodsBuildDirs(val project: Project) {
internal fun String.asValidFrameworkName() = replace('-', '_') internal fun String.asValidFrameworkName() = replace('-', '_')
open class KotlinCocoapodsPlugin: Plugin<Project> { open class KotlinCocoapodsPlugin : Plugin<Project> {
private fun KotlinMultiplatformExtension.supportedTargets() = targets private fun KotlinMultiplatformExtension.supportedTargets() = targets
.withType(KotlinNativeTarget::class.java) .withType(KotlinNativeTarget::class.java)
@@ -175,19 +175,25 @@ open class KotlinCocoapodsPlugin: Plugin<Project> {
kotlinExtension: KotlinMultiplatformExtension, kotlinExtension: KotlinMultiplatformExtension,
cocoapodsExtension: CocoapodsExtension cocoapodsExtension: CocoapodsExtension
) { ) {
val moduleNames = mutableSetOf<String>()
cocoapodsExtension.pods.all { pod -> cocoapodsExtension.pods.all { pod ->
if (moduleNames.contains(pod.moduleName)) {
return@all
}
moduleNames.add(pod.moduleName)
val defTask = project.tasks.create( val defTask = project.tasks.create(
lowerCamelCaseName("generateDef", pod.name).asValidTaskName(), lowerCamelCaseName("generateDef", pod.moduleName).asValidTaskName(),
DefFileTask::class.java DefFileTask::class.java
) { ) {
it.pod = pod 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 // This task is an implementation detail so we don't add it in any group
// to avoid showing it in the `tasks` output. // to avoid showing it in the `tasks` output.
} }
kotlinExtension.supportedTargets().all { target -> 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) val interopTask = project.tasks.getByPath(interop.interopProcessingTaskName)
interopTask.dependsOn(defTask) interopTask.dependsOn(defTask)
@@ -199,7 +205,7 @@ open class KotlinCocoapodsPlugin: Plugin<Project> {
// Here and below we need to split such paths taking this into account. // Here and below we need to split such paths taking this into account.
interop.compilerOpts.addAll(args.splitQuotedArgs()) 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" }) interop.compilerOpts.addAll(args.splitQuotedArgs().map { "-I$it" })
} }
project.findProperty(FRAMEWORK_PATHS_PROPERTY)?.toString()?.let { args -> project.findProperty(FRAMEWORK_PATHS_PROPERTY)?.toString()?.let { args ->
@@ -216,7 +222,7 @@ open class KotlinCocoapodsPlugin: Plugin<Project> {
check(hasCompilerOpts || hasHeaderSearchPath) { 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. |Probably the build is executed from command line.
|Note that a Kotlin/Native module using CocoaPods dependencies can be built only from Xcode. |Note that a Kotlin/Native module using CocoaPods dependencies can be built only from Xcode.
@@ -225,7 +231,6 @@ open class KotlinCocoapodsPlugin: Plugin<Project> {
""".trimMargin() """.trimMargin()
} }
} }
} }
} }
} }
@@ -57,7 +57,8 @@ open class PodspecTask : DefaultTask() {
val syncTask = "${project.path}:$SYNC_TASK_NAME" val syncTask = "${project.path}:$SYNC_TASK_NAME"
outputFile.writeText(""" outputFile.writeText(
"""
|Pod::Spec.new do |spec| |Pod::Spec.new do |spec|
| spec.name = '$specName' | spec.name = '$specName'
| spec.version = '${settings.version}' | spec.version = '${settings.version}'
@@ -102,7 +103,8 @@ open class PodspecTask : DefaultTask() {
| } | }
| ] | ]
|end |end
""".trimMargin()) """.trimMargin()
)
logger.quiet( logger.quiet(
""" """
@@ -204,14 +206,16 @@ open class DefFileTask : DefaultTask() {
@get:OutputFile @get:OutputFile
val outputFile: File val outputFile: File
get() = project.cocoapodsBuildDirs.defs.resolve("${pod.name}.def") get() = project.cocoapodsBuildDirs.defs.resolve("${pod.moduleName}.def")
@TaskAction @TaskAction
fun generate() { fun generate() {
outputFile.parentFile.mkdirs() outputFile.parentFile.mkdirs()
outputFile.writeText(""" outputFile.writeText(
"""
language = Objective-C language = Objective-C
modules = ${pod.moduleName} modules = ${pod.moduleName}
""".trimIndent()) """.trimIndent()
)
} }
} }