ios xcode cocoa-touch frameworks ios-universal-framework

ios - ¿Cómo exportar Cocoa Touch Framework "gordo"(para simulador y dispositivo)?



xcode cocoa-touch (6)

Básicamente para esto encontré muy buena solución. solo necesita seguir estos sencillos pasos.

  1. Crea un marco táctil de cacao.
  2. Establecer código de bits habilitado en No.
  3. Seleccione su objetivo y elija editar esquemas. Seleccione Ejecutar y elija Liberar de la pestaña Información.
  4. No se requiere otra configuración.
  5. Ahora construya el marco para cualquier simulador, ya que el simulador se ejecuta en la arquitectura x86.
  6. Haga clic en el grupo Productos en Project Navigator y busque el archivo .framework.
  7. Haga clic derecho sobre él y haga clic en Mostrar en el buscador. Copie y pegue en cualquier carpeta, personalmente prefiero el nombre ''simulador''.
  8. Ahora cree el marco para el dispositivo iOS genérico y siga los pasos del 6 al 9. Simplemente cambie el nombre de la carpeta a ''dispositivo'' en lugar de ''simulador''.
  9. Copie el archivo .framework del dispositivo y péguelo en cualquier otro directorio. Prefiero el súper directorio inmediato de ambos. Entonces la estructura del directorio ahora se convierte en:
    • Escritorio
    • dispositivo
      • MyFramework.framework
    • simulador
      • MyFramework.framework
    • MyFramework.framework Ahora abra la terminal y el CD al escritorio. Ahora comience a escribir el siguiente comando:

simulador lipo -crear ''dispositivo / MyFramework.framework / MyFramework'' ''/ MyFramework.framework / MyFramework'' -salida ''MyFramework.framework / MyFramework''

y eso es. Aquí fusionamos el simulador y la versión del dispositivo del presente binario MyFramework dentro de MyFramework.framework. Obtenemos un marco universal que se construye para todas las arquitecturas, incluidos el simulador y el dispositivo.

Con Xcode 6 tenemos la capacidad de crear sus propios Cocoa Frameworks dinámicos de Cocoa Frameworks .

Porque:

  • El simulador todavía usa 32-bit biblioteca de 32-bit

  • a partir del 1 de junio de 2015, las actualizaciones de aplicaciones enviadas a la tienda de aplicaciones deben incluir soporte de 64 bits y deben estar compiladas con el SDK de iOS 8 ( developer.apple.com )

Tenemos que hacer una gran biblioteca para ejecutar proyectos en dispositivos y simuladores. es decir, admite 32 y 64 bits en Frameworks.

Pero no encontré ningún manual, cómo exportar Universal Fat Framework para una futura integración con otros proyectos (y compartir esta biblioteca con alguien).

Aquí están mis pasos para reproducir:

  1. Establezca ONLY_ACTIVE_ARCH=NO en la Build Settings

  2. Agregue soporte armv7 armv7s arm64 i386 x86_64 a Architectures (seguro)

  1. Construye Framework y ábrelo en Finder:

  1. Agregar este marco a otro proyecto

Resultado actual:

Pero al final todavía tengo problemas para ejecutar un proyecto con este marco en dispositivos y simulador a la vez.

  • si tomo el marco de la carpeta Debug-iphoneos , funciona en dispositivos y obtiene un error en los simuladores: ld: symbol(s) not found for architecture i386

    xcrun lipo -info CoreActionSheetPicker

    Las arquitecturas en el archivo grueso: CoreActionSheetPicker son: armv7 armv7s arm64

  • si tomo framework de la carpeta Debug-iphonesimulator , funciona en simuladores. y tengo un error en el dispositivo: ld: symbol(s) not found for architecture arm64

    xcrun lipo -info CoreActionSheetPicker

    Las arquitecturas en el archivo grueso: CoreActionSheetPicker son: i386 x86_64

Entonces, ¿cómo crear un marco dinámico que funcione en dispositivos y simuladores?

Esta respuesta se relaciona con Xcode 6 iOS Creación de un marco Cocoa Touch: problemas de arquitectura, pero no es duplicado.

Actualizar:

Encontré un "truco sucio" para este caso. Mira mi respuesta a continuación . Si alguien conoce una forma más conveniente, ¡hágamelo saber!


Esta no es una solución tan clara, pero solo hay una forma, que encuentro:

  1. Establezca ONLY_ACTIVE_ARCH=NO en la Build Settings

    • Construir biblioteca para simulador
    • Construir biblioteca para dispositivo
  2. Abrir en la carpeta de Products consola para su marco (puede abrirlo abriendo la carpeta del marco y cd .. desde allí)

  1. Ejecute this script desde la carpeta Products . Crea un marco gordo en esta carpeta. (o hágalo manualmente como se explica a continuación en 3. 4. )

O:

  1. Combine estos 2 Frameworks usando lipo por este script (reemplace YourFrameworkName por su nombre de Framework)

    lipo -create -output "YourFrameworkName" "Debug-iphonesimulator/YourFrameworkName.framework/YourFrameworkName" "Debug-iphoneos/YourFrameworkName.framework/YourFrameworkName"

  2. Reemplace con uno nuevo binario de los marcos existentes:

    cp -R Debug-iphoneos/YourFrameworkName.framework ./YourFrameworkName.framework mv YourFrameworkName ./YourFrameworkName.framework/YourFrameworkName

  1. Beneficio: ./YourFrameworkName.framework - ¡ es un binario gordo listo para usar! ¡Puedes importarlo a tu proyecto!

Para proyecto, que no está en Espacios de trabajo:

También puede intentar usar esta esencia como se describe here . Pero parece que no funciona para proyectos en espacios de trabajo.


La actualidad de esta respuesta es: julio de 2015. Es muy probable que las cosas cambien.

TLDR;

Actualmente, Xcode no tiene herramientas para la exportación automática del marco universal de grasa, por lo que el desarrollador debe recurrir al uso manual de la herramienta lipo . Además, de acuerdo con este radar, antes de enviarlo al desarrollador de AppStore, que es el consumidor del framework, también debe usar lipo para quitar los segmentos del simulador de un framework.

La respuesta más larga sigue

Hice una investigación similar en el tema (el enlace en la parte inferior de la respuesta).

No había encontrado ninguna documentación oficial sobre la distribución, por lo que mi investigación se basó en la exploración de los foros de desarrolladores de Apple, los proyectos Carthage y Realm y mis propios experimentos con xcodebuild , lipo , herramientas de xcodebuild .

Aquí hay una cita larga (con un poco de margen de mi parte) de la aplicación de exportación de hilos de los foros de desarrolladores de Apple con marco incrustado :

¿Cuál es la forma correcta de exportar un marco desde un proyecto marco?

Actualmente, la única forma es exactamente lo que has hecho:

  • Construya el objetivo para el simulador y el dispositivo iOS.
  • Navegue a la carpeta DerivedData de Xcode para ese proyecto y lipo los dos binarios juntos en un solo marco. Sin embargo, cuando cree el objetivo de marco en Xcode, asegúrese de ajustar la configuración de destino ''Construir arquitectura activa solo'' a ''NO''. Esto permitirá que Xcode construya el objetivo para múltiples tipos de binarty (arm64, armv7, etc.). Esta sería la razón por la que funciona desde Xcode pero no como un binario independiente.

  • También querrá asegurarse de que el esquema esté configurado en una versión de lanzamiento y compile el objetivo del marco contra el lanzamiento. Si todavía recibe un error de biblioteca no cargada, verifique los segmentos de código en el marco.

  • Utilice lipo -info MyFramworkBinary y examine el resultado.

lipo -info MyFrameworkBinary

El resultado es i386 x86_64 armv7 arm64

  • Los marcos universales modernos incluirán 4 segmentos, pero podrían incluir más: i386 x86_64 armv7 arm64 Si no ve al menos estos 4, podría deberse a la configuración de Build Active Architecture.

Esto describe el proceso más o menos lo mismo que @skywinder lo hizo en su respuesta.

Así es como Cartago usa lipo y Realm usa lipo .

DETALLE IMPORTANTE

Hay un radar: Xcode 6.1.1 y 6.2: los marcos de iOS que contienen segmentos de simulador no se pueden enviar a la App Store y una larga discusión al respecto en el Realm#1163 y Carthage#188 que terminó en una solución especial:

antes de enviarlos al marco de aplicaciones iOS de iOS, los binarios deben eliminarse de los segmentos del simulador

Cartago tiene un código especial: CopyFrameworks y la documentación correspondiente:

Este script funciona alrededor de un error de envío de la tienda de aplicaciones activado por binarios universales.

Realm tiene un script especial: strip-frameworks.sh y la documentación correspondiente:

Este paso es necesario para evitar un error de envío de la App Store al archivar binarios universales.

También hay un buen artículo: Eliminación de arquitecturas no deseadas de bibliotecas dinámicas en Xcode .

Yo mismo utilicé el strip-frameworks.sh de Realm, que me funcionó perfectamente sin ninguna modificación, aunque, por supuesto, cualquiera es libre de escribir uno desde cero.

El enlace a mi tema que recomiendo leer porque contiene otro aspecto de esta pregunta: firma de código - Creación de marcos iOS / OSX: ¿es necesario firmarlos antes de distribuirlos a otros desarrolladores?


La respuesta de @Stainlav fue muy útil, pero lo que hice fue compilar dos versiones del marco (una para el dispositivo y otra para el simulador) y luego agregué la siguiente Run Script Phase para copiar automáticamente el marco precompilado requerido para la arquitectura en ejecución

echo "Copying frameworks for architecture: $CURRENT_ARCH" if [ "${CURRENT_ARCH}" = "x86_64" ] || [ "${CURRENT_ARCH}" = "i386" ]; then cp -af "${SRCROOT}/Frameworks/Simulator/." "${SRCROOT}/Frameworks/Active" else cp -af "${SRCROOT}/Frameworks/Device/." "${SRCROOT}/Frameworks/Active" fi

De esta manera, no tengo que usar lipo para crear un marco de trabajo grueso, ni el strip-frameworks.sh del strip-frameworks.sh para eliminar los cortes innecesarios al enviar a la App Store.


Mi respuesta cubre los siguientes puntos:

  • Cree un marco que funcione tanto para el simulador como para el dispositivo

  • ¿Cómo exportar Cocoa Touch Framework "gordo" (tanto para el simulador como para el dispositivo)?

  • Símbolos indefinidos para arquitectura x86_64

  • ld: símbolo (s) no encontrado (s) para arquitectura x86_64

Pasos 1: Primero construye tus frameworks con Simulator target

Pasos 2: después del éxito del proceso de construcción del simulador, ahora construya para su marco con la selección de destino del dispositivo o la selección genérica del dispositivo iOS

Paso 3: Ahora seleccione su objetivo de marco y para eso En "Fases de compilación", seleccione "Agregar secuencia de comandos de ejecución" y copie el código de secuencia de comandos a continuación)

Paso 4: Ahora, finalmente, vuelva a compilar y su marco está listo para la compatibilidad del simulador y del dispositivo. ¡¡¡¡Hurra!!!!

[Nota: debemos tener ambos marcos compatibles listos antes del paso final 4 (simulador y arquitectura de dispositivo compatibles, si no, siga los pasos 1 y 2 anteriores correctamente)

Ver la imagen de referencia:

Ponga el siguiente código en el área de shell:

#!/bin/sh UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal # make sure the output directory exists mkdir -p "${UNIVERSAL_OUTPUTFOLDER}" # Step 1. Build Device and Simulator versions xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build xcodebuild -target "${PROJECT_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build # Step 2. Copy the framework structure (from iphoneos build) to the universal folder cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/" # Step 3. Copy Swift modules from iphonesimulator build (if it exists) to the copied framework directory SIMULATOR_SWIFT_MODULES_DIR="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule/." if [ -d "${SIMULATOR_SWIFT_MODULES_DIR}" ]; then cp -R "${SIMULATOR_SWIFT_MODULES_DIR}" "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule" fi # Step 4. Create universal binary file using lipo and place the combined executable in the copied framework directory lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}" # Step 5. Convenience step to copy the framework to the project''s directory cp -R "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework" "${PROJECT_DIR}" # Step 6. Convenience step to open the project''s directory in Finder open "${BUILD_DIR}/${CONFIGURATION}-universal"


Solo quiero actualizar esta gran respuesta de @odm. Desde Xcode 10, la variable CURRENT_ARCH ya no refleja la arquitectura de construcción. Así que cambié el script para verificar la plataforma en su lugar:

echo "Copying frameworks for platform: $PLATFORM_NAME" rm -R "${SRCROOT}/Frameworks/Active" if [ "${PLATFORM_NAME}" = "iphonesimulator" ]; then cp -af "${SRCROOT}/Frameworks/Simulator/." "${SRCROOT}/Frameworks/Active" else cp -af "${SRCROOT}/Frameworks/Device/." "${SRCROOT}/Frameworks/Active" fi

También agregué una línea para borrar el directorio de destino antes de copiar, porque noté que los archivos adicionales en subdirectorios no se sobrescribirían de otra manera.