多年来,Apple 已经改变了指令集。由于单个程序可能需要在不止一种机器上运行,Apple 使用由名为“lipo”的工具构建的“fat binaries”。您告诉 Xcode 多次编译您的程序,每种机器类型一次,然后 lipo 将它们绑定在一起。
Apple 最近推出了第四个 iOS 指令集。第一部手机使用 Armv6,从 3GS 开始,我们有 Armv7,为 Armv7s 添加了一些新指令,现在,5S 添加了 Arm64。
我喜欢我的程序在一系列操作系统下运行,所以我将我的 MIN_DEPLOYMENT_TARGET 设置为 5.0,因此 Apple 将从 5.0 开始将程序加载到机器上。但是当在当前版本的 Xcode 中尝试时,我收到一条错误消息,指出这在 Arm64 中是不可能的。
好的,我设置了条件构建设置:对于 Arm64 以外的架构,MIN_DEPLOYMENT_TARGET 为 5.0,但对于 Arm64,它设置为 7.0。现在程序编译、链接和 lipos。但是现在,由于其中一个编译器仅适用于 iOS 7.0,我收到一堆警告,说我的程序包含对旧操作系统的调用。我知道。这是故意的 - 所以程序将在那些旧系统上运行。在 iOS 7 系统上,这些旧例程不会被调用,而是在运行时,程序调用它们的现代替换。我可以让编译器停止抱怨:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
// old code here.
#pragma clang diagnostic pop
该程序在 iOS 7 设备上运行良好,包括 Armv7 和 Arm64。一段诊断代码验证了在 Arm64 设备上运行时,实际使用的是 Arm64 分支。
在二进制文件上运行 lipo 报告它具有预期的体系结构。
但是,这是一个很大的问题:当我尝试在 iOS 5 设备上安装该应用程序时,Xcode 只是发出警告:“存在内部 API 错误。”
我认为 iOS 5 和 iOS 6 中存在一个错误,因此他们不会忽略来自未来的分叉。加载程序应该简单地忽略它无法识别的分叉。但这不是它的工作方式。
Apple 永远不会修复 iOS 5。我认为 Apple 可能会在将应用程序加载到设备上时解决这个问题:让 Xcode 剥离不需要的 fork,然后重新签署(现已修改的)二进制文件。同样,从 iTunes 下载可能会剥离不需要的分叉并重新签名。但苹果不太可能这样做:苹果希望每个有能力的人都能升级到 iOS7。对于那些无法升级的人,Apple 的解决方案是:购买新硬件。
所以,我们被困住了。您可以在应用商店中拥有一个支持 5&6 的单个标题,然后发布针对 7 的更新,即胖 armv7 和 arm64,这样您的 iOS7 用户将获得胖子,而您拥有 5 或 6 的用户将获得旧的,但你只能做一次。发布 7 更新后,您将永远无法再更新 5 和 6 更新。
有没有解决的办法?我想要一个在 Armv7 和 Arm64 上运行的单个程序,以及用于 armv7 端的 iOS 5 和 6,用于 armv7 的 iOS 7 更难,不是 arm64 和支持它的 iOS 7 arm64,如何?