具有 iOS Arm64 二进制框架 (.xcframework) 和 cinterop 的 KMM

mut*_*112 7 android ios kotlin-multiplatform xcframework kotlin-multiplatform-mobile

我按照此处的指南尝试在新的 KMM 项目中使用不带 CocoaPods 的 iOS 框架:

https://kotlinlang.org/docs/kmm-add-dependency.html#without-cocoapods

我有一个现有的、工作的 .xcframework,我将其添加到 .xcframework 下的项目中shared/src。我添加了一个MyKit.def文件并在同一共享目录中src/nativeInterop/cinterop/更新了该文件:build.gradle.kts

MyKit.def 看起来像

language = Objective-C
modules = MyKit
package = MyKit
Run Code Online (Sandbox Code Playgroud)

构建.gradle.kts

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

plugins {
    kotlin("multiplatform")
    id("com.android.library")
}

kotlin {
    android()

    val iosTarget: (String, KotlinNativeTarget.() -> Unit) -> KotlinNativeTarget =
        if (System.getenv("SDK_NAME")?.startsWith("iphoneos") == true)
            ::iosArm64
        else
            ::iosX64

    iosTarget("ios") {
        binaries {
            framework {
                baseName = "shared"
            }
        }
    }
    sourceSets {
        val commonMain by getting
        val commonTest by getting {
            dependencies {
                implementation(kotlin("test-common"))
                implementation(kotlin("test-annotations-common"))
            }
        }
        val androidMain by getting
        val androidTest by getting {
            dependencies {
                implementation(kotlin("test-junit"))
                implementation("junit:junit:4.13.2")
            }
        }
        val iosMain by getting
        val iosTest by getting
    }
    iosArm64() {
        compilations.getByName("main") {
            val MyKit by cinterops.creating {
                // Path to .def file
                defFile("src/nativeInterop/cinterop/MyKit.def")
                compilerOpts("-framework", "MyKit", "-F/src/MyKit.framework")
            }
        }

        binaries.all {
            // Linker options required to link to the library -- the framework binary is located under src/MyKit.framework/ios-arm64/MyKit.framework/
            linkerOpts("-framework", "MyKit", "-F/src/MyKit.framework/ios-arm64/MyKit.framework/")
        }
    }
}

android {
    compileSdkVersion(31)
    sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
    defaultConfig {
        minSdkVersion(26)
        targetSdkVersion(31)
    }
}
Run Code Online (Sandbox Code Playgroud)

添加import MyKit.*到我的 MainActivity 后出现unknown reference错误。

是否支持 iOS 二进制框架?.他们的文件名中有一个分隔符,所以这可能是一个问题。-F我的路径有问题吗?我不清楚路径是否应该一直到目录Headers和二进制文件本身,或者只是到框架根目录。TIA

小智 6

假设您有默认的 KMM 项目结构以及框架和 def 文件,如下所示:

- androidApp
- iosApp
  - MyFramework.framework
- shared
  - src
    - nativeInterop
      - cinterop
        - MyFramework.def
Run Code Online (Sandbox Code Playgroud)

这是您需要在build.gradle文件中添加的内容:

- androidApp
- iosApp
  - MyFramework.framework
- shared
  - src
    - nativeInterop
      - cinterop
        - MyFramework.def
Run Code Online (Sandbox Code Playgroud)

不幸的是,正如这里所述,相对路径不能作为编译器参数正常工作,因此您可以做的是使用projectDir值,并从该点到您的框架所在的位置。

注意:您需要指向框架所在的父文件夹(在示例中,我指向iosApp/,它是 的父文件夹MyFramework.framework)。

另请注意:如果您有.framework, afaik,您需要为 , , 等复制此代码iosX64iosArm64iosSimulatorArm64使导入在iosMain.
如果您有.xcframework路径,则需要指向 中的正确变体.xcframework,例如ios-arm64_armv7ios-arm64_i386_x86_64-simulator等。