You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何构建无需Rosetta即可在M1 Xcode运行的KMM XCFramework

解决M1设备Xcode无需Rosetta运行KMM XCFramework的问题

问题背景

在M1设备的Xcode中不启用Rosetta运行时,使用自行构建的KMM XCFramework出现链接错误,提示找不到iOS Simulator-arm64架构的符号。原构建脚本仅打包了真机arm64和模拟器x86_64架构,无法适配M1原生模拟器。

原Shell构建脚本

#!/bin/bash

./gradlew :shared:packForXCodeArm -PXCODE_CONFIGURATION=Release
./gradlew :shared:packForXCodeX64 -PXCODE_CONFIGURATION=Release
FRAMEWORK_NAME="shared"
ARM64PATH="shared/build/xcode-framework-arm/${FRAMEWORK_NAME}.framework"
X64PATH="shared/build/xcode-framework-X64/${FRAMEWORK_NAME}.framework"
UNIVERSAL_PATH="shared/build/xcode-framework-universal/"

xcodebuild -create-xcframework -framework "${ARM64PATH}" -framework "${X64PATH}" -output "${UNIVERSAL_PATH}/${FRAMEWORK_NAME}.xcframework"

原build.gradle.kts配置

val packForXcodeArm by tasks.creating(Sync::class) {
    group = "build"
    val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
    val framework = kotlin.targets.getByName<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget>("iosArm64").binaries.getFramework(mode)
    inputs.property("mode", mode)
    dependsOn(framework.linkTask)
    val targetDir = File(buildDir, "xcode-framework-arm")
    from({ framework.outputDirectory })
    into(targetDir)
}

val packForXcodeX64 by tasks.creating(Sync::class) {
    group = "build"
    val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
    val framework = kotlin.targets.getByName<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget>("iosX64").binaries.getFramework(mode)
    inputs.property("mode", mode)
    dependsOn(framework.linkTask)
    val targetDir = File(buildDir, "xcode-framework-X64")
    from({ framework.outputDirectory })
    into(targetDir)
}

报错信息

ld: warning: ignoring file /Users/.../Library/Developer/Xcode/DerivedData/froeling_ios-dwqfcfqkcvofjtgtuipjhkedehfx/Build/Products/Debug-iphonesimulator/shared.framework/shared, building for iOS Simulator-arm64 but attempting to link with file built for iOS Simulator-x86_64
Undefined symbols for architecture arm64:
  "_OBJC_CLASS_$_SharedNetworkRequests", referenced from:
      objc-class-ref in LoginView.o

解决方案

要适配M1原生模拟器,需要补充打包iOS Simulator-arm64架构,并将其与模拟器x86_64合并为通用模拟器framework,再与真机framework一起构建XCFramework。

1. 更新build.gradle.kts,添加Simulator Arm64打包任务

在原配置基础上,新增针对iosSimulatorArm64目标的打包任务:

val packForXcodeSimulatorArm by tasks.creating(Sync::class) {
    group = "build"
    val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
    val framework = kotlin.targets.getByName<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget>("iosSimulatorArm64").binaries.getFramework(mode)
    inputs.property("mode", mode)
    dependsOn(framework.linkTask)
    val targetDir = File(buildDir, "xcode-framework-simulator-arm")
    from({ framework.outputDirectory })
    into(targetDir)
}

同时确保KMM的iOS目标已包含iosSimulatorArm64:

kotlin {
    ios {
        binaries.framework {
            baseName = "shared"
        }
        targets {
            iosArm64()
            iosX64()
            iosSimulatorArm64() // 确认此目标已添加
        }
    }
    // 其他配置...
}

2. 更新Shell构建脚本

修改脚本,打包三个架构并合并模拟器架构:

#!/bin/bash

# 打包三个目标架构
./gradlew :shared:packForXcodeArm -PXCODE_CONFIGURATION=Release
./gradlew :shared:packForXcodeX64 -PXCODE_CONFIGURATION=Release
./gradlew :shared:packForXcodeSimulatorArm -PXCODE_CONFIGURATION=Release

FRAMEWORK_NAME="shared"
# 各架构framework路径
DEVICE_ARM_PATH="shared/build/xcode-framework-arm/${FRAMEWORK_NAME}.framework"
SIM_X64_PATH="shared/build/xcode-framework-X64/${FRAMEWORK_NAME}.framework"
SIM_ARM_PATH="shared/build/xcode-framework-simulator-arm/${FRAMEWORK_NAME}.framework"
# 临时目录:合并后的模拟器通用framework
UNIVERSAL_SIM_PATH="shared/build/xcode-framework-universal-simulator"
# 最终XCFramework输出目录
FINAL_UNIVERSAL_PATH="shared/build/xcode-framework-universal"

# 创建合并后的模拟器framework目录
mkdir -p "${UNIVERSAL_SIM_PATH}/${FRAMEWORK_NAME}.framework"
# 复制资源文件和Info.plist(从x64架构复制即可)
cp -r "${SIM_X64_PATH}/." "${UNIVERSAL_SIM_PATH}/${FRAMEWORK_NAME}.framework/"
# 合并模拟器的x86_64和arm64二进制文件
lipo -create "${SIM_X64_PATH}/${FRAMEWORK_NAME}" "${SIM_ARM_PATH}/${FRAMEWORK_NAME}" -output "${UNIVERSAL_SIM_PATH}/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}"

# 构建最终的XCFramework,包含真机和通用模拟器framework
xcodebuild -create-xcframework \
    -framework "${DEVICE_ARM_PATH}" \
    -framework "${UNIVERSAL_SIM_PATH}/${FRAMEWORK_NAME}.framework" \
    -output "${FINAL_UNIVERSAL_PATH}/${FRAMEWORK_NAME}.xcframework"

3. 验证结果

构建完成后,使用lipo -info查看XCFramework内的二进制架构:

lipo -info shared/build/xcode-framework-universal/shared.xcframework/ios-arm64/shared.framework/shared
# 输出:Non-fat file: ... is architecture: arm64

lipo -info shared/build/xcode-framework-universal/shared.xcframework/ios-x86_64-simulator/shared.framework/shared
# 输出:Architectures in the fat file: ... are: x86_64 arm64

此时XCFramework同时支持真机arm64、模拟器x86_64和arm64,无需启用Rosetta即可在M1设备的Xcode中正常运行。

内容的提问来源于stack exchange,提问作者swalkner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 05:25:29