ios - 无法将 iOS 自定义框架添加到 KMM(Kotlin 多平台)模块(找不到 cinteropXXXIosArm64 FAILED 模块)
问题描述
我正在开发一个使用 Kotlin Native 共享模块的 iOS 应用程序。这个 Kotlin Native 共享模块,利用了自研的 iOS 框架。
这在过去效果很好,但现在我正在尝试将我的项目升级为 Kotlin Native 的最新版本(此时为 1.4.10)、Android Studio 等,但我无法导入我的自定义 iOS 框架依赖项。
按照https://kotlinlang.org/docs/mobile/add-dependencies.html上的指南,我在共享代码项目中添加了一个 .def 文件,其中包含以下内容:
language = Objective-C
modules = SlicerUtils
package = com.xxxx.customframework
build.gradle.kts 文件是使用 Android Studio 最新版本 (4.2.idontremember) 中可用的 KMM 项目模板生成的标准文件。然后我添加了 iosX64 和 iosArm64 部分,如上面链接中所述:
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)
我收到的错误如下:
> 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.
我尝试了几乎所有从框架文件夹的路径存在的组合,但没有成功,但在粘贴的示例中,我使用 compileropts 命令提供框架根文件夹的路径,以及每个架构的构建文件夹的路径使用 linkeropts 命令。如前所述,我尝试了这个和其他组合,但没有成功。
作为一个一般性问题,当官方文档说:
使用 -framework 选项将框架名称传递给编译器和链接器。使用 -F 选项将框架源和二进制文件的路径传递给编译器和链接器。
- 错误的模块名称是什么?
- 框架名称是什么?xCode 中的项目名称?
- 框架源的路径是这个框架的swift文件的路径,还是框架的根文件夹或什么?
- 框架的二进制文件存储在哪里?我想二进制文件是以下文件,但我不确定:
也许你可以指出我做错了什么。先感谢您!
解决方案
推荐阅读
- scala - 相同的行为 Scala Spark Sample 和 SampleBy
- python - 如何在 SimPy 4 中终止模拟
- logging - 为什么 Greylog 和 Grafana 显示的数据存在差异?
- html - 在页面加载时显示工具提示然后自动隐藏
- r - 从熔体数据框中计算百分比
- apache-nifi - JoltTransformJSON - 3 个 JSON 转换
- python - 在 Python 中永久更新字典
- kubernetes - Kubernetes - 按服务名称调用微服务
- angular - 如何以编程方式从组件类中选择角度引导导航选项卡
- c - C编程中位数的问题