53 votes

Comment prendre en charge armv6 et armv7s pour la version intégrée à xcode 4.5

Je sais que ce n'est pas possible d'Apple et planifié de cette façon de forcer les utilisateurs à mettre à niveau leurs appareils. Mais je veux juste savoir s'il existe une solution de contournement ou de hacks en mesure de le faire? Le client insiste pour que l'on devrait toujours soutenir les armv6 en raison d'un "grand" pourcentage des utilisateurs de l'application.

Je sais que la commande lipo de fusionner les bibliothèques statiques et j'ai lu quelque part que l'on peut également l'utiliser pour fusionner les fichiers ipa mais je ne suis pas sûr de savoir comment sa fait exactement. J'ai fait quelques recherche autour de déjà sur google et sur ce site, mais il est difficile de trouver une réponse concrète.

93voto

Mike Points 946

J'ai été en mesure de le faire avec mon appli dans l'App Store. Il prend en charge armv6, armv7, et armv7s et les versions d'iOS, passant de 4,2 à 6.0. J'ai vérifié qu'il fonctionne sur les anciens appareils (iPhone 3G, iPod touch 2g) tout le chemin à travers l'iPhone 5.

Cette méthode nécessite d'avoir à la fois Xcode 4.5 et une ancienne version de Xcode installé en même temps. Je suis toujours sur 4.3.2 pour mon ancienne version, mais 4.4 devrait fonctionner aussi bien.

J'ai eu des captures d'écran pour cette réponse, mais le Débordement de Pile ne me permet pas de poster parce que je suis nouveau. :(

Le programme d'installation de Xcode 4.5

  1. Ajouter une nouvelle configuration de build pour votre armv6 construire. J'ai dupliqué la Libération de config et l'a nommé Release_armv6.

  2. Définir les Architectures et Valide les Architectures de votre configuration. Pour tous, mais Release_armv6, utilisez la valeur par défaut. Pour Release_armv6, définissez manuellement pour armv6. http://i.stack.imgur.com/h8Mpl.png

  3. Si vous utilisez iOS 6 dispose que Xcode 4.4 ci-dessous et de ne pas comprendre, vous aurez besoin de #ifdef pour votre armv6 construire. Dans les Paramètres de construction sous d'Autres Drapeaux et Autres C++ Drapeaux, j'ai ajouté -DARMV6_ONLY à mon Release_armv6 config. Alors, où que le code utilise une nouvelle iOS 6 API, je fais quelque chose comme #ifndef ARMV6_ONLY / #endif tant que de besoin. http://i.stack.imgur.com/czF6J.png

  4. Ajouter un nouveau schéma et le configurer pour utiliser la Release_armv6 de configuration de la compilation dans tous les cas.

  5. En vertu de Phases de construction, d'ajouter un Exécuter le Script Phase de construction avec le script suivant (réglage de la Shell /bin/csh). C'est là que la magie se produit. Modifier la section de Configuration: Déterminer votre chemin d'accès complet à la Release_armv6 de construire et de le substituer par ARMV6_EXECUTABLE_PATH. Également définir 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"

Processus De Construction

Lorsque vous êtes prêt à créer une libération de construire, de le faire dans l'ordre suivant:

  1. Fermer Xcode 4.5 et ouvrez Xcode 4.4 ou ci-dessous. Sélectionnez votre armv6 régime et de le construire.

  2. Fermer Xcode 4.4 ou ci-dessous et ouvrez Xcode 4.5. Sélectionnez votre Version de système et de le construire.

C'est assez bien. Vérifiez la sortie de la construction pour vérifier que vous avez obtenu ce que vous voulez - un exécutable avec trois architectures. La dernière sortie de l'exécuter le script devrait vous dire ceci.

Si quelqu'un a des idées pour améliorer cette situation, sentez-vous svp libre. J'imagine que vous pourriez être en mesure d'obtenir la fantaisie et de l'appel Xcode 4.4 "xcodebuild" commande dans le script de construction, en réduisant le besoin de basculer entre les versions de Xcode. Mais cela fonctionne assez bien pour moi. ;)

Mises en garde:

  • Juste pour être sûr, vous pouvez éditer vos fichiers xib dans l'ancienne version de Xcode. Jusqu'à présent, il semble que 4.5 est rétro-compatible, mais on ne sait jamais.

  • En fait, vous pourriez envisager de faire la plupart de votre développement, sauf pour iOS 6-spécifique des choses, dans l'ancienne Xcode. Dépend de ce qui est le plus facile pour vous.

26voto

kenji Points 2152

Il y a une autre façon de gcc-4.2 prend toujours en charge de armv6, qui ne vous demandera pas de fermer Xcode 4.5 ouvert une version précédente (pour la compilation, mais pas pour l'application en cours d'exécution sur un 4.2 appareil) :

  • Ajouter armv6 à la validité des ponts et des ponts :

Architectures : $(ARCHS_STANDARD_32_BIT) armv6

Valide Architectures : armv6 armv7 armv7s

  • Vim (ou TextEdit) de votre projet.pbxproj fichier pour remplacer IPHONEOS_DEPLOYMENT_TARGET à 4.0 - 4.1 - 4.2 comme vous avez besoin, Xcode 4.5 ne vous laissera pas vous ci-dessous 4.3.

Alors, si vous construisez votre projet, vous allez voir mises en garde :

avertissement: pas de règle pour traiter le fichier '$(PROJECT_DIR)/App/AppDelegate.m' de type de code source.c.objc pour l'architecture armv6
avertissement: pas de règle pour traiter le fichier '$(PROJECT_DIR)/App/SomeFile.c " du type de code source.c.c pour l'architecture armv6
  • Ajouter un Build Rule pour source les fichiers avec les noms correspondants : *.[mc] qui utilisera LLVM GCC 4.2

Il fonctionne pour les bibliothèques statiques, mais pas pour les applications :

ld: le fichier est universel (4 tranches), mais ne contient pas de(n) armv6 tranche: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib/crt1.3.1.o pour l'architecture armv6
  • Pour faire cela fonctionne pour les applications, nous devons ajouter la armv6 tranche de ce fichier de l'objet (qui est livré avec le SDK 5.1) :
lipo /path/to-4.4/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/usr/lib/crt1.3.1.o -extrait armv6 -sortie /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 -créer -sortie /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

Compilez votre projet et vérifier que votre application contient toutes les architectures :

$ fichier DerivedData/TestApp/Construction/Produits/Debug-iphoneos/TestApp.app/TestApp 
DerivedData/TestApp/Construction/Produits/Debug-iphoneos/TestApp.app/TestApp: Mach-O binaire universel avec 3 architectures
DerivedData/TestApp/Construction/Produits/Debug-iphoneos/TestApp.app/TestApp (pour l'architecture armv6): Mach-O executable bras
DerivedData/TestApp/Construction/Produits/Debug-iphoneos/TestApp.app/TestApp (pour l'architecture armv7): Mach-O executable bras
DerivedData/TestApp/Construction/Produits/Debug-iphoneos/TestApp.app/TestApp (pour l'architecture cputype (12) cpusubtype (11)): Mach-O executable bras

Notez que le dSYM fichier contient également toutes les architectures (utile pour le rapport de crash symbolification) :

$ fichier DerivedData/TestApp/Construction/Produits/Debug-iphoneos/TestApp.app.dSYM/Contents/Resources/NAIN/TestApp 
DerivedData/TestApp/Construction/Produits/Debug-iphoneos/TestApp.app.dSYM/Contents/Resources/NAIN/TestApp: Mach-O binaire universel avec 3 architectures
DerivedData/TestApp/Construction/Produits/Debug-iphoneos/TestApp.app.dSYM/Contents/Resources/NAIN/TestApp (pour l'architecture armv6): Mach-O dSYM fichier compagnon bras
DerivedData/TestApp/Construction/Produits/Debug-iphoneos/TestApp.app.dSYM/Contents/Resources/NAIN/TestApp (pour l'architecture armv7): Mach-O dSYM fichier compagnon bras
DerivedData/TestApp/Construction/Produits/Debug-iphoneos/TestApp.app.dSYM/Contents/Resources/NAIN/TestApp (pour l'architecture cputype (12) cpusubtype (11)): Mach-O dSYM fichier compagnon bras

J'ai installé avec succès et a lancé l'application sur iOS 4.2 2gen iPod touch par l'ouverture de xcode 4.4.1, alors Product -> Run without building.

  • Lorsque vous Archive de votre produit, vous pouvez rencontrer de nouveau la Pomme de Mach-O de l'éditeur de liens d'erreur, cette fois avec d'autres fichiers, tels que libarclite_iphoneos.a ou libclang_rt.ios.a:
ld: le fichier est universel (2 tranches), mais ne contient pas de(n) armv6 tranche: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphoneos.un pour l'architecture armv6
ld: le fichier est universel (2 tranches), mais ne contient pas de(n) armv6 tranche: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/4.1/libclang_rt.ios.un pour l'architecture armv6

La procédure utilisée pour l'crt1.3.1.o s'applique à ces fichiers trop, et va corriger l'erreur permettant Xcode pour réussir l'archive de votre projet: vous pouvez utiliser le chemin d'accès imprimé par ld pour trouver le fichier et rejoindre la armv6 tranche avec lipo; il suffit de garder à l'esprit que libclang_rt.ios.un dans les précédentes versions de Xcode n'est pas situé dans Xcode.app/[...]/usr/lib/clang/4.1 mais Xcode.app/[...]/usr/lib/clang/4.0.

J'ai été archivé le fichier, déployé avec une ad-hoc profil de distribution, et testé sur iPhone 3G (4.2.1) et iPhone 3GS (6.0).

  • Dernière question : on ne peut pas lancer l'application. Dans l' Organizer, il y a le message : les Appareils de type "iPhone 3G" ne sont pas pris en charge par cette version de Xcode.

Mais un ls dans la DeviceSupport montre :

 ls /Applications/Xcode.app/Contents/Développeur/plates-formes/iPhoneOS.de plate-forme/DeviceSupport/ 
4.2 4.3 5.0 5.1 6.0 (10A403)

Avec pas de différences dans l'4.2 répertoire à partir de Xcode 4.4.1.

La question est maintenant : comment Xcode détection de périphérique est pris en charge ou pas ?

L'ouverture d' /Applications/Xcode.app/Contents/Developer//Platforms/iPhoneOS.platform/Developer//Library/PrivateFrameworks/DTDeviceKitBase.framework/DTDeviceKitBase avec Hex Fiend (ou un autre éditeur hexadécimal), et le remplacement de l'ascii 4.3 avec 4.2 rendre le message d'erreur disparaît, et l'application installée sur l'appareil sont répertoriés (mais le dispositif balle dans la liste des périphériques est encore rouge).

Ensuite, nous devons éditer /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks//DTDeviceKit.framework/Versions/Current/DTDeviceKit et remplacer :

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

pour :

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

Puis nous avons une orange balle dans l'Organisateur (Xcode 4.5.1) :

La version de l'iOS sur "iPhone" est trop vieux pour une utilisation avec cette version du SDK iOS. S'il vous plaît restaurer l'appareil à une version de l'OS énumérés ci-dessous.

Système d'exploitation Installé sur l'iPhone
4.2.1 (8C148)

Xcode pris en charge les Versions d'iOS
6.0 (10A403)
5.1
5.0
4.3

La question est maintenant : où Xcode pris en charge les Versions d'iOS sont-ils définis ?

Comme il y a un 4.2 - répertoire dans le répertoire /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/, il devrait déjà être pris en charge...

Essayé de copier iPhoneOS4.2.sdk de Xcode 4.4.1 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/, mais ce n'est pas de périphérique pris en charge.

Donc n'ai pas trouvé comment ajouter 4.2 prise en charge de périphériques dans Xcode 4.5. Des idées ?

Conclusion : la compilation pour armv6/7/7 dans Xcode 4.5 est possible. Mais il n'est pas possible de lancer une application sur un 4.2 armv6 appareil sans lancer Xcode 4.4.

Grosse mise à jour : il fonctionne avec Xcode 4.5.2 !

Maintenant la balle est vert dans Xcode 4.5.2 :-) L'appareil apparaît dans la liste déroulante près sur le bouton Exécuter. Mais lorsque j'essaie d'exécuter l'application, a compris le message :

Xcode ne peut pas s'exécuter à l'aide de l'appareil sélectionné.
Choisissez une destination avec une prise en charge de l'architecture afin de fonctionner sur cet appareil.

Ajoutez simplement armv6, à la validité des architectures :-)

Autre remarque : l' Build Rule pour source les fichiers avec les noms correspondants : *.[mc] pouvez utiliser LLVM GCC 4.2 ou Apple LLVM compiler 4.1ou Default compiler

7voto

Jerome Points 138

Merci pour ce script !

J'ai réussi à combiner toutes les infos de ce post entier, le script complet est ci-dessous. Ce script nécessite d'avoir à la fois Xcode 4.5.x et un précédent Xcode version de soutenir armv6 (Xcode 4.4.1 par exemple, installé dans /Applications/Xcode 4.4.1.app)

Le script n'a PAS besoin de compiler d'abord dans xcode 4.4.x, il vous suffit de lancer votre dernier Xcode, sélectionnez la configuration de Version et de build. (la Libération-armv6 configuration doit avoir été défini comme mentionné dans le post original de Mike).

Il va produire une .application compatible avec armv6 armv7 et armv7s

Merci à Mike pour le script original !

#################
# 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"

4voto

K1w1Geek Points 304

Merci pour le post. Nous avons quelques applications à construire, nous avons donc automatisé la construction d’armv6 en utilisant xcodebuild comme vous l’aviez suggéré. C'est la partie de notre script (modifiée car nous utilisons bash) qui le fait, ce qui peut être ajouté à votre script ci-dessus. Cela pourrait être ajouté avant "# 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
 

3voto

Max_B Points 129

Merci à Mike pour ce tutoriel et de script. Comme mentionné par Piotr dans les commentaires, le script est en échec, si vous exécutez la commande archive à partir de Xcode depuis il utiliser un autre répertoire de construction pour de l'archivage.

Voici ci-dessous ma modification dans le script afin de l'activer pour les deux version normale de construire et d'archivage de construction précis.

Il suppose que le armv6 construire est exécuté selon les instructions originales de Mike. Il utilise bash syntaxe, car il est plus facile pour moi de bande de la base commune répertoire de construction. Donc, cela implique la traduction de l'original script bash qui n'est qu'une question de remplacement setenv par l'exportation et la modification de la si les déclarations de la syntaxe.

# 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"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X