So che questo non è ansible e Apple l’ha pianificato in questo modo per costringere gli utenti ad aggiornare i loro dispositivi. Ma voglio solo sapere se c’è qualche soluzione o hack in grado di farlo? Il cliente insiste sul fatto che dovremmo ancora supportare armv6 a causa di una percentuale ancora “grande” di utenti dell’app.
Conosco un comando chiamato lipo
per unire le librerie statiche e ho letto da qualche parte che possiamo anche usarlo per unire i file ipa, ma non sono sicuro di come sia stato fatto esattamente. Ho fatto un paio di ricerche su google e su questo sito, ma è difficile trovare una risposta concreta.
Sono stato in grado di farlo con successo con la mia app che si trova nell’App Store. Supporta armv6, armv7 e armv7s e versioni iOS da 4.2 a 6.0. Ho verificato che venga eseguito su dispositivi meno recenti (iPhone 3G, iPod touch 2g) fino all’iPhone 5.
Questo metodo richiede di avere contemporaneamente Xcode 4.5 e una versione precedente di Xcode installati. Sono ancora sul 4.3.2 per la mia versione precedente, ma dovrebbe funzionare anche 4.4.
Avevo screenshot per questa risposta, ma Stack Overflow non mi consente di pubblicarli perché sono nuovo. 🙁
Aggiungi una nuova configurazione di build per la tua build armv6. Ho duplicato la configurazione di rilascio e l’ho chiamata Release_armv6.
Impostare Architetture e Architetture valide per le configurazioni di generazione. Per tutti tranne Release_armv6, utilizzare il valore predefinito. Per Release_armv6, impostarlo manualmente su armv6 . http://sofit.miximages.com/xcode/h8Mpl.png
Se utilizzi funzionalità di iOS 6 che Xcode 4.4 e versioni precedenti non comprenderanno, dovrai #ifdeferle per la build armv6. In Impostazioni di compilazione sotto Altri flag C e altri flag C ++ ho aggiunto -DARMV6_ONLY alla mia configurazione Release_armv6. Quindi ovunque il codice usi una nuova API iOS 6, faccio qualcosa come #ifndef ARMV6_ONLY / #endif come appropriato. http://sofit.miximages.com/xcode/czF6J.png
Aggiungi un nuovo schema e impostalo per utilizzare la configurazione di build di Release_armv6 in tutti i casi.
In Fasi di creazione, aggiungi una fase di generazione di script di esecuzione con il seguente script (imposta Shell su / bin / csh ). Qui è dove avviene la magia. Modifica la sezione Configurazione: consente di determinare il percorso completo del build Release_armv6 e di sostituirlo con ARMV6_EXECUTABLE_PATH. Imposta anche 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"
Quando sei pronto per creare una build di rilascio, fallo nel seguente ordine:
Chiudi Xcode 4.5 e apri Xcode 4.4 o versioni precedenti. Seleziona il tuo schema armv6 e costruiscilo.
Chiudi Xcode 4.4 o inferiore e apri Xcode 4.5. Seleziona il tuo schema di rilascio e costruiscilo.
Questo è praticamente tutto. Controlla l’output della build per verificare di aver ottenuto ciò che desideri: un eseguibile con tre architetture al suo interno. L’ultimo output dello script di esecuzione dovrebbe dirti questo.
Se qualcuno ha idee per migliorare questo, per favore sentiti libero. Immagino che potreste essere fantasiosi e chiamare il comando “xcodebuild” di Xcode 4.4 all’interno dello script di build, alleviando la necessità di cambiare tra le versioni di Xcode. Ma questo funziona abbastanza bene per me. 😉
Avvertenze:
Per sicurezza, potresti voler modificare i tuoi file xib nella versione precedente di Xcode. Finora sembra che 4.5 sia compatibile all’indietro, ma non si sa mai.
In effetti, potresti prendere in considerazione la maggior parte del tuo sviluppo, ad eccezione di materiale specifico per iOS 6, nel vecchio Xcode. Dipende da qualunque cosa sia più facile per te.
C’è un altro modo in cui gcc-4.2 supporta ancora armv6, che non richiede di chiudere Xcode 4.5 e aprire una versione precedente (per la compilazione, ma non per l’esecuzione dell’app su un dispositivo 4.2):
Arch: $ (ARCHS_STANDARD_32_BIT) armv6
Architetture valide: armv6 armv7 armv7s
Quindi, se costruisci il tuo progetto, vedrai le avvertenze:
avviso: nessuna regola per elaborare il file '$ (PROJECT_DIR) /App/AppDelegate.m' di tipo sourcecode.c.objc per l'architettura armv6 avviso: nessuna regola per elaborare il file '$ (PROJECT_DIR) /App/SomeFile.c' di tipo sourcecode.cc per architettura armv6
Build Rule
per i file di origine con i nomi corrispondenti: *.[mc]
che utilizzerà LLVM GCC 4.2
Funziona con le librerie statiche, ma non con le app:
ld: file è universale (4 sezioni) ma non contiene una sezione (n) armv6: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib /crt1.3.1.o per architettura armv6
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/ piattaforms / iPhoneOS.platform / Developer / SDK / 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
Compila il tuo progetto e verifica che la tua app contenga tutti gli arch:
$ file DerivedData / TestApp / Build / Prodotti / Debug-iphoneos / TestApp.app / TestApp DerivedData / TestApp / Build / Prodotti / Debug-iphoneos / TestApp.app / TestApp: Mach-O binario universale con 3 architetture DerivatoData / TestApp / Build / Prodotti / Debug-iphone / TestApp.app / TestApp (per architettura armv6): arm eseguibile Mach-O DerivedData / TestApp / Build / Products / Debug-iphoneos / TestApp.app / TestApp (per architettura armv7): arm eseguibile Mach-O DerivedData / TestApp / Build / Products / Debug-iphoneos / TestApp.app / TestApp (per architettura cputype (12) cpusubtype (11)): arm eseguibile Mach-O
Si noti che il file dSYM contiene anche tutti gli arch (utile per la simbolizzazione del rapporto di arresto anomalo):
$ file DerivedData / TestApp / Build / Prodotti / Debug-iphoneos / TestApp.app.dSYM / Contents / Resources / DWARF / TestApp DerivatoData / TestApp / Build / Prodotti / Debug-iphoneos / TestApp.app.dSYM / Contents / Resources / DWARF / TestApp: binario universale Mach-O con 3 architetture DerivedData / TestApp / Build / Products / Debug-iphoneos / TestApp.app.dSYM / Contents / Resources / DWARF / TestApp (per architettura armv6): arm file companion Mach-O dSYM DerivedData / TestApp / Build / Products / Debug-iphoneos / TestApp.app.dSYM / Contents / Resources / DWARF / TestApp (per architettura armv7): arm file companion Mach-O dSYM DerivatoData / TestApp / Build / Prodotti / Debug-iphoneos / TestApp.app.dSYM / Contents / Resources / DWARF / TestApp (per architettura cputype (12) cpusubtype (11)): arm file companion Mach-O dSYM
Ho installato e lanciato l’applicazione su iOS 4.2 2gen iPod touch aprendo xcode 4.4.1, quindi Product
-> Run without building
.
libarclite_iphoneos.a
o libclang_rt.ios.a
: ld: file è universale (2 sezioni) ma non contiene una sezione (n) armv6: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphoneos.a per architettura armv6
ld: file è universale (2 sezioni) ma non contiene una (n) sezione armv6: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/4.1/libclang_rt.ios.a per l'architettura armv6
La procedura utilizzata per crt1.3.1.o si applica anche a questi file e risolverà l’errore che consente a Xcode di archiviare correttamente il progetto: è ansible utilizzare il percorso stampato da ld per trovare il file e unirsi alla slice armv6 con lipo ; tieni a mente che libclang_rt.ios.a nelle versioni precedenti di Xcode non si trova in Xcode.app/[...]/usr/lib/clang/4.1
ma in Xcode.app/[...]/usr/lib/clang/4.0
.
Ho archiviato con successo il file, lo ho implementato con un profilo di distribuzione ad-hoc e testato su iPhone 3G (4.2.1) e iPhone 3GS (6.0).
Organizer
, c’è il messaggio: Dispositivi di tipo “iPhone 3G” non sono supportati da questa versione di Xcode. Ma un ls
in DeviceSupport
mostra:
ls /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/ 4.2 4.3 5.0 5.1 6.0 (10A403)
Senza differenze nella directory 4.2 da Xcode 4.4.1.
La domanda è ora: in che modo Xcode rileva se il dispositivo è supportato o no?
Aprendo /Applications/Xcode.app/Contents/Developer//Platforms/iPhoneOS.platform/Developer//Library/PrivateFrameworks/DTDeviceKitBase.framework/DTDeviceKitBase
con Hex Fiend
(o un altro editor esadecimale) e sostituendo ascii 4.3
con 4.2
fai l’errore il messaggio scompare e l’app installata sul dispositivo è elencata (ma il punto elenco dispositivo è ancora rosso).
Quindi dobbiamo modificare /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks//DTDeviceKit.framework/Versions/Current/DTDeviceKit
e sostituire:
Expired.deviceArchitecture.iPhone1,1.iPhone1,2.iPod1,1.iPod2,1.iPod2,2.armv6
a :
Expired.deviceArchitecture.iPhone0,1.iPhone0,2.iPod0,1.iPod0,1.iPod0,2.armv5
Poi abbiamo un proiettile arancione nell’Organizzatore (Xcode 4.5.1):
La versione di iOS su "iPhone" è troppo vecchia per essere utilizzata con questa versione dell'SDK di iOS. Si prega di ripristinare il dispositivo su una versione del sistema operativo elencata di seguito. Sistema operativo installato su iPhone 4.2.1 (8C148) Versioni iOS supportate Xcode 6.0 (10A403) 5.1 5.0 4.3
La domanda è ora: dove sono definite le versioni iOS supportate da Xcode?
Poiché esiste una directory 4.2
in /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/
, dovrebbe già essere supportata …
Ho provato a copiare iPhoneOS4.2.sdk
da Xcode 4.4.1 a /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/
, ma non rende il dispositivo supportato.
Quindi non ho trovato come aggiungere 4.2 supporto per dispositivi in Xcode 4.5. Qualche idea ?
Conclusione: è ansible compilare per armv6 / 7 / 7s con Xcode 4.5. Ma non è ansible avviare un’applicazione su un dispositivo armv6 4.2 senza avviare Xcode 4.4.
Grande aggiornamento: funziona con Xcode 4.5.2!
Ora il punto è verde in Xcode 4.5.2 🙂 Il dispositivo viene visualizzato nell’elenco a discesa vicino al pulsante Esegui. Ma quando provi a eseguire l’app, hai ricevuto il messaggio:
Xcode non può essere eseguito utilizzando il dispositivo selezionato. Scegli una destinazione con un'architettura supportata per poter essere eseguita su questo dispositivo.
Aggiungi semplicemente armv6 alle architetture valide 🙂
Altra nota: la Build Rule
di Apple LLVM compiler 4.1
per i file sorgente con i nomi corrispondenti: *.[mc]
può utilizzare LLVM GCC 4.2
o Apple LLVM compiler 4.1
, o Default compiler
Grazie per questo script utile!
Ho combinato con successo tutte le informazioni di questo post, lo script completo risultante è di seguito. Questo script richiede di avere sia Xcode 4.5.x sia una versione precedente di Xcode che supporta armv6 (Xcode 4.4.1 per esempio, installato in / Applicazioni / Xcode 4.4.1.app)
Lo script NON richiede di compilare prima in xcode 4.4.x, devi solo lanciare il tuo ultimo Xcode, selezionare la configurazione di rilascio e compilare. (la configurazione Release-armv6 avrebbe dovuto essere definita come menzionato nel post originale di Mike).
Produrrà una .app compatibile con armv6 armv7 e armv7s
Grazie a Mike per la sceneggiatura originale!
################# # 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"
Grazie per il post. Abbiamo alcune app da compilare, quindi abbiamo automatizzato la build armv6 usando xcodebuild come suggerito. Questa è la parte del nostro script (modificato come usiamo bash) che lo fa, che può essere aggiunto al tuo script sopra. Questo potrebbe essere aggiunto prima di “# 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
Grazie a Mike per questo utile tutorial e script. Come menzionato da Piotr nei commenti, lo script non funziona se si esegue il comando di archiviazione da Xcode poiché utilizza un’altra directory di build per l’archiviazione.
Di seguito è riportata la mia modifica allo script per abilitarlo sia per la versione di build normale che per quella di archiviazione specifica.
Si presuppone che la build armv6 venga eseguita prima come da istruzioni originali di Mike. Usa la syntax di bash perché è più facile per me rimuovere la directory di creazione di base comune. Quindi questo implica la traduzione dello script originale in bash che è solo una questione di sostituzione di setenv tramite esportazione e modifica della syntax delle istruzioni if.
# 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"
Mi piacerebbe condividere la mia esperienza con la risposta di kenji. Penso che sia il migliore e il modo migliore per creare un’app universale che funzioni su armv6 / armv7 / armv7s, da iOS3.1 a iOS7.
Fai esattamente come suggerisce il kenji. È ansible ignorare le parti sull’archiviazione del prodotto, principalmente se si invia l’app a Apple tramite Application Loader (zippato).
Pochi altri consigli:
Quando crei per la configurazione “distribuzione”, xcode convaliderà il prodotto e riceverai due avvertimenti:
Ovviamente, perché in realtà si costruisce per armv6 e si imposta la destinazione di implementazione su 3.1 o 4.2, ad esempio!
Quindi … ignora questi avvertimenti.
Dopo aver inviato la tua app a itunes connect, riceverai un’e-mail di avviso da Apple, che afferma che la tua app non è “Eseguibile indipendente dalla posizione”. Ovviamente, è perché il tuo objective è inferiore a 4.3. Ignora questo avvertimento.
A questa data (2013 luglio 03) ho aggiornato con successo un’app all’appstore con questo metodo e ha superato la convalida. L’objective di distribuzione dell’app è iOS 3.1.2 e supporta armv6-armv7-armv7s.
Vorrei anche dire che:
Apple ha smesso di accettare build che supportano i dispositivi pre iOS5 e contengono un’immagine di avvio di iPhone 5. Ecco l’email per l’ultima build che ho inviato che è stata creata su Xcode 4.4.1
Caro sviluppatore,
Abbiamo rilevato uno o più problemi relativi alla consegna recente per “”. Per elaborare la consegna, è necessario correggere i seguenti problemi:
Immagine di avvio non valida: l’app contiene un’immagine di avvio con un modificatore di dimensioni supportato solo per le app create con l’SDK di iOS 6.0 o versioni successive.
Una volta che questi problemi sono stati corretti, vai alla pagina Dettagli della versione e fai clic su “Pronto per caricare file binari”. Continua attraverso il processo di invio fino a quando lo stato dell’app è “In attesa del caricamento”. È quindi ansible fornire il file binario corretto.
Saluti,
Il team di App Store