Apple has changed instruction sets over the years. Because individual programs can run on multiple machines, Apple uses live binary files created by the lipo tool. You tell Xcode to compile your program several times, once for each type of machine, and lipo binds them together.
Apple recently released its fourth iOS instruction set. The first phones used Armv6, the 3GS we had Armv7, a few new instructions were added for Armv7s, and now 5S adds Arm64.
I like my programs to work under various operating systems, so I set MIN_DEPLOYMENT_TARGET to 5.0, so Apple will download the program on machines from 5.0 to. But when I try that in the current version of Xcode, I get an error message saying that this is not possible in Arm64.
OK, I set the conditional settings for the assembly: MIN_DEPLOYMENT_TARGET - 5.0 for architectures other than Arm64, but for Arm64 it is set to 7.0. Now the program compiles, links and lipo. But now, since one of the compilations is only iOS 7.0, I get a bunch of warnings that my program contains calls for older operating systems. I know it. This is intentional - so the program will work on those old systems. In iOS 7, these old procedures are not called, and at run time the program calls them modern replacements. I can make the compiler stop complaining:
#pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations"
and the program works fine on iOS 7 devices, both Armv7 and Arm64. A bit of diagnostic code verifies that the Arm64 plug is actually used when running on an Arm64 device.
Running lipo in binary reports that it has the expected architectures.
But, and this is big: when I try to install the application on the iOS 5 device, Xcode simply puts a warning: "There was an internal API error."
I think there is a bug in iOS 5 and iOS 6, so they don’t ignore the plugs that come from the future. The loader should simply ignore forks that it does not recognize. But that is not how it works.
Apple is never going to fix iOS 5. I thought that Apple could solve the problem when the application loads onto the device: Xcode cuts out the unnecessary plug and overwrites the (now modified) binary. Similarly, downloading from iTunes may remove the unwanted plug and rewrite it. But Apple is unlikely to do this: Apple wants everyone who can upgrade to iOS7. Apple's solution for those who cannot upgrade is to buy new hardware.
So we are stuck. You can have one header in the app store that supports 5 and 6, and release an update that will contain 7 that is fat armv7 and arm64, so your users who have iOS7 will become fat, and your users who have 5 or 6 will get the old one, but you can only do it once. After you publish update 7, you will never be able to update update 5 & 6 again.
Is there any way around this? I want one program to work on Armv7 and Arm64, and iOS 5 and 6 for the armv7 side, iOS 7 for armv7 on a hard drive other than arm64, and iOS 7 arm64, where supported, How?