Search code examples
androidkotlingradle-kotlin-dslkotlin-multiplatformkotlin-native

How to add thirdparty iOS pod library into kotlin native project ? getting error "SharedCode:cinteropAFNetworkingIos failed"


I created Kotlin native project to shared code between iOS and android.I did integration for cocoapods in-order to use in iOS project using POD file, Project successfully run on iOS and Android but when I tried to used iOS pod library in Kotlin native project, I start getting errors below.

I know that I have to run pod install first from Xcode in-order to compile library in Kotlin native project.

SO iOS pod library should be converted via cinterop, to use in Kotlin Native Project.

I run below command just to check either framework compile successfully or not.

./gradlew :SharedCode:packForXCode

got this error


FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':SharedCode:cinteropAFNetworkingIos'.
> Cannot perform cinterop processing for AFNetworking: 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.

please find below Gradle file.

build.Gradle.kts


plugins {
    kotlin("multiplatform")
    kotlin("native.cocoapods")
}

kotlin {

    //select iOS target platform depending on the Xcode environment variables
    val iOSTarget: (String, KotlinNativeTarget.() -> Unit) -> KotlinNativeTarget =
        if (System.getenv("SDK_NAME")?.startsWith("iphoneos") == true)
            ::iosArm64
        else
            ::iosX64

    iOSTarget("ios") {
        binaries {
            framework("Shared") {
                baseName = "SharedCode"
            }
        }
    }
    jvm("android")

    sourceSets["commonMain"].dependencies {
        implementation("org.jetbrains.kotlin:kotlin-stdlib-common")
    }

    sourceSets["androidMain"].dependencies {
        implementation("org.jetbrains.kotlin:kotlin-stdlib")
    }

    version = "1.0.0"
    cocoapods {
        summary = "This is sample Summary"
        homepage = "Home URL"

        pod("AFNetworking", "~> 3.2.0")
    }
}


val packForXcode by tasks.creating(Sync::class) {
    group = "build"

    //selecting the right configuration for the iOS framework depending on the Xcode environment variables
    val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
    val framework = kotlin.targets.getByName<KotlinNativeTarget>("ios").binaries.getFramework(mode)

    inputs.property("mode", mode)
    dependsOn(framework.linkTask)

    val targetDir = File(buildDir, "xcode-frameworks")
    from({ framework.outputDirectory })
    into(targetDir)

    doLast {
        val gradlew = File(targetDir, "gradlew")
        gradlew.writeText("#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew \$@\n")
        gradlew.setExecutable(true)
    }
}

tasks.getByName("build").dependsOn(packForXcode)```





Solution

  • I just tried these steps and managed to extend this sample with working interop of AFNetworking framework using CocoaPods plugin. These are my steps:

    1. After cloning the project and checking out the step-008 branch, edit build.gradle.kts that way: add CocoaPods plugin to the plugins section as id("org.jetbrains.kotlin.native.cocoapods") and delete whole binaries block from the iOSTarget specification block. This should be done because the cocoaPods plugin creates framework on it's own, and we should avoid duplication (see discussion). Instead of that block, add cocoapods specification. This part of the script should look like that:
    iOSTarget("ios") {}
        version = "1.0.0"
        cocoapods {
            summary = "This is sample Summary"
            homepage = "Home URL"
    
            pod("AFNetworking", "~> 3.2.0")
        }
    
    1. Then, execute Gradle task podspec to generate podspec for your framework. This should be done inside of the /SharedCode/ directory, as the previous one. If the task is not presented, it means that the CocoaPods plugin was not applied correctly.
    2. When the podspec is ready, we can use it from the Xcode project. To do it, open the /native/KotlinIOS/ directory, and create Podfile there. I used these contents for is:
    use_frameworks!
    
    platform :ios, '9.0'
    
    target 'KotlinIOS' do
        pod 'SharedCode', :path => '../../SharedCode'
    end
    

    The important part here is that the name corresponds to our framework name, and the relative path points on the place containing build.gradle.kts from the first step. After Podfile creation, install pods here using pod install from the terminal(CocoaPods should be installed).

    1. Now open generated KotlinIOS.xcworkspace with Xcode. There, one more thing should be fixed. At this moment the KotlinIOS project is set to search for frameworks only in /SharedCode/build/Xcode-frameworks/ directory, but CocoaPods won't put anything there. So, select KotlinIOS on the left panel, open Build Settings tab and find there Search Paths -> Framework Search Paths. Press + and add $(inherited) to the list, to make available frameworks that CocoaPods installed.
    2. Now, execute Build from the Xcode. After that, in your Kotlin IDE the AFNetworking package should become available. To import it, use import cocoapods.AFNetworking.*. For the first time it might need to invalidate Caches and Restart, to make it see this package correctly.

    I hope this will help. Please comment if something is unclear in this instruction.