Not able to add iOS custom framework to a KMM (Kotlin Multi Platform) module (cinteropXXXIosArm64 FAILED module not found)

Viewed 1665

I'm developing an iOS app, which makes use of a Kotlin Native share module. This Kotlin Native shared module, makes use of a self-developed iOS framework.

This had worked very well in the past, but now I'm trying to upgrade my project for the last release of Kotlin Native (1.4.10 at this moment), Android Studio, and so on, and I'm not able to import my custom iOS framework dependency.

The folder structure of the iOS framework is the following: This is the folder structure of my iOS framework

introducir la descripción de la imagen aquí

Following the guide at https://kotlinlang.org/docs/mobile/add-dependencies.html, I added a .def file to my shared code project with the following content:

language = Objective-C
modules = SlicerUtils
package = com.xxxx.customframework

The build.gradle.kts file is the standard file generated with the template for KMM projects available in the last release of Android Studio (4.2.idontremember). Then I added the iosX64 and iosArm64 sections as explained in the link above:

import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget

plugins {
    id("com.android.library")
    kotlin("multiplatform")
    kotlin("plugin.serialization") version "1.4.10"



    id("kotlin-android-extensions")

}
group = "con.xxxx.customframework"
version = "1.0"

repositories {
    gradlePluginPortal()
    google()
    jcenter()
    mavenCentral()
}
kotlin {
    android()
    ios {
        binaries {
            framework {
                baseName = "shared"
            }
        }
    }





    //////////////////////////

    val iosFrameworkBaseDir = "${projectDir}/../../ios-frameworks"
    val slicerUtilsDir = file("$iosFrameworkBaseDir/SlicerUtils/SlicerUtils").absolutePath


    val slicerUtilsBaseFrameworkDirX64 = file("$slicerUtilsDir/DerivedData/SlicerUtils/Build/Products/Debug-iphonesimulator/SlicerUtils.framework").absolutePath
    val slicerUtilsBaseBuildDirArm64 = file("$slicerUtilsDir/DerivedData/SlicerUtils/Build/Products/Debug-iphoneos/SlicerUtils.framework").absolutePath

    iosX64() {
        compilations.getByName("main") {
            val slicerUtils  by cinterops.creating {

                defFile("SwiftSlicerUtils.def")

               compilerOpts("-framework", "SlicerUtils", "-F${slicerUtilsDir}")
               

            }

        }

        binaries.all {
            // Linker options required to link to the library.
            linkerOpts("-L$slicerUtilsBaseFrameworkDirX64", "-lSlicerUtils")
        
        }
    }

    iosArm64() {
        compilations.getByName("main") {
            val slicerUtils by cinterops.creating {

                defFile("SwiftSlicerUtils.def")

                compilerOpts("-framework", "SlicerUtils", "-F${slicerUtilsDir}")
                

            }

        }

        binaries.all {
            // Linker options required to link to the library.
              linkerOpts("-L$slicerUtilsBaseBuildDirArm64", "-lSlicerUtils")
        }
    }
    /////////////////////////


    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation("org.jetbrains.kotlin:kotlin-stdlib-common")
                implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.0.1")
                implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1")
            }
        }
        val commonTest by getting {
            dependencies {
                implementation(kotlin("test-common"))
                implementation(kotlin("test-annotations-common"))


            }
        }
        val androidMain by getting {
            dependencies {

                implementation("org.jetbrains.kotlin:kotlin-stdlib")
                implementation("org.jsoup:jsoup:1.13.1")
            }
        }
        val androidTest by getting {
            dependencies {
                implementation(kotlin("test-junit"))
                implementation("junit:junit:4.13")
            }
        }
        val iosMain by getting
        val iosTest by getting
    }
}
android {
    compileSdkVersion(29)
    sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
    defaultConfig {
        minSdkVersion(23)
        targetSdkVersion(29)
        versionCode = 1
        versionName = "1.0"
    }
    buildTypes {
        getByName("release") {
            isMinifyEnabled = true
        }
    }
}
val packForXcode by tasks.creating(Sync::class) {
    group = "build"
    val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
    val sdkName = System.getenv("SDK_NAME") ?: "iphonesimulator"
    val targetName = "ios" + if (sdkName.startsWith("iphoneos")) "Arm64" else "X64"
    val framework =
        kotlin.targets.getByName<KotlinNativeTarget>(targetName).binaries.getFramework(mode)
    inputs.property("mode", mode)
    dependsOn(framework.linkTask)
    val targetDir = File(buildDir, "xcode-frameworks")
    from({ framework.outputDirectory })
    into(targetDir)
}
tasks.getByName("build").dependsOn(packForXcode)

The error I'm receiving is the following:

> Task :shared:cinteropSlicerUtilsIosArm64 FAILED
Exception in thread "main" java.lang.Error: /var/folders/xd/ts3w2yyj66732_54xj7nhrtr0000gn/T/tmp3537373282020062433.m:1:9: fatal error: module 'SlicerUtils' not found
    at org.jetbrains.kotlin.native.interop.indexer.UtilsKt.ensureNoCompileErrors(Utils.kt:152)
    at org.jetbrains.kotlin.native.interop.indexer.ModuleSupportKt.getModulesASTFiles(ModuleSupport.kt:67)
    at org.jetbrains.kotlin.native.interop.indexer.ModuleSupportKt.getModulesInfo(ModuleSupport.kt:13)
    at org.jetbrains.kotlin.native.interop.gen.jvm.MainKt.buildNativeLibrary(main.kt:499)
    at org.jetbrains.kotlin.native.interop.gen.jvm.MainKt.processCLib(main.kt:264)
    at org.jetbrains.kotlin.native.interop.gen.jvm.MainKt.interop(main.kt:72)
    at org.jetbrains.kotlin.cli.utilities.InteropCompilerKt.invokeInterop(InteropCompiler.kt:45)
    at org.jetbrains.kotlin.cli.utilities.MainKt.mainImpl(main.kt:19)
    at org.jetbrains.kotlin.cli.utilities.MainKt.main(main.kt:37)

FAILURE: Build failed with an exception.

I tried pretty much all the combinations existent from paths to the framework folder without success, but in the example pasted, I'm providing the path to the root folder of the framework with the compileropts command, and the path to build folder of each architecture with the linkeropts command. As said I tried this and other combinations, without success.

As a general question, when the official documentation says:

Pass the framework name to the compiler and linker using the -framework option. Pass the path to the framework sources and binaries to the compiler and linker using the -F option.

  • What is the module name of the error?
  • What is the framework name? The name of the project in xCode?
  • The path to the framework sources is the path to the swift files of this framework, or to the root folder of the framework or what?
  • And where is the binary of a framework stored? I suppose that the binary is the following file, but I'm not sure: introducir la descripción de la imagen aquí

Maybe you can point me out what I'm doing wrong. Thank you in advance!

0 Answers
Related