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.
- Crea un marco táctil de cacao.
- Establecer código de bits habilitado en No.
- Seleccione su objetivo y elija editar esquemas. Seleccione Ejecutar y elija Liberar de la pestaña Información.
- No se requiere otra configuración.
- Ahora construya el marco para cualquier simulador, ya que el simulador se ejecuta en la arquitectura x86.
- Haga clic en el grupo Productos en Project Navigator y busque el archivo .framework.
- Haga clic derecho sobre él y haga clic en Mostrar en el buscador. Copie y pegue en cualquier carpeta, personalmente prefiero el nombre ''simulador''.
- 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''.
-
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 de32-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:
-
Establezca
ONLY_ACTIVE_ARCH=NO
en laBuild Settings
-
Agregue soporte
armv7 armv7s arm64 i386 x86_64
aArchitectures
(seguro)
- Construye Framework y ábrelo en Finder:
- 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:
-
Establezca
ONLY_ACTIVE_ARCH=NO
en laBuild Settings
-
- Construir biblioteca para simulador
- Construir biblioteca para dispositivo
-
Abrir en la carpeta de
Products
consola para su marco (puede abrirlo abriendo la carpeta del marco ycd ..
desde allí)
-
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:
-
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"
-
Reemplace con uno nuevo binario de los marcos existentes:
cp -R Debug-iphoneos/YourFrameworkName.framework ./YourFrameworkName.framework mv YourFrameworkName ./YourFrameworkName.framework/YourFrameworkName
-
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.