无法将 iOS 自定义框架添加到 KMM(Kotlin 多平台)模块(未找到 cinteropXXXIosArm64 FAILED 模块)

R. *_*pos 6 ios kotlin kotlin-multiplatform

我正在开发一个 iOS 应用程序,它使用 Kotlin Native 共享模块。这个Kotlin Native共享模块,利用了自主开发的iOS框架。

\n

这在过去非常有效,但现在我正在尝试将我的项目升级为最新版本的 Kotlin Native(此时为 1.4.10)、Android Studio 等,但我无法导入我的自定义 iOS 框架依赖项。

\n

iOS 框架的文件夹结构如下:\n这是我的iOS框架的文件夹结构

\n

介绍 aqu\xc3\xad 图像的描述\xc3\xb3n

\n

按照https://kotlinlang.org/docs/mobile/add-dependency.html上的指南,我向我的共享代码项目添加了一个 .def 文件,其中包含以下内容:

\n
language = Objective-C\nmodules = SlicerUtils\npackage = com.xxxx.customframework\n
Run Code Online (Sandbox Code Playgroud)\n

build.gradle.kts 文件是使用 Android Studio 最新版本 (4.2.idontremember) 中提供的 KMM 项目模板生成的标准文件。然后我添加了 iosX64 和 iosArm64 部分,如上面链接中所述:

\n
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget\n\nplugins {\n    id("com.android.library")\n    kotlin("multiplatform")\n    kotlin("plugin.serialization") version "1.4.10"\n\n\n\n    id("kotlin-android-extensions")\n\n}\ngroup = "con.xxxx.customframework"\nversion = "1.0"\n\nrepositories {\n    gradlePluginPortal()\n    google()\n    jcenter()\n    mavenCentral()\n}\nkotlin {\n    android()\n    ios {\n        binaries {\n            framework {\n                baseName = "shared"\n            }\n        }\n    }\n\n\n\n\n\n    //////////////////////////\n\n    val iosFrameworkBaseDir = "${projectDir}/../../ios-frameworks"\n    val slicerUtilsDir = file("$iosFrameworkBaseDir/SlicerUtils/SlicerUtils").absolutePath\n\n\n    val slicerUtilsBaseFrameworkDirX64 = file("$slicerUtilsDir/DerivedData/SlicerUtils/Build/Products/Debug-iphonesimulator/SlicerUtils.framework").absolutePath\n    val slicerUtilsBaseBuildDirArm64 = file("$slicerUtilsDir/DerivedData/SlicerUtils/Build/Products/Debug-iphoneos/SlicerUtils.framework").absolutePath\n\n    iosX64() {\n        compilations.getByName("main") {\n            val slicerUtils  by cinterops.creating {\n\n                defFile("SwiftSlicerUtils.def")\n\n               compilerOpts("-framework", "SlicerUtils", "-F${slicerUtilsDir}")\n               \n\n            }\n\n        }\n\n        binaries.all {\n            // Linker options required to link to the library.\n            linkerOpts("-L$slicerUtilsBaseFrameworkDirX64", "-lSlicerUtils")\n        \n        }\n    }\n\n    iosArm64() {\n        compilations.getByName("main") {\n            val slicerUtils by cinterops.creating {\n\n                defFile("SwiftSlicerUtils.def")\n\n                compilerOpts("-framework", "SlicerUtils", "-F${slicerUtilsDir}")\n                \n\n            }\n\n        }\n\n        binaries.all {\n            // Linker options required to link to the library.\n              linkerOpts("-L$slicerUtilsBaseBuildDirArm64", "-lSlicerUtils")\n        }\n    }\n    /////////////////////////\n\n\n    sourceSets {\n        val commonMain by getting {\n            dependencies {\n                implementation("org.jetbrains.kotlin:kotlin-stdlib-common")\n                implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.0.1")\n                implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1")\n            }\n        }\n        val commonTest by getting {\n            dependencies {\n                implementation(kotlin("test-common"))\n                implementation(kotlin("test-annotations-common"))\n\n\n            }\n        }\n        val androidMain by getting {\n            dependencies {\n\n                implementation("org.jetbrains.kotlin:kotlin-stdlib")\n                implementation("org.jsoup:jsoup:1.13.1")\n            }\n        }\n        val androidTest by getting {\n            dependencies {\n                implementation(kotlin("test-junit"))\n                implementation("junit:junit:4.13")\n            }\n        }\n        val iosMain by getting\n        val iosTest by getting\n    }\n}\nandroid {\n    compileSdkVersion(29)\n    sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")\n    defaultConfig {\n        minSdkVersion(23)\n        targetSdkVersion(29)\n        versionCode = 1\n        versionName = "1.0"\n    }\n    buildTypes {\n        getByName("release") {\n            isMinifyEnabled = true\n        }\n    }\n}\nval packForXcode by tasks.creating(Sync::class) {\n    group = "build"\n    val mode = System.getenv("CONFIGURATION") ?: "DEBUG"\n    val sdkName = System.getenv("SDK_NAME") ?: "iphonesimulator"\n    val targetName = "ios" + if (sdkName.startsWith("iphoneos")) "Arm64" else "X64"\n    val framework =\n        kotlin.targets.getByName<KotlinNativeTarget>(targetName).binaries.getFramework(mode)\n    inputs.property("mode", mode)\n    dependsOn(framework.linkTask)\n    val targetDir = File(buildDir, "xcode-frameworks")\n    from({ framework.outputDirectory })\n    into(targetDir)\n}\ntasks.getByName("build").dependsOn(packForXcode)\n
Run Code Online (Sandbox Code Playgroud)\n

我收到的错误如下:

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

我尝试了框架文件夹路径中存在的几乎所有组合,但没有成功,但在粘贴的示例中,我使用compileropts命令提供框架根文件夹的路径,以及每个框架的构建文件夹的路径使用 linkeropts 命令的体系结构。正如我所说,我尝试了这个和其他组合,但没有成功。

\n

作为一个一般性问题,当官方文档说:

\n
\n

使用 -framework 选项将框架名称传递给编译器和链接器。使用 -F 选项将框架源代码和二进制文件的路径传递给编译器和链接器。

\n
\n
    \n
  • 错误的模块名称是什么?
  • \n
  • 框架名称是什么?xCode 中的项目名称?
  • \n
  • 框架源的路径是该框架的swift文件的路径,还是框架的根文件夹的路径还是什么?
  • \n
  • 框架的二进制文件存储在哪里?我认为二进制文件是以下文件,但我不确定:\n介绍 aqu\xc3\xad 图像的描述\xc3\xb3n
  • \n
\n

也许你可以指出我做错了什么。先感谢您!

\n