🌚

Kam's Online Notebook


解决 ARM Simulator 的 link 错误

为什么在 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

WHY IT WORKS

网上不少人通过EXCLUDED_ARCHS[sdk=iphonesimulator*] = arm64 解决上面这个问题了,实际上这是让 Xcode 编译一个 X86 模拟器版本的 app,然后通过 Rosetta 2 在 ARM Mac 上运行,这种方式不够 native,还是敦促下 SDK 提供商更新比较好。

EOF

— Jun 2, 2021