How to support both armv6 and armv7s for release build in xcode 4.5
Asked Answered
P

7

53

I know that this is not possible and Apple planned it this way to force the users to upgrade their devices. But I just want to know if there is some workaround or hacks in able to do this? The client insists that we should still support armv6 because of a still "large" percentage of the app users.

I know a command called lipo to merge static libraries and I read somewhere that we can also use it to merge ipa files but I'm not sure how its exactly done. I did a couple of searching around already on google and this site, buts its hard to find a concrete answer.

Posterior answered 27/9, 2012 at 10:19 Comment(0)
M
93

I've been able to do this successfully with my app that's in the App Store. It supports armv6, armv7, and armv7s and iOS versions from 4.2 to 6.0. I've verified that it runs on older devices (iPhone 3G, iPod touch 2g) all the way through the iPhone 5.

This method requires having both Xcode 4.5 and an older version of Xcode installed simultaneously. I'm still on 4.3.2 for my older version, but 4.4 should work as well.

I had screenshots for this answer, but Stack Overflow won't let me post them because I'm new. :(

Setup in Xcode 4.5

  1. Add a new build configuration for your armv6 build. I duplicated the Release config and named it Release_armv6.

  2. Set the Architectures and Valid Architectures for your build configurations. For all but Release_armv6, use the default. For Release_armv6, manually set it to armv6. https://i.sstatic.net/h8Mpl.png

  3. If you're using iOS 6 features that Xcode 4.4 and below won't understand, you'll need to #ifdef these out for your armv6 build. In Build Settings under Other C Flags and Other C++ Flags I added -DARMV6_ONLY to my Release_armv6 config. Then wherever the code uses a new iOS 6 API, I do something like #ifndef ARMV6_ONLY / #endif as appropriate. https://i.sstatic.net/czF6J.png

  4. Add a new scheme and set it to use the Release_armv6 build configuration in all cases.

  5. Under Build Phases, add a Run Script Build Phase with the following script (set the Shell to /bin/csh). This is where the magic happens. Edit the Configuration section: Determine your full path to the Release_armv6 build and substitute it for ARMV6_EXECUTABLE_PATH. Also set MINIMUM_OS.



    #
    # Script to add armv6 architecture to iOS executable built with Xcode 4.5
    #

    #################
    # Configuration #
    #################
    # Change this to the full path where Xcode 4.4 (or below) puts your armv6 output
    setenv ARMV6_EXECUTABLE_PATH "$BUILD_ROOT/Release_armv6-iphoneos/$EXECUTABLE_PATH"

    # Your "real" minimum OS version since Xcode 4.5 wants to make it iOS 4.3
    # Must be 4.2 or below if you are supporting armv6...
    setenv MINIMUM_OS 4.2
    #####################
    # End configuration #
    #####################


    # For debugging
    echo CURRENT_ARCH = $CURRENT_ARCH
    echo CONFIGURATION = $CONFIGURATION

    # Don't need to do this for armv6 (built in older Xcode), simulator (i386), or debug build
    if ("$CURRENT_ARCH" == "armv6") exit 0
    if ("$CURRENT_ARCH" == "i386") exit 0
    if ("$CONFIGURATION" != "Release" && "$CONFIGURATION" != "Beta Test") exit 0

    # Paths
    setenv LIPO_PATH "$CODESIGNING_FOLDER_PATH/${EXECUTABLE_NAME}.lipo"
    setenv FINAL_PATH "$CODESIGNING_FOLDER_PATH/$EXECUTABLE_NAME"
    setenv FULL_INFO_PLIST_PATH "$CONFIGURATION_BUILD_DIR/$INFOPLIST_PATH"

    # Debug / sanity check
    lipo -info "$FINAL_PATH"
    ls -l "$ARMV6_EXECUTABLE_PATH"

    # Make sure something exists at $LIPO_PATH even if the next command fails
    cp -pv "$FINAL_PATH" "$LIPO_PATH"

    # If rebuilding without cleaning first, old armv6 might already be there so remove it
    # If not, lipo won't output anything (thus the cp command just above)
    lipo -remove armv6 -output "$LIPO_PATH" "$FINAL_PATH"

    # Add armv6 to the fat binary, show that it worked for debugging, then remove temp file
    lipo -create -output "$FINAL_PATH" "$ARMV6_EXECUTABLE_PATH" "$LIPO_PATH"
    lipo -info "$FINAL_PATH"
    rm -f "$LIPO_PATH"

    # Change Info.plist to set minimum OS version to 4.2 (instead of 4.3 which Xcode 4.5 wants)
    /usr/libexec/PlistBuddy -c "Set :MinimumOSVersion $MINIMUM_OS" "$FULL_INFO_PLIST_PATH"
    plutil -convert binary1 "$FULL_INFO_PLIST_PATH"

Build Process

When you're ready to create a release build, do it in the following order:

  1. Close Xcode 4.5 and open Xcode 4.4 or below. Select your armv6 scheme and build it.

  2. Close Xcode 4.4 or below and open Xcode 4.5. Select your Release scheme and build it.

That's pretty much it. Check the build output to verify that you got what you want - an executable with three architectures in it. The last output from the run script should tell you this.

If anyone has ideas to improve this, please feel free. I imagine you might be able to get fancy and call Xcode 4.4's "xcodebuild" command from within the build script, alleviating the need to switch between Xcode versions at all. But this works well enough for me. ;)

Caveats:

  • Just to be safe, you might want to edit your xib files in the older version of Xcode. So far it seems like 4.5 is backwards compatible, but you never know.

  • In fact, you might consider just doing most of your development, except for iOS 6-specific stuff, in the older Xcode. Depends on whatever's easiest for you.

Marrowfat answered 1/10, 2012 at 17:29 Comment(18)
Have you had something accepted into the App Store using this method?Barmy
Yes, my latest update used this method and was accepted without issues by Apple.Marrowfat
Works like a charm ;) Thanks for the pretty clean instruction, I really appreciate it! My only problem now is how to make the external libraries I used to support all 3 architectures as well.Posterior
Can you support taller screens for iPhone5 by doing so? Because recently I've heard that if you target the iOS 5 SDK you’ll be rejected if you include an iPhone 5 launch image: t.co/2ZLU93KMProwel
@davsan, yes. In Xcode 4.5 your project builds against the iOS 6.0 SDK, and you can add the Retina 4 launch image. Xcode 4.4 will build against iOS 5.1 SDK, but remember that is only for generating the armv6 binary. Everything else in the finished app bundle comes from Xcode 4.5.Marrowfat
The method works perfectly, thanks! However, you don't need to do any plist changes, so the script could be simplifiedCausalgia
The one improvement I would suggest is: setenv ARMV6_EXECUTABLE_PATH "$BUILD_ROOT/Release_armv6-iphoneos/$EXECUTABLE_PATH" And then you don't have to search for this directory too much, and if Xcode for some reason re-generates its name, the script will pick it up immediately.Theravada
@Max, I didn't do a lot of testing myself (don't have an armv6 device so I had to rely on beta testers to verify) but the assumption was that something would break on older devices if I didn't reset the minimum OS in the plist. Either the app wouldn't run, wouldn't install, or wouldn't download from the App Store. Are you sure it would still work on 4.2 if MINIMUM_OS is set to 4.3 in the plist?Marrowfat
@PiotrKalinowski, thanks! That simplifies things; I edited the post to make the change.Marrowfat
@Mike, I have Deployment Target set to 3.0 in target Summary, and this goes as-is to binary plist packaged with the app. The app installs and runs on iPodTouch 1G (3.1.3)Causalgia
@Mike, how to make debug build with both architecture? i am following same steps to make debug build but its not showing armv6 architecture in it.is there any difference for that? can you please modify steps for debug build as well. Btw i am able to generate release build and its in approval process. Thanks for that.Clevelandclevenger
For debug builds you might want to use `setenv ARMV6_EXECUTABLE_PATH "$BUILD_ROOT/${CONFIGURATION}_armv6-iphoneos/$EXECUTABLE_PATH", and then you'd have to repeat the rest of the steps for debug, that is, create a Debug_armv6 configuration.Theravada
@Marrowfat There's one downside to $BUILD_ROOT that I discovered later: it won't work if you choose to run an Archive command. Then you'd have to preprocess $BUILD_ROOT. But it only matters if you really want to do that archive operation ;)Theravada
@Marrowfat Thanks for posting this. If I use any ios6 dependent framework (even with weak-link), then compiling in xcode4 shows 'framework not found' error. How to solve this?Nara
awesome! I was able to do this with Archiving from XCode 4.5, but only after I explicitly changed the ARMV6_EXECUTABLE_PATH.Bicarb
This "It supports armv6, armv7, and armv7s and iOS versions from 4.2 to 6.0." isn't really true, right? It doesn't support 4.2 on armv7 (or amrv7s) since that was build with the iOS 6 SDK which can only target 4.3 as a minimum. I realize that there probably aren't many people with armv7 devices still running 4.2, but I'm surprised that Apple is willing to accept a build like this. How do they communicate that it supports one minimum OS on some devices and a different minimum OS on different devices? Or do they just not care?Ashlaring
This is a great method for creating a universal app, however the crash reports do not work with symbolicatecrash regardless of whether I use the dSYM from Release_armv6-iphoneos or release-iphoneos. I have tried symbolicatecrash from 4.5 and 4.3. Have you found a way to get this to work?Bicarb
I would appreciate if you could post a little video tutorial on Youtube of the solution that you have proposed :) It will be really of a great help for newbies like me.Tonneson
L
26

There is a another way as gcc-4.2 still supports armv6, which won't require you to close Xcode 4.5 an open a previous version (for compilation, but not for running app on a 4.2 device) :

  • Add armv6 to both valid archs and archs :

Archs : $(ARCHS_STANDARD_32_BIT) armv6

Valid Architectures : armv6 armv7 armv7s

  • Vim (or TextEdit) your project.pbxproj file to replace IPHONEOS_DEPLOYMENT_TARGET to 4.0 - 4.1 - 4.2 as you need, Xcode 4.5 won't let you get below 4.3.

Then, if you build your project, you will see warnings :

warning: no rule to process file '$(PROJECT_DIR)/App/AppDelegate.m' of type sourcecode.c.objc for architecture armv6
warning: no rule to process file '$(PROJECT_DIR)/App/SomeFile.c' of type sourcecode.c.c for architecture armv6
  • Add a Build Rule for source files with names matching : *.[mc] that will use LLVM GCC 4.2

It works for static libraries, but not for apps :

ld: file is universal (4 slices) but does not contain a(n) armv6 slice: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib/crt1.3.1.o for architecture armv6
  • For making it works for apps, we need to add the armv6 slice to this object file (which comes with the 5.1 SDK) :
lipo /path/to-4.4/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/usr/lib/crt1.3.1.o -extract armv6 -output /tmp/crt1.3.1-armv6.o
lipo /Applications/Xcode.app/Contents//Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib/crt1.3.1.o /tmp/crt1.3.1-armv6.o -create -output /tmp/crt1.3.1-armv677s.o
mv /Applications/Xcode.app/Contents//Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib/crt1.3.1.o /Applications/Xcode.app/Contents//Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib/crt1.3.1.o.bkp
mv /tmp/crt1.3.1-armv677s.o /Applications/Xcode.app/Contents//Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib/crt1.3.1.o

Compile your project and check that your app contains all archs :

$ file DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app/TestApp 
DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app/TestApp: Mach-O universal binary with 3 architectures
DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app/TestApp (for architecture armv6): Mach-O executable arm
DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app/TestApp (for architecture armv7): Mach-O executable arm
DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app/TestApp (for architecture cputype (12) cpusubtype (11)):  Mach-O executable arm

Note that the dSYM file also contains all archs (useful for crash report symbolification) :

$ file DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app.dSYM/Contents/Resources/DWARF/TestApp 
DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app.dSYM/Contents/Resources/DWARF/TestApp: Mach-O universal binary with 3 architectures
DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app.dSYM/Contents/Resources/DWARF/TestApp (for architecture armv6):   Mach-O dSYM companion file arm
DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app.dSYM/Contents/Resources/DWARF/TestApp (for architecture armv7):   Mach-O dSYM companion file arm
DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app.dSYM/Contents/Resources/DWARF/TestApp (for architecture cputype (12) cpusubtype (11)):    Mach-O dSYM companion file arm

I've sucessfully installed and launched the app on an iOS 4.2 2gen iPod touch by opening xcode 4.4.1, then Product -> Run without building.

  • When you Archive your product, you may experience again the Apple Mach-O Linker error, this time involving other files, such as libarclite_iphoneos.a or libclang_rt.ios.a:
ld: file is universal (2 slices) but does not contain a(n) armv6 slice: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphoneos.a for architecture armv6
ld: file is universal (2 slices) but does not contain a(n) armv6 slice: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/4.1/libclang_rt.ios.a for architecture armv6

The procedure used for crt1.3.1.o applies to these files too, and will fix the error allowing Xcode to successfully archive your project: you can use the path printed by ld to find the file and join the armv6 slice with lipo; just keep in mind that libclang_rt.ios.a in the previous versions of Xcode isn't located in Xcode.app/[...]/usr/lib/clang/4.1 but in Xcode.app/[...]/usr/lib/clang/4.0.

I've successfully archived the file, deployed it with an ad-hoc distribution profile, and tested on iPhone 3G (4.2.1) and iPhone 3GS (6.0).

  • Last issue : we can't launch app. In the Organizer, there is the message : Devices of type “iPhone 3G” are not supported by this version of Xcode.

But an ls in the DeviceSupport shows :

 ls /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/ 
4.2          4.3          5.0          5.1          6.0 (10A403)

With no diffs in the 4.2 directory from Xcode 4.4.1.

The question is now : how Xcode detect is device is supported or not ?

Opening /Applications/Xcode.app/Contents/Developer//Platforms/iPhoneOS.platform/Developer//Library/PrivateFrameworks/DTDeviceKitBase.framework/DTDeviceKitBase with Hex Fiend (or another hex editor), and replacing ascii 4.3 with 4.2 make the error message disappear, and app installed on the device are listed (but device bullet in the device list is still red).

Then we need to edit /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks//DTDeviceKit.framework/Versions/Current/DTDeviceKit and replace :

Expired.deviceArchitecture.iPhone1,1.iPhone1,2.iPod1,1.iPod2,1.iPod2,2.armv6

to :

Expired.deviceArchitecture.iPhone0,1.iPhone0,2.iPod0,1.iPod0,1.iPod0,2.armv5

Then we have an orange bullet in the Organizer (Xcode 4.5.1) :

The version of iOS on “iPhone” is too old for use with this version of the iOS SDK. Please restore the device to a version of the OS listed below.

OS Installed on iPhone
4.2.1 (8C148)

Xcode Supported iOS Versions
6.0 (10A403)
5.1
5.0
4.3

The question is now : where Xcode Supported iOS Versions are defined ?

As there is a 4.2 directory in /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/, it should already be supported...

Tried to copy iPhoneOS4.2.sdk from Xcode 4.4.1 to /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/, but it don't make device supported.

So haven't found how to add 4.2 device support in Xcode 4.5. Any ideas ?

Conclusion : compiling for armv6/7/7s within Xcode 4.5 is possible. But it is not possible to start an app on a 4.2 armv6 device without starting Xcode 4.4.

Big update : it works with Xcode 4.5.2 !

Now the bullet is green in Xcode 4.5.2 :-) The device appear in the drop down list near the Run button. But when trying to run the app, got the message :

Xcode cannot run using the selected device.
Choose a destination with a supported architecture in order to run on this device.

Simply add armv6 to the valid architectures :-)

Other note : the Build Rule for source files with names matching : *.[mc] can use LLVM GCC 4.2 or Apple LLVM compiler 4.1, or Default compiler

Lights answered 11/10, 2012 at 9:50 Comment(10)
Successfully commited an App to the Store with these settings :-)Motel
Stuck at the lipo command part... I still have the error in xcode when compiling ..Selfexecuting
Fantastic work Kenji! It appears Apple is still going to great lengths to make our lives difficult. Just a note for other folks out there: The dots listed in the 2nd file to edit are NULL characters for me (0x00) on XCode 4.5.2Palecek
One other note. If you're using Apple LVVM 4.2, you're going to need to set "Implicitly Link Objective-C Runtime" in the "Apple LVVM compiler 4.2 Language" section to "NO" otherwise it will try to link the ARC stuff which doesn't appear to exist in the older armv6 versions of the static libraries.Palecek
It also works for 4.6 (but I haven't had time to test with 4.6.2).Motel
I can confirm that this way works for me for Xcode 4.6.2 although file which i updated was not crt1.3.1.o but crt1.oBiscay
Amazing... This answer is the best, I think. My app is now running on 3G/iOS3.1.3 -> iPod touch 2G/iOS4.2.1 -> iPad mini iOS 6.0.2. And just with the same build from xcode 4.5. Thanks!Fourdimensional
Hello, Kenji. Your solution is working great for testing on devices, but if I validate the product(for distrib) I got 2 warnings : "architecture armv6 is not supported..." and "iOS deployment targets lower than 4.3 are not supported...". I guess it still works fine since it's the same executable than the one I use to test on the device, but do you think it's an issue for submitting to the appstore ?Fourdimensional
As we no more support iOS 4, I can't tell you if validation will succeed. We have successfully submitted app with XCode 4.6 (but not tried with 4.6.x). Maybe you can make a try with these warnings and tell us if it pass validation. Maybe the binary will be rejected just after upload due to the not supported warn.Motel
Success ! Just ignore the two warnings and it works. Please see my response below for details.Fourdimensional
A
7

Thanks for this useful script !

I successfully combined all infos from this entire post, the resulting complete script is below. This script requires having both Xcode 4.5.x and a previous Xcode version supporting armv6 (Xcode 4.4.1 for instance, installed in /Applications/Xcode 4.4.1.app)

The script does NOT require to compile first in xcode 4.4.x, you just have to launch your latest Xcode, select the Release configuration and build. (the Release-armv6 configuration should have been defined like mentioned in the original post from Mike).

It will produce a .app compatible with armv6 armv7 and armv7s

Thanks to Mike for the original script !

#################
# Configuration #
#################
# Change this to the full path where Xcode 4.4 (or below) puts your armv6 output
setenv ARMV6_OUTPUT_PATH     "$BUILD_ROOT/Release-armv6-iphoneos/"
setenv ARMV6_EXECUTABLE_PATH "$ARMV6_OUTPUT_PATH$EXECUTABLE_PATH"

# Your "real" minimum OS version since Xcode 4.5 wants to make it iOS 4.3
# Must be 4.2 or below if you are supporting armv6...
setenv MINIMUM_OS 4.2
#####################
# End configuration #
#####################

# For debugging
echo CURRENT_ARCH = $CURRENT_ARCH
echo CONFIGURATION = $CONFIGURATION

# Don't need to do this for armv6 (built in older Xcode), simulator (i386), or debug build
#if ("$CURRENT_ARCH" == "armv6") exit 0
if ("$CURRENT_ARCH" == "i386") exit 0
if ("$CONFIGURATION" != "Release" && "$CONFIGURATION" != "Beta Test") exit 0

# Paths
setenv LIPO_PATH "$CODESIGNING_FOLDER_PATH/${EXECUTABLE_NAME}.lipo"
setenv FINAL_PATH "$CODESIGNING_FOLDER_PATH/$EXECUTABLE_NAME"
setenv FULL_INFO_PLIST_PATH "$CONFIGURATION_BUILD_DIR/$INFOPLIST_PATH"

#log file for armv6 build
echo "------------------------- BUILDING ARMV6 NOW -------------------------"
setenv LOGFILE "$BUILD_ROOT/buildarmv6.txt"
setenv CONFIGURATION_ARMV6 "${CONFIGURATION}-armv6"
#build armv6 version
echo "Building $FULL_PRODUCT_NAME armv6         CONFIG=$CONFIGURATION-armv6            target=$TARGETNAME"
"/Applications/Xcode 4.4.1.app/Contents/Developer/usr/bin/xcodebuild" -project         "${PROJECT_FILE_PATH}" -target "${TARGETNAME}" -sdk "${PLATFORM_NAME}" -configuration "$CONFIGURATION-armv6" CONFIGURATION_BUILD_DIR="$ARMV6_OUTPUT_PATH" >> "$LOGFILE"
echo "---------------------------- ARMV6 BUILT  -------------------------"
# to check for armv6 build errors
open "$LOGFILE"

# Debug / sanity check
lipo -info "$FINAL_PATH"
ls -l "$ARMV6_EXECUTABLE_PATH"

# Make sure something exists at $LIPO_PATH even if the next command fails
cp -pv "$FINAL_PATH" "$LIPO_PATH"

# If rebuilding without cleaning first, old armv6 might already be there so remove it
# If not, lipo won't output anything (thus the cp command just above)
lipo -remove armv6 -output "$LIPO_PATH" "$FINAL_PATH"

# Add armv6 to the fat binary, show that it worked for debugging, then remove temp file
lipo -create -output "$FINAL_PATH" "$ARMV6_EXECUTABLE_PATH" "$LIPO_PATH"
echo "------------------------- CHECK ARMV6 ARMV7 ARMV7S ARE MENTIONED BELOW -------------------------"
lipo -info "$FINAL_PATH"
echo "------------------------------------------------------------------------------------------------"
rm -f "$LIPO_PATH"

# Change Info.plist to set minimum OS version to 4.2 (instead of 4.3 which Xcode 4.5 wants)
/usr/libexec/PlistBuddy -c "Set :MinimumOSVersion $MINIMUM_OS" "$FULL_INFO_PLIST_PATH"
plutil -convert binary1 "$FULL_INFO_PLIST_PATH"
Assiduity answered 23/11, 2012 at 12:23 Comment(1)
Just to let you know my app was approved yesterday using the above technique ... it is now compatible with iPhone 3G and iOS 6 !Assiduity
W
4

Thanks for the post. We have a few apps to build so we automated the armv6 build using xcodebuild as you suggested. This is the part of our script (modified as we use bash) that does that, which can be added to your script above. This could be added before "# Debug / sanity check"

setenv LOGFILE "/Users/xyz/Desktop/buildarmv6.txt"

setenv CONFIGURATION_ARMV6 "${CONFIGURATION}_armv6"
echo "Building $FULL_PRODUCT_NAME armv6         CONFIG=$CONFIGURATION_ARMV6         target=$TARGETNAME"

"/Applications/Xcode 4.4.1.app/Contents/Developer/usr/bin/xcodebuild" -project "${PROJECT_FILE_PATH}" -target "${TARGETNAME}" -sdk "${PLATFORM_NAME}" -configuration "$CONFIGURATION_ARMV6" >> "$LOGFILE"

echo "Built armv6"
open "$LOGFILE" # to check for armv6 build errors
Woll answered 17/10, 2012 at 0:58 Comment(0)
P
3

Thank to Mike for this useful tutorial and script. As mentioned by Piotr in comments, the script is failing if you run the archive command from Xcode since it use another build directory for archiving.

Here below is my modification to the script to enable it for both normal release build and archive specific build.

It assumes that the armv6 build is run before as per original instructions from Mike. It use bash syntax because it is easier for me to strip-out the common base build directory. So this implies translation of the original script to bash which is only a matter of replacing setenv by export and changing the if statements syntax.

# Find the common base directory for both build
XCODE_BUILD=${BUILD_ROOT%%/Build*}
# Change this to the full path where Xcode 4.4 (or below) puts your armv6 output, using the previously derived base
export ARMV6_EXECUTABLE_PATH="$XCODE_BUILD/Build/Products/Release_armv6-iphoneos/$EXECUTABLE_PATH"
Paniculate answered 30/10, 2012 at 23:50 Comment(1)
This snippet—when combined with the one from @K1w1Geek, and the main answer—has sealed the deal on this problem for me. I've now got a version that's both armv6 (which I've verified as working on a 3G) and armv7 with iPhone 5 launch image (which I've verified on a 5). The only issue I had was that some of my older binary static libraries were only armv6/armv7 or armv7/armv7s, which meant that I couldn't have a binary with armv6/armv7/armv7s. But that's not a big deal.Pill
F
3

I would like to share my experience with kenji's answer. I think it's the best one and the best way to build a universal app which runs on armv6 / armv7 / armv7s, from iOS3.1 to iOS7.

Just do exactly as kenji suggests. You may ignore the parts about archiving the product, mainly if you send your app to apple via Application Loader (zipped).

Few more advices :

When you build for "distribution" configuration, xcode will validate the product, and you will get two warnings :

  • "architecture armv6 is not supported..."
  • "iOS deployment targets lower than 4.3 are not supported...".

Of course, because you actually build for armv6 and you set the deployment target to 3.1 or 4.2, for example !

So... just ignore these warnings.

After sending your app to itunes connect, you will receive a warning email from apple, saying that your app is not "Position Independent Executable". Of course again, it's because your target is lower than 4.3. Just ignore this warning.

At this date (2013 jul 03) I have successfully update an app to the appstore with this method, and it has passed validation. The app deployment target is iOS 3.1.2, and it supports armv6-armv7-armv7s.

I would like to say also that :

  • If you make a brand new app, just set the deployment target to iOS6 or iOS5. Ignore old OS.
  • If you have an old app sold since 2010, with dozens of thousands of users, you actually may have much more people who use it on armv6 than Apple usually says. I think 3 years is a too short period to drop support for these old devices, mainly if your app CAN run on them.
Fourdimensional answered 4/7, 2013 at 8:14 Comment(1)
This armv6/armv7/armv7s method was working a few days before but now it seems that after successful upload, itunes is sending this email: Invalid Image - For iOS applications, icons included in the binary submission must be in the PNG format.Nara
S
1

Apple has stopped accepting builds that support pre iOS5 devices and contain an iPhone 5 launch image. Here is the email for the last build I submitted that was build on Xcode 4.4.1

Dear developer,

We have discovered one or more issues with your recent delivery for "". To process your delivery, the following issues must be corrected:

Invalid Launch Image - Your app contains a launch image with a size modifier that is only supported for apps built with the iOS 6.0 SDK or later.

Once these issues have been corrected, go to the Version Details page and click "Ready to Upload Binary." Continue through the submission process until the app status is "Waiting for Upload." You can then deliver the corrected binary.

Regards,

The App Store team

Supernatant answered 17/2, 2013 at 14:27 Comment(1)
That is odd. We have been submitting apps as recently as this week and have never seen that response. The app supports iOS 3.1 and iPhone 5 by including the iPhone 5 launch image. This is the iTunes description from an app released this week: "Requirements: Compatible with iPhone, iPod touch, and iPad. Requires iOS 3.1 or later This app is optimized for iPhone 5"Woll

© 2022 - 2024 — McMap. All rights reserved.