studio - ejecutar c++ android
CompilaciĆ³n de una biblioteca externa de C++ para usar con proyectos iOS (6)
Así que he usado muchas bibliotecas de C ++ de terceros en mis proyectos de iOS. Existen diferentes estrategias que las personas usan para esto. Como algunos ya han citado, puede incluir el código dentro del proyecto directamente, compilar la lib estática con Xcode o compilarla en la línea de comandos. En el caso de las bibliotecas C ++ multiplataforma que utilizan el sistema de configuración y compilación GNU, prefiero la línea de comandos. Solo necesita compilarlo una vez y solo debe volver a visitarlo si necesita actualizar la versión o agregar una nueva porción de arquitectura.
El enfoque generalizado que desea es:
-
Averigüe los argumentos de configuración adecuados para usar para construir cada segmento. Por lo general, solo necesita concentrarse en lograr que uno de los brazos y el i386 funcionen. El resto es fácil, tienes esto hecho. En algunos casos, en realidad necesita modificar el archivo de configuración para agregar el host o hacer otros ajustes.
-
Una vez que pueda construir todas las rebanadas, desea ejecutar lipo para construir un binario gordo.
La mejor manera de lidiar con esto es crear un script de compilación que haga todo el trabajo por usted. De esta manera, es más fácil rehacer. Más importante aún, puede reutilizar el script o permutarlo para construir otras bibliotecas externas.
Hay muchas formas de construir el script. Acá hay uno. Resulta que tengo varias variaciones de este tipo de script. Este script se usó para construir cURL. Funcionó más o menos para presagiar con muy poca modificación (es decir, cambiar el rizo a presagiar). Tenga en cuenta que no lo probé en Xcode (es decir, lo vinculé y lo ejecuté). Descubrí que tenía que deshabilitar sqlite, de lo contrario, creó elementos de herramienta que no se construyeron correctamente. Si lo necesita, puede resolver esa parte.
Hay muchas maneras de hacerlo más elegante. Por ejemplo, usando una matriz para almacenar todas las arquitecturas. Esto es solo fuerza bruta.
Los puntos clave del guión son:
- Obteniendo el último SDK
- Construyendo cada rebanada
- Entonces corriendo lipo
Tenga en cuenta que debería funcionar fuera de la caja, sin embargo, YMMV. Esté preparado para tener que depurarlo si es necesario. Por ejemplo, no he confirmado el tipo de host, pero en general eso es lo que siempre he usado. Desea poner esto en el directorio de presagiado (mismo directorio donde configurar). Cuando se hace, todas las arquitecturas están en el directorio de salida. La biblioteca universal está en el directorio de presagio.
También recuerde que es su responsabilidad vincular correctamente en la biblioteca universal, así como tener la ruta de búsqueda de archivos de encabezado definida correctamente.
#!/bin/bash
PLATFORMPATH="/Applications/Xcode.app/Contents/Developer/Platforms"
TOOLSPATH="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin"
export IPHONEOS_DEPLOYMENT_TARGET="8.0"
pwd=`pwd`
findLatestSDKVersion()
{
sdks=`ls $PLATFORMPATH/$1.platform/Developer/SDKs`
arr=()
for sdk in $sdks
do
arr[${#arr[@]}]=$sdk
done
# Last item will be the current SDK, since it is alpha ordered
count=${#arr[@]}
if [ $count -gt 0 ]; then
sdk=${arr[$count-1]:${#1}}
num=`expr ${#sdk}-4`
SDKVERSION=${sdk:0:$num}
else
SDKVERSION="8.0"
fi
}
buildit()
{
target=$1
hosttarget=$1
platform=$2
if [[ $hosttarget == "x86_64" ]]; then
hostarget="i386"
elif [[ $hosttarget == "arm64" ]]; then
hosttarget="arm"
fi
export CC="$(xcrun -sdk iphoneos -find clang)"
export CPP="$CC -E"
export CFLAGS="-arch ${target} -isysroot $PLATFORMPATH/$platform.platform/Developer/SDKs/$platform$SDKVERSION.sdk -miphoneos-version-min=$SDKVERSION"
export AR=$(xcrun -sdk iphoneos -find ar)
export RANLIB=$(xcrun -sdk iphoneos -find ranlib)
export CPPFLAGS="-arch ${target} -isysroot $PLATFORMPATH/$platform.platform/Developer/SDKs/$platform$SDKVERSION.sdk -miphoneos-version-min=$SDKVERSION"
export LDFLAGS="-arch ${target} -isysroot $PLATFORMPATH/$platform.platform/Developer/SDKs/$platform$SDKVERSION.sdk"
mkdir -p $pwd/output/$target
./configure --prefix="$pwd/output/$target" --disable-shared --disable-sqlite --host=$hosttarget-apple-darwin
make clean
make
make install
}
findLatestSDKVersion iPhoneOS
buildit armv7 iPhoneOS
buildit armv7s iPhoneOS
buildit arm64 iPhoneOS
buildit i386 iPhoneSimulator
buildit x86_64 iPhoneSimulator
LIPO=$(xcrun -sdk iphoneos -find lipo)
$LIPO -create $pwd/output/armv7/lib/libpresage.a $pwd/output/armv7s/lib/libpresage.a $pwd/output/arm64/lib/libpresage.a $pwd/output/x86_64/lib/libpresage.a $pwd/output/i386/lib/libpresage.a -output libpresage.a
Soy completamente nuevo en el uso de bibliotecas C ++, así que aprecio que esto sea un poco específico para mi caso (hágamelo saber y puedo proporcionar más detalles).
Tengo una biblioteca externa de C ++ que estoy tratando de usar con un proyecto de iOS. La biblioteca sigue un patrón de configuración, creación y creación para generar un archivo de biblioteca .a. Cuando intento agregar este archivo de biblioteca a Xcode, aparece el siguiente error:
ignorando el archivo /Users/Developer/iOS/TestProj/libpresage.a, el archivo se creó para el archivo que no es la arquitectura que se está vinculando (i386):
/Users/Developer/iOS/TestProj/libpresage.a
En base a esta pregunta , he intentado convertir Build Active Architecture Only a NO, y obtengo el mismo error. Esto me hace sospechar que he compilado la biblioteca para la arquitectura incorrecta.
Ejecutar lipo -info en el archivo .a da:
el archivo de entrada libpresage.a no es un archivo grueso Archivo no grueso: libpresage.a
es arquitectura: x86_64
Dado que esto no es armv7s, armv7 o arm64, intento compilar la biblioteca de C ++ nuevamente con los siguientes parámetros:
1) Prueba
./configure CC="gcc -arch armv7s" /
CXX="g++ -arch armv7s" /
CPP="gcc -E" CXXCPP="g++ -E"
Error al compilar, obtengo:
ld: library not found for -lcrt1.3.1.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)
2) Prueba
./configure CC="gcc -arch arm64" /
CXX="g++ -arch arm64" /
CPP="gcc -E" CXXCPP="g++ -E"
Error al compilar, obtengo:
ld: warning: ld: warning: ignorando el archivo /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/lib/libSystem.dylib, falta la arquitectura requerida arm64 en archivo /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/lib/libSystem.dylib (2 cortes) ignorando el archivo /Applications/Xcode.app/Contents/ Developer / Platforms / MacOSX.platform / Developer / SDKs / MacOSX10.10.sdk / usr / lib / libstdc ++. Dylib, falta la arquitectura requerida arm64 en el archivo /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer /SDKs/MacOSX10.10.sdk/usr/lib/libstdc++.dylib (2 rebanadas)
ld: los ejecutables principales dinámicos deben vincularse con libSystem.dylib para la arquitectura arm64 clang: error: el comando del vinculador falló con el código de salida 1 (use -v para ver la invocación)
¿Hay algo obvio que me estoy perdiendo?
EDITAR:
Gracias por las respuestas, así que logré colocar la biblioteca en Xcode como un objetivo de compilación personalizado, señalando el comando ''make'' a las bibliotecas MakeFile. Esta construcción está bien.
Mis pasos desde aquí:
- Agregar una dependencia desde el objetivo de mi aplicación Objective C iOS al objetivo de compilación personalizado.
- Consulte la biblioteca y cree un contenedor Objective C ++.
- Esto parece estar bien hasta que necesito llamar a la biblioteca externa de C ++, luego aparece el error al compilar:
Símbolos indefinidos para arquitectura armv7: "Presage :: Presage (PresageCallback *)", referenciado desde: - [PresageBridge init] en PresageBridge.o "Presage :: ~ Presage ()", referenciado desde: - [PresageBridge init] en PresageBridge. o ld: símbolo (s) no encontrado (s) para la arquitectura armv7 clang: error: el comando del enlazador falló con el código de salida 1 (use -v para ver la invocación)
-
Mi objetivo C ++ wrapper (enlazando el encabezado de la biblioteca externa C ++ presage.h):
#import "PresageBridge.h" #include "presage.h" @implementation PresageBridge - (instancetype)init { if(self = [super init]) { Presage hello(&callback); } return self; }
-
Según el código anterior, no parece que me falte el encabezado, y lo interesante es que también he intentado crear una instancia de otras clases en la biblioteca externa y parece que funcionan, lo que sugiere que Xcode puede No enlace presage.h correctamente por alguna razón.
C ++ funciona en iOS, solo puede agregarlo en su proyecto. O si realmente desea tener su biblioteca dinámica, puede compilarla con Xcode y especificar su arquitectura de destino.
El guión de Mobile Ben es excelente, aparte de la línea final codifica el nombre de archivo de la biblioteca en el guión. El siguiente es un reemplazo para el último comando lipo y utiliza dinámicamente lipo combina cada archivo de biblioteca creado después de la compilación.
Cambiar la línea de Mobile Ben:
$LIPO -create $pwd/output/armv7/lib/libpresage.a $pwd/output/armv7s/lib/libpresage.a $pwd/output/arm64/lib/libpresage.a $pwd/output/x86_64/lib/libpresage.a $pwd/output/i386/lib/libpresage.a -output libpresage.a
a:
for t in `ls $pwd/output/armv7/lib/*.a` ;
do
export LIB=`basename $t`
export ARCHSTRING=""
for a in `ls $pwd/output`
do
export ARCSTRING="$ARCSTRING $pwd/output/$a/lib/$LIB "
done
$LIPO -create $ARCSTRING -output $LIB
done
Nota: No quería editar la respuesta de Mobile Ben con la nueva funcionalidad de código, y agregar esto como un formato de comentario perdido.
Esto es lo que funcionó para mí en Xcode 9 para dispositivos iOS (iPhone X):
1) Compile dylib con estos indicadores configurados de la siguiente manera:
a) "Directorio de instalación": @ ruta_ejecutable / Frameworks b) "Ruta de búsqueda de ruta de ejecución": @ ruta_ejecutable / Frameworks
Vea la imagen a continuación:
configuración de dylib en Xcode 9
2) En el proyecto Xcode donde se usa / vincula el dylib:
a) "Ruta de búsqueda de Runpath":
@ ejecutable_path / Frameworks
b) En "Fase de compilación-> Incrustar bibliotecas", asegúrese de seleccionar "Destino" como "Ejecutables" y Subtrayecto como "Frameworks", "Signo de código en copia" marcado:
Configurar la aplicación para vincular iOS
Este método se prueba y se usa con Xcode 9.2 y iPhone X.
David
Teniendo en cuenta que eres nuevo con las bibliotecas de C ++, creo que tendrás que investigar un poco más.
Sin embargo, trataré de describir algunos pasos que debe tener en cuenta:
- debe asegurarse de compilar para la misma arquitectura tanto la biblioteca estática (.a) como el proyecto
- a partir de su error, necesita compilar su biblioteca estática para i386 O cambiar su proyecto a x86_64 (la diferencia entre estas arquitecturas es un poco más compleja, pero por ahora digamos que i386 significa escritorio de 32 bits mientras que x86_64 significa escritorio de 64 bits)
- ¡Las arquitecturas de brazo son para iPhone, no para MacOS (es por eso que no puede encontrar bibliotecas con arquitectura de brazo dentro de la carpeta MacOSX)!
Existen múltiples formas de abordar estos problemas.
Para el primero, sugeriría incluir en su espacio de trabajo la biblioteca estática y agregarla como dependencia a su destino de compilación. Para esto necesitas entender las compilaciones de XCode.
Supongo que realmente está tratando de hacer una aplicación de teléfono, por lo que para la tercera opción, debe configurar su compilación g ++ para buscar en el iPhoneSDK desde XCode al vincular los objetivos del brazo (cuidar iPhoneOS.platform) para esto.
Hacer una construcción de brazo solo funcionará en iPhones. Si desea que funcione en el simulador, deberá vincular su biblioteca estática a las bibliotecas dentro de iPhoneSimulator.platform.
Si desea que su biblioteca estática funcione tanto para iPhone como para simulador de iPhone, necesitará crear una lib gorda (básicamente una biblioteca que contenga símbolos para ambas plataformas)
Si falta estas plataformas, puede descargarlas de XCode (pero creo que están allí)
Como puede ver, las cosas se volverán cada vez más complejas en el camino, por lo que le recomiendo usar XCode para compilar la biblioteca estática (todavía es factible con g ++ you).
Creo que los siguientes conceptos sobre los que sería útil investigar:
- brazo, x86, x86_64
- biblioteca estática
- enlace estático
- fat lib (biblioteca universal)
- Espacio de trabajo XCode con múltiples proyectos
Espero que esto ayude :).
Vuelva a configurar su arquitectura por defecto y luego intente lo siguiente. 1. En Build Phases-> Link Binary With Libraries, agregue las bibliotecas libz.dylib y libxml2.dylib a su proyecto. 2. En BuildSettings-> Buscar rutas, configure Buscar siempre rutas de usuario en Sí y, en Rutas de búsqueda de marco, agregue la ruta correcta de su marco. Use la terminal para obtener la ruta correcta de su marco. 3. Intente configurar su "Fuente del compilador como" en C ++ o use hit y trial y verifique con todas las opciones. Fuente de cumplimiento como también está en BuildSettings. Use cmd + f para buscarlo.
Pruebe estos y hágamelo saber, también cuénteme sobre el framework o sdk que está tratando de usar en su proyecto.