53 votos

Cómo apoyar tanto armv6 y armv7s para versión de lanzamiento en xcode 4.5

Sé que esto no es posible y Apple planeado de esta manera para obligar a los usuarios a actualizar sus dispositivos. Pero yo sólo quiero saber si hay alguna solución o hacks en capaz de hacer esto? El cliente insiste en que debemos apoyar binarios armv6 a causa de un "grande" porcentaje de los usuarios de la aplicación.

Conozco a un comando llamado lipo a la combinación de las bibliotecas estáticas y he leído que también se puede utilizar para combinar archivos ipa pero no estoy seguro de cómo exactamente su hecho. Hice un par de búsqueda alrededor ya en google y este sitio, pero es difícil encontrar una respuesta concreta.

93voto

Mike Puntos 946

He sido capaz de hacer esto con éxito con mi aplicación en la App Store. Soporta binarios armv6, armv7, y armv7s y versiones de iOS de 4,2 a 6,0. He comprobado que se ejecuta en dispositivos más antiguos (iPhone 3G, iPod touch 2g) todo el camino a través de el iPhone 5.

Este método requiere tener tanto Xcode 4.5 y una antigua versión de Xcode instalado de forma simultánea. Todavía estoy en la 4.3.2 para mi versión anterior, pero 4.4 debería funcionar así.

Yo tenía las capturas de pantalla de esta respuesta, pero Stack Overflow no me deja publicarlos porque soy nuevo. :(

El programa de instalación de Xcode 4.5

  1. Agregar una nueva configuración de compilación para su binarios armv6 construir. He duplicado la Liberación de configuración y la llamó Release_armv6.

  2. Conjunto de las Arquitecturas y de las Arquitecturas Válidas para la construcción de configuraciones. Para todos, pero Release_armv6, use el valor predeterminado. Para Release_armv6, establezca manualmente a binarios armv6. http://i.stack.imgur.com/h8Mpl.png

  3. Si estás usando iOS 6 características que Xcode 4.4 y por debajo no lo entiendo, usted necesitará #ifdef de estos para su binarios armv6 construir. En la Configuración de generación bajo Otros C Banderas y Otros C++ Banderas añadí -DARMV6_ONLY a mi Release_armv6 config. A continuación, donde quiera que el código utiliza un nuevo iOS 6 de la API, tengo que hacer algo como #ifndef ARMV6_ONLY / #endif según corresponda. http://i.stack.imgur.com/czF6J.png

  4. Añadir un nuevo esquema y configurarse para que utilice el Release_armv6 configuración de generación en todos los casos.

  5. En virtud de Fases de construcción, agregar una secuencia de Comandos Ejecutar la Fase de construcción con la siguiente secuencia de comandos (conjunto el Shell /bin/csh). Aquí es donde sucede la magia. Editar la Configuración de la sección: a Determinar su ruta de acceso completa a la Release_armv6 construir y sustitución de la misma ARMV6_EXECUTABLE_PATH. También se establece 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"

Proceso De Construcción

Cuando estés listo para crear una versión, se hará en el siguiente orden:

  1. Cerca de Xcode 4.5 y abrir Xcode 4.4 o por debajo. Seleccione su binarios armv6 régimen y la construcción.

  2. Cerca de Xcode 4.4 o de abajo y abrir Xcode 4.5. Seleccione su Liberación del régimen y la construcción.

Eso es todo. Compruebe la salida de la compilación para comprobar que usted tiene lo que usted quiere - un ejecutable con tres arquitecturas. La última salida de la secuencia de comandos ejecutar debería decir esto.

Si alguien tiene ideas para mejorar esto, por favor no dude en. Me imagino que usted podría ser capaz de conseguir la suposición y de la llamada Xcode 4.4 "xcodebuild" comando desde dentro de la secuencia de comandos de compilación, aliviando la necesidad de cambiar entre versiones de Xcode. Pero esto funciona bastante bien para mí. ;)

Advertencias:

  • Sólo para estar seguro, puede que desee editar sus archivos xib en la antigua versión de Xcode. Hasta ahora parece que 4.5 es compatible, pero nunca se sabe.

  • De hecho, usted podría considerar la posibilidad de simplemente hacer la mayoría de su desarrollo, excepto para iOS 6-específicos de la materia, en los mayores de Xcode. Depende de lo que sea más fácil para usted.

26voto

kenji Puntos 2152

No hay otra forma como gcc-4.2 todavía soporta binarios armv6, que no requieren cerca de Xcode 4.5 abierto una versión anterior (para la compilación, pero no para la ejecución de la aplicación en un 4.2 dispositivo) :

  • Añadir binarios armv6 válidos arcos y arcos :

Arcos : $(ARCHS_STANDARD_32_BIT) binarios armv6

Válido para Arquitecturas : binarios armv6 armv7 armv7s

  • Vim (o TextEdit) de su proyecto.pbxproj archivo para reemplazar IPHONEOS_DEPLOYMENT_TARGET a 4.0 - 4.1 - 4.2 como la que usted necesita, Xcode 4.5, no te deja abajo 4.3.

Entonces, si la construcción de su proyecto, usted va a ver advertencias :

advertencia: no hay ninguna regla para procesar el archivo '$(PROJECT_DIR)/App/AppDelegate.m' del tipo de sourcecode.c.objc para la arquitectura binarios armv6
advertencia: no hay ninguna regla para procesar el archivo '$(PROJECT_DIR)/App/SomeFile.c' de tipo de sourcecode.c.c para la arquitectura binarios armv6
  • Añadir un Build Rule de origen de los archivos con los nombres que coincidan con : *.[mc] que utilizará LLVM GCC 4.2

Funciona para las bibliotecas estáticas, pero no para las aplicaciones :

ld: es universal (4 rebanadas), pero no contiene(n) binarios armv6 slice: /Aplicaciones/Xcode.aplicación/Contenido/Developer/Platforms/iPhoneOS.plataforma/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib/crt1.3.1.o para la arquitectura binarios armv6
  • Para hacer funciona para las aplicaciones, tenemos que añadir el binarios armv6 sector a este archivo objeto (el que viene con el SDK 5.1) :
lipo /ruta/a-4.4/Xcode.aplicación/Contenido/Developer/Platforms/iPhoneOS.plataforma/Developer/SDKs/iPhoneOS5.1.sdk/usr/lib/crt1.3.1.o-extracto de binarios armv6-salida /tmp/crt1.3.1-binarios armv6.o
lipo /Aplicaciones/Xcode.aplicación/Contenido/en/Developer/Platforms/iPhoneOS.plataforma/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib/crt1.3.1.o /tmp/crt1.3.1-binarios armv6.o-crear-salida /tmp/crt1.3.1-armv677s.o
mv /Aplicaciones/Xcode.aplicación/Contenido/en/Developer/Platforms/iPhoneOS.plataforma/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib/crt1.3.1.o /Aplicaciones/Xcode.aplicación/Contenido/en/Developer/Platforms/iPhoneOS.plataforma/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib/crt1.3.1.o.bkp
mv /tmp/crt1.3.1-armv677s.o /Aplicaciones/Xcode.aplicación/Contenido/en/Developer/Platforms/iPhoneOS.plataforma/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib/crt1.3.1.o

Compilar el proyecto y comprobar que la aplicación contiene todas las arquitecturas :

$ archivo DerivedData/Prueba/Construcción/Productos/Debug-iphoneos/TestApp.app/TestApp 
DerivedData/Prueba/Construcción/Productos/Debug-iphoneos/TestApp.app/TestApp: Mach-O binario universal con 3 arquitecturas
DerivedData/Prueba/Construcción/Productos/Debug-iphoneos/TestApp.app/Prueba (para arquitectura binarios armv6): Mach-O ejecutable brazo
DerivedData/Prueba/Construcción/Productos/Debug-iphoneos/TestApp.app/Prueba (para la arquitectura armv7): Mach-O ejecutable brazo
DerivedData/Prueba/Construcción/Productos/Debug-iphoneos/TestApp.app/Prueba (para arquitectura cputype (12) cpusubtype (11)): Mach-O ejecutable brazo

Tenga en cuenta que el dSYM archivo también contiene todas las arquitecturas (útil para el informe de accidente symbolification) :

$ archivo DerivedData/Prueba/Construcción/Productos/Debug-iphoneos/TestApp.aplicación.dSYM/Contenidos/Recursos/ENANO/TestApp 
DerivedData/Prueba/Construcción/Productos/Debug-iphoneos/TestApp.aplicación.dSYM/Contenidos/Recursos/ENANO/TestApp: Mach-O binario universal con 3 arquitecturas
DerivedData/Prueba/Construcción/Productos/Debug-iphoneos/TestApp.aplicación.dSYM/Contenidos/Recursos/ENANO/Prueba (para arquitectura binarios armv6): Mach-O dSYM compañero archivo brazo
DerivedData/Prueba/Construcción/Productos/Debug-iphoneos/TestApp.aplicación.dSYM/Contenidos/Recursos/ENANO/Prueba (para la arquitectura armv7): Mach-O dSYM compañero archivo brazo
DerivedData/Prueba/Construcción/Productos/Debug-iphoneos/TestApp.aplicación.dSYM/Contenidos/Recursos/ENANO/Prueba (para arquitectura cputype (12) cpusubtype (11)): Mach-O dSYM compañero archivo brazo

He instalado con éxito y puso en marcha la aplicación en iOS 4.2 2gen iPod touch mediante la apertura de xcode 4.4.1, a continuación, Product -> Run without building.

  • Al Archivo de su producto, puede experimentar de nuevo la Manzana Mach-O error del Vinculador, esta vez involucrando a otros archivos, como libarclite_iphoneos.a o libclang_rt.ios.a:
ld: es universal (2 rebanadas), pero no contiene(n) binarios armv6 slice: /Aplicaciones/Xcode.aplicación/Contenido/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphoneos.una para la arquitectura binarios armv6
ld: es universal (2 rebanadas), pero no contiene(n) binarios armv6 slice: /Aplicaciones/Xcode.aplicación/Contenido/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/4.1/libclang_rt.de ios.una para la arquitectura binarios armv6

El procedimiento utilizado para crt1.3.1.o se aplica a estos archivos también, y se solucionará el error de permitir que Xcode con éxito archivar el proyecto: se puede utilizar la ruta de acceso impreso por ld para buscar el archivo y unirse a la binarios armv6 sector con lipo; sólo ten en cuenta que libclang_rt.de ios.en las anteriores versiones de Xcode no se encuentra en Xcode.app/[...]/usr/lib/clang/4.1 pero en Xcode.app/[...]/usr/lib/clang/4.0.

Me ha archivado el archivo, implementado con un ad-hoc perfil de distribución, y probado en el iPhone 3G (4.2.1) y el iPhone 3GS (6.0).

  • Última edición : nosotros no podemos lanzar la aplicación. En la Organizer, no es el mensaje : los Dispositivos de tipo "iPhone 3G" no son compatibles con esta versión de Xcode.

Pero un ls de la DeviceSupport muestra :

 ls /Aplicaciones/Xcode.aplicación/Contenido/Developer/Platforms/iPhoneOS.plataforma/DeviceSupport/ 
4.2 4.3 5.0 5.1 6.0 (10A403)

Sin diferencias en la 4.2 directorio de Xcode 4.4.1.

La pregunta ahora es: ¿cómo Xcode detección de dispositivo es compatible o no ?

Apertura /Applications/Xcode.app/Contents/Developer//Platforms/iPhoneOS.platform/Developer//Library/PrivateFrameworks/DTDeviceKitBase.framework/DTDeviceKitBase con Hex Fiend (u otro editor hexadecimal), y la sustitución de ascii 4.3 con 4.2 hacer que desaparezca el mensaje de error, y la aplicación instalada en el dispositivo aparecen (pero el dispositivo de bala en la lista de dispositivos todavía es rojo).

Luego tenemos que editar /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks//DTDeviceKit.framework/Versions/Current/DTDeviceKit y reemplazar :

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

A continuación, tenemos una naranja de bala en el Organizador (Xcode 4.5.1) :

La versión de iOS "iPhone" es demasiado antigua para usar con esta versión del SDK de iOS. Por favor, restaurar el dispositivo a una versión de OS que se enumeran a continuación.

Sistema operativo Instalado en el iPhone
4.2.1 (8C148)

Xcode Compatibles las Versiones de iOS
6.0 (10A403)
5.1
5.0
4.3

La pregunta es ahora: ¿dónde Xcode Compatibles las Versiones de iOS se definen ?

Como hay un 4.2 directorio /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/, que ya debería ser compatibles...

Tratado de copiar iPhoneOS4.2.sdk de Xcode 4.4.1 para /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/, pero no hacen dispositivo compatible.

Así que no he encontrado cómo agregar 4.2 dispositivo de apoyo en Xcode 4.5. Alguna idea ?

Conclusión : la compilación de binarios armv6/7/7s dentro de Xcode 4.5 es posible. Pero no es posible iniciar una aplicación en un 4.2 binarios armv6 dispositivo sin necesidad de comenzar de Xcode 4.4.

Actualización importante : funciona con Xcode 4.5.2 !

Ahora la viñeta es de color verde en Xcode 4.5.2 :-) El dispositivo aparece en la lista desplegable de cerca en el botón Ejecutar. Pero al intentar ejecutar la aplicación, entendió el mensaje :

Xcode no se pueden ejecutar utilizando el dispositivo seleccionado.
Elegir un destino con una arquitectura compatible en orden a ejecutar en este dispositivo.

Simplemente añadir binarios armv6 a la validez de las arquitecturas :-)

Otra nota : la Build Rule de origen de los archivos con los nombres que coincidan con : *.[mc] puede usar LLVM GCC 4.2 o Apple LLVM compiler 4.1o Default compiler

7voto

Jerome Puntos 138

Gracias por este útil script !

Yo combinado con éxito todas las infos de todo este post, el resultado es una completa secuencia de comandos es la siguiente. Este script requiere tener tanto Xcode 4.5.x y una anterior versión de Xcode apoyo binarios armv6 (Xcode 4.4.1 por ejemplo, instalado en /Aplicaciones/Xcode 4.4.1.de la aplicación)

La secuencia de comandos NO requieren para compilar primero en xcode 4.4.x, usted sólo tiene que lanzar su última versión de Xcode, seleccione la configuración de Lanzamiento y construir. (la Liberación de binarios armv6 configuración debería haber sido definido como se mencionó en el post original de Mike).

Se va a producir .aplicación compatible con los binarios armv6 armv7 y armv7s

Gracias a Mike por el guión 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 Puntos 304

Gracias por el post. Tenemos algunas aplicaciones construir así habían automatizado la construcción armv6 usando xcodebuild como usted sugiere. Esta es la parte de nuestro script (modificado como usamos bash) que hace eso, que puede ser agregado al script anterior. Esto podría ser añadido antes "# Debug / cordura 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 Puntos 129

Gracias a Mike por este útil tutorial y la secuencia de comandos. Como se ha mencionado por Piotr en los comentarios, la secuencia de comandos está fallando si ejecuta el archivo de comandos de Xcode, ya que utilizar otro directorio de generación para el archivado.

Aquí abajo está mi modificación de la secuencia de comandos para habilitar para la liberación normal de compilación y archivo de compilación específicos.

Se supone que los binarios armv6 construir se ejecuta antes de que según la traducción de las instrucciones originales de Mike. Utiliza la sintaxis de bash, porque es más fácil para mí a la franja de la base común el directorio de compilación. Por lo que esto implica de traducción de la original script para bash que es sólo una cuestión de reemplazar setenv por la exportación y el cambio de las sentencias if sintaxis.

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

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by: