Unable to archive Kotlin Native with Cocoapods in XCode

799 views Asked by At

I try to archive in XCode 12 a project referencing a Kotlin Native framework with cocoapods plugin, but it fails with message like this (using iPhone SE to build archive)

Ignoring file *MyFramework*, building for iOS-armv7 but attempting to link with file built for iOS-arm64

Undefined symbol: _OBJC_CLASS_$_... (for armv7)

I reference my framework in Podfile of the project as a local pod (using :path and :modular_headers => true)

As I understand I have to build a fat framework to include both armv7 and arm64 but how do I manage this using Kotlin cocoapods plugin?


Here are some links with recommendations, but I was unable to put it together in my case

https://github.com/ilmat192/kotlin-native-gradle-samples/blob/master/fat-framework/build.gradle.kts

https://github.com/JetBrains/kotlin-native/issues/3140

https://medium.com/@yuyaHorita/universal-frameworks-xcframework-with-kotlinnative-999d830e206e

https://github.com/JetBrains/kotlin-native/issues/2574

https://github.com/ilmat192/kotlin-native-gradle-samples/blob/master/fat-framework/build.gradle.kts


Project's build.gradle

buildscript {

    ext.kotlinVersion = '1.4.20-M2'
    // use 1.3.7 to avoid iOS build error
    // "Deserializer for declaration public kotlinx.coroutines/SingleThreadDispatcher|null[0] is not found"
    ext.coroutinesVersion = '1.3.7'
    ext.ktorVersion = '1.4.1'
    ext.napierVersion = '1.4.0'

    repositories {
        google()
        jcenter()
        maven { url "https://dl.bintray.com/kotlin/kotlin-eap" }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:4.1.0'
    }
}
repositories {
    google()
    jcenter()
}

Molule's build.gradle

plugins {
    id 'org.jetbrains.kotlin.multiplatform' version "$kotlinVersion"
    id "org.jetbrains.kotlin.native.cocoapods" version "$kotlinVersion"
    id "org.jetbrains.kotlin.plugin.serialization" version "$kotlinVersion"
}
repositories {
    google()
    jcenter()
    mavenCentral()
    maven { url "https://dl.bintray.com/aakira/maven" }
    maven { url "https://dl.bintray.com/kotlin/kotlin-eap" }
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId 'org.jetbrains.kotlin.mpp_app_android'
        minSdkVersion 16
        targetSdkVersion 28
        versionCode 1
        versionName '1.0'
        testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'
    }
    buildTypes {
        release {
            minifyEnabled false
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:2.0.2'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
}

kotlin {
    android("android")

    targets {
        final def iOSTarget = System.getenv('SDK_NAME')?.startsWith("iphoneos")  \
         ? presets.iosArm64 : presets.iosX64

        // https://kotlinlang.org/docs/reference/mpp-dsl-reference.html#native-targets
        fromPreset(iOSTarget, 'ios') {
            binaries {
            }
        }
    }

    // CocoaPods requires the podspec to have a version.
    version = "1.0"

    cocoapods {
        // Configure fields required by CocoaPods.
        def projectName = project.getRootProject().getName()

        summary = projectName
        homepage = "https://ya.ru"
        ios.deploymentTarget = "9.0"

        frameworkName = projectName

        pod("NVHTarGzip")
    }

    sourceSets {
        commonMain {
            dependencies {
                implementation kotlin('stdlib')

                implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.0")
                implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:0.9.1")

                // Coroutines components
                implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
                // workaround https://youtrack.jetbrains.com/issue/KT-41378
                implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9-native-mt-2")

                // Ktor components
                implementation("io.ktor:ktor-client-core:$ktorVersion")
                implementation("io.ktor:ktor-network:$ktorVersion")

                // workaround https://github.com/AAkira/Napier/issues/48
                implementation "com.github.aakira:napier:1.4.1-alpha1"
            }
        }
        commonTest {
            dependencies {
                implementation kotlin('test-common')
                implementation kotlin('test-annotations-common')
            }
        }
        androidMain {
            dependencies {
                // Ktor components
                implementation("io.ktor:ktor-client-android:$ktorVersion")
            }
        }
        androidTest {
            dependencies {
                implementation kotlin('test')
                implementation kotlin('test-junit')
            }
        }
        iosMain {
            dependencies {
                implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:0.9.1")

                // Ktor components
                implementation("io.ktor:ktor-client-ios:$ktorVersion")
            }
        }
        iosTest {
        }
    }
}

Solution

Actually not a true solution - based on accepted answer I just dropped armv7 support adding it to Excluded Architectures

1

There are 1 answers

0
Kevin Galligan On BEST ANSWER

building for iOS-armv7 but attempting to link with file built for iOS-arm64

Looks like you're trying to archive for armv7, which (I think) is 32 bit ios, or maybe watch, etc. Most apps need just arm64, and your Xcode framework will only be arm64 according to this:

final def iOSTarget = System.getenv('SDK_NAME')?.startsWith("iphoneos")  \
         ? presets.iosArm64 : presets.iosX64

If you only need arm64, and if it's just an iOS app, that seems likely, you can disable armv7 architecture in your build. Alternatively, you might try the combined ios() target.

We have a functional example here: https://github.com/touchlab/KaMPKit

It is using a fork of the cocoapods plugin, but besides isStatic, it's basically the same plugin.