为什么在 M1 模拟器上 run 不起来,而出现下面的错误:
building for iOS Simulator, but linking in object file built for iOS, for architecture arm64
字面意思原因是第三方的 binary 没有 ARM64 iOS Simulator 的 slice,导致 link 失败(btw 现在很多 SDK 都还没能提供 XCFramework 版本)。有些「偷摸大吉」直觉上认为 M1 也是 ARM 架构,可以编译给 iOS Device 运行的 app,也应该能让 M1 模拟器运行才对。
这种直觉很准,但没完全准。
这个 binary 有 x86_64 Simulator 及 ARM64 Device 两个 slice,而我们的 target 是 ARM64 Simlator,那 ld 是怎么识别这几个类型?通过 otool -l your_binary
可以看到,两个在 load command 上是有差异的:
其中 2 与 7 的值参考这里
// Note, this should match PLATFORM_* values in <mach-o/loader.h>
enum class Platform {
unknown = 0,
macOS = 1, // PLATFORM_MACOS
iOS = 2, // PLATFORM_IOS
tvOS = 3, // PLATFORM_TVOS
watchOS = 4, // PLATFORM_WATCHOS
bridgeOS = 5, // PLATFORM_BRIDGEOS
iOSMac = 6, // PLATFORM_MACCATALYST
iOS_simulator = 7, // PLATFORM_IOSSIMULATOR
tvOS_simulator = 8, // PLATFORM_TVOSSIMULATOR
watchOS_simulator = 9, // PLATFORM_WATCHOSSIMULATOR
driverKit = 10, // PLATFORM_DRIVERKIT
};
理论上对 mach-o 做一定对修改,能将 ARM64 Device 的 slice 当作 ARM64 Simulator 使用。搜了下原来已经有大佬整活儿了,参考 Hacking native ARM64 binaries to run on the iOS Simulator。
网上不少人通过EXCLUDED_ARCHS[sdk=iphonesimulator*] = arm64
解决上面这个问题了,实际上这是让 Xcode 编译一个 X86 模拟器版本的 app,然后通过 Rosetta 2 在 ARM Mac 上运行,这种方式不够 native,还是敦促下 SDK 提供商更新比较好。
— Jun 2, 2021