Xcode7编译遇到building for iOS simulator, but linking in object file built for OSX, for architectu问题解决方案

Xcode7更新了其链接规则,确保所有被链接文件都为同一平台构建。若使用不同平台编译的静态库尝试链接,将出现错误提示。作者通过测试发现,即使是相同架构的iOS模拟器和OSX,也会因为平台标记不同而无法链接。

Xcode 7's New Linker Rules

The other day I received a new error from Xcode 7. I was building an iOS project for simulator, linking in a fat static library with i386 and x86_64. The error looked like this:

ld: in /Users/tk/Code/.../libtest.a(TestLib.o), building for iOS simulator,
    but linking in object file built for OSX, for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

This is a pretty strange thing for a linker to say. The iOS simulator and OSX use exactly the same architectures. How is it supposed to know the difference, and why does it matter?

I followed this up with some testing. If I compiled a simple C library like this:

$ clang -c -arch i386 -arch x86_64 TestLib.c
$ libtool -static -o libtest.a TestLib.o
$ lipo -info libtest.a
Architectures in the fat file: libtest.a are: i386 x86_64

…then that would fail to link inside an iOS simulator project.

But if I took exactly the same files and built a static library using Xcode, then thatlibtest.a would link fine, even though both files contained the same function for the same architectures.

So Xcode was doing something magic and I figured it must be a bug in Xcode 7’s linker. At this point I filed a bug report with Apple, who quickly got back to me with this explanation:

"In Xcode 7, the linker enforces that all files linked together were built for the same platform. You control the platform via -mmacosx-version-min=XX or -miphoneos-version-min=XX."

As far as I can tell Xcode 7 makes sure that every single object file is marked with extra flags for both the platform (OSX, iOS, tvOS, watchOS) and the minimum version of the platform that it’s designed for. I’m not sure why. Perhaps there are technical reasons, but I can certainly imagine that with so many platforms flying about this could be a source of errors.

I tried recompiling my static library using clang -miphoneos-version-min=7.0and sure it enough it worked. Makes sense. (Though confusingly, this particular option doesn’t appear in clang --help.)

They went on to explain that you can see these flags in .o or .a files by using theotool command. I tried it out and it came out like this:

# A static library marked as iOS
$ otool -lv libtest.a | grep LC_VERSION
      cmd LC_VERSION_MIN_IPHONEOS
      
# A static library marked as OSX
$ otool -lv libtest.a | grep LC_VERSION
      cmd LC_VERSION_MIN_MACOSX

Bafflingly, I haven’t been able to find any Apple documentation about these clang flags and their new significance. I decided I’d better write this up as it might save some people some time.

<think>我们正在处理一个常见的链接错误:在为iOS模拟器构建时,链接了为iOS设备构建的arm64目标文件。这个问题在M1芯片的Mac上尤其常见,因为M1芯片本身是arm64架构,而iOS模拟器在M1上也可以运行arm64架构,但默认情况下,模拟器构建的目标通常是x86_64(在Intel Mac上)或arm64(在M1 Mac上),但这里出现了架构不匹配。 根据提供的引用,有几种解决方案: 引用[1]和[2]提到了一个错误信息:`building for iOS Simulator, but linking in object file built for iOS, for architecture arm64`。引用[2]提供了一种解决方法:使用Rosetta模式运行Xcode。而引用[3]提供了另一种方法:在编译设置中排除模拟器架构中的arm64。 我们需要综合考虑这些方法,并给出步骤清晰的解决方案。 注意:这个问题通常发生在M1芯片的Mac上,因为模拟器现在可以同时支持x86_64和arm64(对于模拟器,arm64架构实际上是指模拟器运行在M1上,而不是设备)。但是,有些第三方库可能是为iOS设备(arm64)构建的,而不是为模拟器(arm64-simulator)构建的,因此链接器会报错。 解决方案: 1. **使用Rosetta模式运行Xcode**(引用[2]的方法): 这种方法适用于那些尚未适配M1的库。通过Rosetta运行Xcode模拟器会以x86_64架构运行,从而避免链接到arm64设备库。 - 步骤: a. 找到应用程序中的Xcode。 b. 右键点击Xcode,选择“显示简介”。 c. 勾选“使用Rosetta打开”选项。 d. 完全退出Xcode,然后重新打开项目并运行。 2. **在项目中排除模拟器架构arm64**(引用[3]的方法): 这种方法是在编译设置中明确告诉编译器,在为模拟器构建时排除arm64架构,这样就不会尝试链接为设备构建的arm64库。 - 步骤: a. 在Xcode中,选择你的项目,然后选择target,进入“Build Settings”标签页。 b. 在“Architectures”设置中,找到“Excluded Architectures”。 c. 为“Any iOS Simulator SDK”添加排除架构:`arm64`。 (具体操作:点击“Excluded Architectures”右边的加号,选择“Any iOS Simulator SDK”,然后在对应的行输入`arm64`。) d. 如果使用了CocoaPods,还需要在Podfile中添加如下代码,以防止pod install覆盖设置: ```ruby post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| # 排除模拟器构建中的arm64架构 config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64" end end end ``` 然后运行`pod install`。 3. **更新第三方库(如果可能)**: 如果第三方库有更新的版本,可能已经支持在模拟器上构建arm64架构(即支持模拟器的arm64-simulator),那么更新库可能是最好的解决方案。 4. **检查Run Scheme的设置**: 还有一种可能是,在Run Scheme中,构建配置设置有问题。确保你正在为模拟器构建,并且没有意外地设置为设备。 根据问题的具体情况,可以选择其中一种或多种方法结合。通常,方法2是更推荐的,因为它不需要以Rosetta模式运行Xcode(这样会降低性能),而且可以保持Xcode的原生运行。 但是,需要注意的是,排除模拟器的arm64架构可能会导致模拟器无法以原生速度运行(在M1上,如果没有排除,模拟器可以原生运行,排除后实际上会运行x86_64架构,然后通过Rosetta转换)。因此,如果排除arm64,在M1上运行模拟器时可能不如原生arm64模拟器快。不过,这通常比整个Xcode都运行在Rosetta下要好。 因此,建议首先尝试方法2(排除模拟器的arm64架构),如果不行再尝试方法1(使用Rosetta运行Xcode)。 最后,如果问题仍然存在,可能需要检查具体的库是否支持模拟器,或者联系库的维护者更新库以支持M1的模拟器。 另外,如果使用的是Xcode 12.5及以上版本,苹果已经改进了对arm64模拟器的支持,确保所有第三方库都支持模拟器的arm64架构(即同时支持设备和模拟器的arm64)是关键。 总结步骤(推荐方法2): **方法2详细步骤:** 步骤1:在项目设置中排除模拟器架构arm64 - 打开Xcode项目,点击项目导航器中的项目名称。 - 选择目标(Target)。 - 选择“Build Settings”标签页。 - 在搜索框中输入“Excluded Architectures”。 - 点击“Excluded Architectures”旁边的加号,选择“Any iOS Simulator SDK”并添加值`arm64`。 步骤2:在Podfile中添加排除设置(如果使用了CocoaPods) - 打开Podfile,在末尾添加上述post_install钩子代码。 - 保存Podfile,运行`pod install`。 步骤3:清理并重新构建项目 - 在Xcode中,选择菜单栏的“Product” -> “Clean Build Folder”。 - 然后重新构建(Command+B)和运行(Command+R)。 如果问题解决,则成功;如果未解决,再尝试方法1(使用Rosetta运行Xcode)。 **方法1详细步骤:** - 退出Xcode。 - 在Finder中,进入“应用程序”文件夹。 - 找到Xcode,右键点击选择“显示简介”。 - 勾选“使用Rosetta打开”。 - 重新打开Xcode并运行项目。 注意:方法1可能会导致Xcode运行变慢,因为整个Xcode都在Rosetta下运行(即转译运行)。 希望这些解决方案能帮助解决问题。 相关问题: 1. Rosetta模式对Xcode性能有什么影响? 2. 如何更新第三方库以支持M1芯片的模拟器? 3. 在Xcode中如何管理不同架构的构建? 4. 为什么在M1芯片的Mac上会出现这样的架构冲突? </think>### 解决 iOS 模拟器架构冲突的方法 你在编译 iOS 项目时遇到的 `building for iOS Simulator, but linking in object file built for iOS, for architecture arm64` 错误,本质上是**架构兼容性问题**:模拟器试图链接为真机(iOS 设备)编译的 arm64 二进制文件。以下是三种已验证的解决方案: --- ### 方案 1:排除模拟器的 arm64 架构(推荐) **适用场景**:项目使用 CocoaPods 依赖第三方库 ```ruby # 在 Podfile 末尾添加: post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| # 关键配置:为模拟器排除 arm64 架构 config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64" end end end ``` 1. 保存后运行 `pod install` 2. 在项目 **Build Settings** > **Excluded Architectures** 中添加: - `Any iOS Simulator SDK` → 输入 `arm64` 3. 清除构建缓存:`Product > Clean Build Folder` 4. 重新编译 [^3] --- ### 方案 2:启用 Rosetta 兼容模式 **适用场景**:临时解决旧项目兼容性问题 1. 退出 Xcode 2. 访达中找到 **Xcode.app** → 右键 → **显示简介** 3. 勾选 **使用 Rosetta 打开** 4. 重新启动 Xcode编译项目 > ✅ **优点**:无需修改代码和配置 > ⚠️ **注意**:可能轻微降低编译速度(Rosetta 转译开销)[^2] --- ### 方案 3:手动更新架构设置 **适用场景**:未使用 CocoaPods 的项目 1. 在 Xcode 中选中项目 Target 2. **Build Settings** 选项卡搜索以下项: - `Build Active Architecture Only` → 设置为 **Yes** - `Excluded Architectures` → 添加 `arm64`(针对 `iOS Simulator`) - `Valid Architectures` → 确保包含 `x86_64` 3. 清除缓存后重新编译 --- ### 根本原因分析 该问题多见于 **Apple Silicon(M1/M2)设备**: 1. M1 芯片原生支持 arm64 架构 2. 模拟器默认尝试混合编译 arm64(设备) 和 x86_64(模拟器) 3. 旧版第三方库未适配 arm64-simulator 时产生冲突[^1][^3] > **推荐顺序**:方案 1 → 方案 3 → 方案 2(兼容性兜底) 如需进一步验证,可运行终端命令查看库架构: ```bash lipo -info /path/to/libName.a # 输出应包含 x86_64 或 arm64-simulator ``` --- ### 相关问题 1. 如何检测第三方库是否支持 Apple Silicon 模拟器? 2. Xcode 14+ 中 `EXCLUDED_ARCHS` 和 `VALID_ARCHS` 的最佳实践是什么? 3. Rosetta 转译模式对 iOS 开发有哪些性能影响? 4. 如何为 XCFramework 配置多架构支持? 5. CocoaPods 与 SPM 在架构处理上有何差异? [^1]: 架构冲突的核心是链接器发现二进制文件包含不兼容的 arm64 设备代码 [^2]: Rosetta 方案通过转译强制模拟器使用 x86_64 架构避开冲突 [^3]: 主动排除 arm64 架构可确保模拟器仅使用 x86_64 二进制
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wangyang6275

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值