[Gradle] Support dependencies between pods in CocoaPods plugin
^KT-38749 Verification Pending
This commit is contained in:
committed by
Space Team
parent
b36e1f1a5b
commit
4b66160afb
+41
@@ -1299,6 +1299,47 @@ class CocoaPodsIT : BaseGradleIT() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `hierarchy of dependant pods compiles successfully`() = with(getProjectByName("native-cocoapods-dependant-pods")) {
|
||||||
|
build(
|
||||||
|
":compileKotlinIosX64",
|
||||||
|
"-Pkotlin.native.cocoapods.generate.wrapper=true",
|
||||||
|
) {
|
||||||
|
assertSuccessful()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `configuration fails when trying to depend on non-declared pod`() = with(getProjectByName("native-cocoapods-dependant-pods")) {
|
||||||
|
gradleBuildScript().appendToCocoapodsBlock("""
|
||||||
|
pod("Foo") { useInteropBindingFrom("JBNonExistent") }
|
||||||
|
""".trimIndent())
|
||||||
|
|
||||||
|
build(
|
||||||
|
":help",
|
||||||
|
"-Pkotlin.native.cocoapods.generate.wrapper=true",
|
||||||
|
) {
|
||||||
|
assertFailed()
|
||||||
|
assertContains("Couldn't find declaration of pod 'JBNonExistent' (interop-binding dependency of pod 'Foo')")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `configuration fails when dependant pods are in the wrong order`() = with(getProjectByName("native-cocoapods-dependant-pods")) {
|
||||||
|
gradleBuildScript().appendToCocoapodsBlock("""
|
||||||
|
pod("Foo") { useInteropBindingFrom("Bar") }
|
||||||
|
pod("Bar")
|
||||||
|
""".trimIndent())
|
||||||
|
|
||||||
|
build(
|
||||||
|
":help",
|
||||||
|
"-Pkotlin.native.cocoapods.generate.wrapper=true",
|
||||||
|
) {
|
||||||
|
assertFailed()
|
||||||
|
assertContains("Couldn't find declaration of pod 'Bar' (interop-binding dependency of pod 'Foo')")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// test configuration phase
|
// test configuration phase
|
||||||
|
|
||||||
private class CustomHooks {
|
private class CustomHooks {
|
||||||
|
|||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("multiplatform") version "<pluginMarkerVersion>"
|
||||||
|
kotlin("native.cocoapods") version "<pluginMarkerVersion>"
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "org.jetbrains.kotlin.sample.native"
|
||||||
|
version = "1.0"
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
iosX64()
|
||||||
|
|
||||||
|
cocoapods {
|
||||||
|
summary = "Some description for the Shared Module"
|
||||||
|
homepage = "Link to the Shared Module homepage"
|
||||||
|
version = "1.0"
|
||||||
|
ios.deploymentTarget = "14.1"
|
||||||
|
framework {
|
||||||
|
baseName = "shared"
|
||||||
|
}
|
||||||
|
|
||||||
|
pod("pod1", path = project.file("pod1"))
|
||||||
|
|
||||||
|
pod("pod2") {
|
||||||
|
source = path(project.file("pod2"))
|
||||||
|
|
||||||
|
useInteropBindingFrom("pod1")
|
||||||
|
|
||||||
|
extraOpts = listOf("-compiler-option", "-fmodules")
|
||||||
|
}
|
||||||
|
|
||||||
|
pod("pod3") {
|
||||||
|
source = path(project.file("pod3"))
|
||||||
|
|
||||||
|
interopBindingDependencies.add("pod1")
|
||||||
|
}
|
||||||
|
|
||||||
|
pod("pod4") {
|
||||||
|
source = path(project.file("pod4"))
|
||||||
|
|
||||||
|
useInteropBindingFrom("pod2")
|
||||||
|
useInteropBindingFrom("pod3")
|
||||||
|
|
||||||
|
extraOpts = listOf("-compiler-option", "-fmodules")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
@interface Pod1 : NSObject
|
||||||
|
-(int)pod1;
|
||||||
|
-(void)name: (NSString *) firstName secondName: (NSString *) secondName;
|
||||||
|
@end
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
#include <pod1.h>
|
||||||
|
|
||||||
|
@implementation Pod1
|
||||||
|
|
||||||
|
-(int)pod1 {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void)name: (NSString *) firstName secondName: (NSString *) secondName {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
Pod::Spec.new do |spec|
|
||||||
|
spec.name = 'pod1'
|
||||||
|
spec.version = '1.0'
|
||||||
|
spec.homepage = 'repro'
|
||||||
|
spec.source = { :git => "Not Published", :tag => "Cocoapods/#{spec.name}/#{spec.version}" }
|
||||||
|
spec.authors = ''
|
||||||
|
spec.license = ''
|
||||||
|
spec.summary = 'repro'
|
||||||
|
|
||||||
|
spec.source_files = '*.{h,m}'
|
||||||
|
spec.public_header_files = '*.h'
|
||||||
|
end
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
Pod::Spec.new do |spec|
|
||||||
|
spec.name = 'pod2'
|
||||||
|
spec.version = '1.0'
|
||||||
|
spec.homepage = 'repro'
|
||||||
|
spec.source = { :git => "Not Published", :tag => "Cocoapods/#{spec.name}/#{spec.version}" }
|
||||||
|
spec.authors = ''
|
||||||
|
spec.license = ''
|
||||||
|
spec.summary = 'repro'
|
||||||
|
|
||||||
|
spec.dependency 'pod1'
|
||||||
|
|
||||||
|
spec.swift_version = '5.0'
|
||||||
|
spec.source_files = '*.swift'
|
||||||
|
end
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
import pod1
|
||||||
|
|
||||||
|
@objc
|
||||||
|
open class Pod2: Pod1 {
|
||||||
|
@objc
|
||||||
|
public func pod2() -> Int32 {
|
||||||
|
return 33
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
#import "pod1/pod1.h"
|
||||||
|
|
||||||
|
@interface Pod3 : Pod1
|
||||||
|
-(int)pod3;
|
||||||
|
@end
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
#include <pod3.h>
|
||||||
|
|
||||||
|
@implementation Pod3
|
||||||
|
|
||||||
|
-(int)pod3 {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
Pod::Spec.new do |spec|
|
||||||
|
spec.name = 'pod3'
|
||||||
|
spec.version = '1.0'
|
||||||
|
spec.homepage = 'repro'
|
||||||
|
spec.source = { :git => "Not Published", :tag => "Cocoapods/#{spec.name}/#{spec.version}" }
|
||||||
|
spec.authors = ''
|
||||||
|
spec.license = ''
|
||||||
|
spec.summary = 'repro'
|
||||||
|
|
||||||
|
spec.source_files = '*.{h,m}'
|
||||||
|
spec.public_header_files = '*.h'
|
||||||
|
|
||||||
|
spec.dependency 'pod1'
|
||||||
|
end
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
Pod::Spec.new do |spec|
|
||||||
|
spec.name = 'pod4'
|
||||||
|
spec.version = '1.0'
|
||||||
|
spec.homepage = 'repro'
|
||||||
|
spec.source = { :git => "Not Published", :tag => "Cocoapods/#{spec.name}/#{spec.version}" }
|
||||||
|
spec.authors = ''
|
||||||
|
spec.license = ''
|
||||||
|
spec.summary = 'repro'
|
||||||
|
|
||||||
|
spec.dependency 'pod2'
|
||||||
|
spec.dependency 'pod3'
|
||||||
|
|
||||||
|
spec.swift_version = '5.0'
|
||||||
|
spec.source_files = '*.swift'
|
||||||
|
end
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
import pod2
|
||||||
|
import pod3
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public class Pod42: Pod2 {
|
||||||
|
@objc
|
||||||
|
public func pod4() -> String {
|
||||||
|
return "Hello"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public class Pod43: Pod3 {
|
||||||
|
@objc
|
||||||
|
public func pod4() -> String {
|
||||||
|
return "Hello"
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
rootProject.name = "cocoapods"
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
import cocoapods.pod1.Pod1
|
||||||
|
import cocoapods.pod2.Pod2
|
||||||
|
import cocoapods.pod3.Pod3
|
||||||
|
import cocoapods.pod4.Pod42
|
||||||
|
import cocoapods.pod4.Pod43
|
||||||
|
|
||||||
|
fun printPod1(p: Pod1) {
|
||||||
|
println(p.pod1())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun printPod2(p: Pod2) {
|
||||||
|
println("Hi from Kt!")
|
||||||
|
println(p.pod2())
|
||||||
|
printPod1(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun printPod3(p: Pod3) {
|
||||||
|
printPod1(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun printPods4(p42: Pod42, p43: Pod43) {
|
||||||
|
printPod2(p42)
|
||||||
|
printPod3(p43)
|
||||||
|
printPod1(p42)
|
||||||
|
printPod1(p43)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
printPods4(Pod42(), Pod43())
|
||||||
|
}
|
||||||
+22
-1
@@ -20,7 +20,7 @@ import java.io.File
|
|||||||
import java.net.URI
|
import java.net.URI
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@Suppress("unused") // Public API
|
@Suppress("unused", "MemberVisibilityCanBePrivate") // Public API
|
||||||
abstract class CocoapodsExtension @Inject constructor(private val project: Project) {
|
abstract class CocoapodsExtension @Inject constructor(private val project: Project) {
|
||||||
/**
|
/**
|
||||||
* Configure version of the pod
|
* Configure version of the pod
|
||||||
@@ -292,6 +292,27 @@ abstract class CocoapodsExtension @Inject constructor(private val project: Proje
|
|||||||
@get:Input
|
@get:Input
|
||||||
var linkOnly: Boolean = false
|
var linkOnly: Boolean = false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains a list of dependencies to other pods. This list will be used while building an interop Kotlin-binding for the pod.
|
||||||
|
*
|
||||||
|
* @see useInteropBindingFrom
|
||||||
|
*/
|
||||||
|
@get:Input
|
||||||
|
val interopBindingDependencies: MutableList<String> = mutableListOf()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify that the pod depends on another pod **podName** and a Kotlin-binding for **podName** should be used while building
|
||||||
|
* a binding for the pod. This is necessary if you need to operate entities from **podName** and from the pod together, for
|
||||||
|
* instance pass an object from **podName** to the pod in Kotlin.
|
||||||
|
*
|
||||||
|
* A pod with the exact name must be declared before calling this function.
|
||||||
|
*
|
||||||
|
* @see interopBindingDependencies
|
||||||
|
*/
|
||||||
|
fun useInteropBindingFrom(podName: String) {
|
||||||
|
interopBindingDependencies.add(podName)
|
||||||
|
}
|
||||||
|
|
||||||
@Input
|
@Input
|
||||||
override fun getName(): String = name
|
override fun getName(): String = name
|
||||||
|
|
||||||
|
|||||||
+29
-2
@@ -7,6 +7,7 @@
|
|||||||
package org.jetbrains.kotlin.gradle.plugin.cocoapods
|
package org.jetbrains.kotlin.gradle.plugin.cocoapods
|
||||||
|
|
||||||
import org.gradle.api.DefaultTask
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.NamedDomainObjectContainer
|
||||||
import org.gradle.api.Plugin
|
import org.gradle.api.Plugin
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.plugins.ExtensionAware
|
import org.gradle.api.plugins.ExtensionAware
|
||||||
@@ -326,12 +327,17 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
kotlinExtension.supportedTargets().all { target ->
|
kotlinExtension.supportedTargets().all { target ->
|
||||||
target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME).cinterops.create(pod.moduleName) { interop ->
|
val cinterops = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME).cinterops
|
||||||
|
cinterops.create(pod.moduleName) { interop ->
|
||||||
|
|
||||||
val interopTask = project.tasks.getByPath(interop.interopProcessingTaskName)
|
val interopTask = project.tasks.named<CInteropProcess>(interop.interopProcessingTaskName).get()
|
||||||
|
|
||||||
interopTask.dependsOn(defTask)
|
interopTask.dependsOn(defTask)
|
||||||
|
|
||||||
|
pod.interopBindingDependencies.forEach { dependencyName ->
|
||||||
|
addPodDependencyToInterop(project, cocoapodsExtension, pod, cinterops, interop, dependencyName)
|
||||||
|
}
|
||||||
|
|
||||||
with(interop) {
|
with(interop) {
|
||||||
defFileProperty.set(defTask.map { it.outputFile })
|
defFileProperty.set(defTask.map { it.outputFile })
|
||||||
_packageNameProp.set(project.provider { pod.packageName })
|
_packageNameProp.set(project.provider { pod.packageName })
|
||||||
@@ -364,6 +370,27 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun addPodDependencyToInterop(
|
||||||
|
project: Project,
|
||||||
|
cocoapodsExtension: CocoapodsExtension,
|
||||||
|
pod: CocoapodsDependency,
|
||||||
|
cinterops: NamedDomainObjectContainer<DefaultCInteropSettings>,
|
||||||
|
interop: DefaultCInteropSettings,
|
||||||
|
dependencyName: String,
|
||||||
|
) {
|
||||||
|
val dependencyPod = cocoapodsExtension.pods.findByName(dependencyName)
|
||||||
|
?: error("Couldn't find declaration of pod '$dependencyName' (interop-binding dependency of pod '${pod.name}')")
|
||||||
|
|
||||||
|
val dependencyTaskName = cinterops.getByName(dependencyPod.moduleName).interopProcessingTaskName
|
||||||
|
val dependencyTask = project.tasks.named<CInteropProcess>(dependencyTaskName)
|
||||||
|
|
||||||
|
interop.dependencyFiles += project.files(dependencyTask.map { it.outputFile }).builtBy(dependencyTask)
|
||||||
|
|
||||||
|
dependencyPod.interopBindingDependencies.forEach { transitiveDependency ->
|
||||||
|
addPodDependencyToInterop(project, cocoapodsExtension, pod, cinterops, interop, transitiveDependency)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun registerDummyFrameworkTask(
|
private fun registerDummyFrameworkTask(
|
||||||
project: Project,
|
project: Project,
|
||||||
cocoapodsExtension: CocoapodsExtension
|
cocoapodsExtension: CocoapodsExtension
|
||||||
|
|||||||
Reference in New Issue
Block a user