Cómo incorporar el archivo de hacer existente con Android NDK
Así que tengo un enorme proyecto C existente que he colocado en el directorio $PROJECT/jni
. Este proyecto se realiza normalmente ejecutando un script de configuración que crea los Makefiles, lo que permite que el proyecto se compile mediante make
.
Este proyecto es bastante grande y tiene muchos directorios que contienen archivos de origen y archivos de cabecera.
- Android-ndk Adición de bibliotecas estáticas al android.mk
- Construyendo Android desde fuentes: unsupported reloc 43
- Copia varios archivos txt en / system usando Android.mk
- Cómo compilar GCC para android?
- Android NDK: Incluye la biblioteca de boost c ++
Supongo que me falta una comprensión fundamental aquí de cómo Android.mk
se supone que funciona. ¿Se supone que debe reemplazar el configure y makefile que se utiliza actualmente para compilar el proyecto? ¿O estaría incorporando el makefile generado desde mi script de configuración en Android.mk
? Los ejemplos que proporcionan son bastante triviales con sólo unos pocos archivos de origen. Mi directorio jni
parece más a:
jni/ folder1/subfolder1 folder1/subfolder2 folder1/source folder2/source ..... foldern/source configure/ configure/configure.sh Makefile Android.mk
Los makefiles generados son bastante extensos (buena cantidad de configuración y hay uno en cada directorio) por lo que estoy poco perdido en cuanto a cómo abordar esto.
EDITAR:
El problema principal es que los ejemplos que se envían con el NDK son ejemplos triviales. Tienen 3-5 archivos de origen en el directorio jni de nivel superior. Mi problema es que se trata de un enorme proyecto con una configuración compleja con 4 carpetas de nivel superior cada una con muchos subdirectorios. No puedo simplemente mover la fuente a la carpeta jni y ejecutar el compilador ndk.
- Guardar vista como mapa de bits, sólo obtener pantalla en negro
- Construir objeto compartido de C ++ al crear un proyecto de Android en Eclipse
- Android no puede construir el proyecto con NDK-Build.cmd de NDK r7
- Cómo configurar la variable GNUMAKE para que ndk-build funcione
- Cómo vincular cualquier biblioteca en la aplicación ndk
- ¿Dónde se supone Android.mk?
- Creación de Debug vs. Release en el NDK de Android
- Construya la aplicación del sistema gradle como parte de la compilación de AOSP
Para responder a tu pregunta, sí Android.mk
es el sistema de compilación de Android. Google apenas menciona que el "lenguaje" de este archivo se implementa como macros de GNU make. Los docs quieren que describas tu proyecto en términos de esas macros. Ellos manejan todos los detalles de la cruz-compilación grungy. Estoy bastante seguro de que Google ha adoptado este enfoque para mejorar la portabilidad hacia adelante de los archivos de Android.mk
medida que evolucionan las herramientas de desarrollo.
El resultado es que (y sé que no querrá oír esto) la mejor respuesta es probablemente escribir correctamente un NDK Android.mk
para su gran proyecto desde cero.
Este artículo establece las mismas observaciones que he hecho portar una biblioteca de unos 800 archivos y 300k SLOC. Desafortunadamente he quemado casi dos semanas llegando a la misma conclusión: La compilación cruzada hace que al menos algunos scripts de configure
fallen (resultan en archivos config.h
erróneos). Yo "inventó" prácticamente las mismas técnicas que usa en el artículo. Pero incluso después de tener una compilación limpia, la biblioteca estática resultante no funcionó completamente. Horas de depuración netted ninguna información útil. [Advertencia: No soy un experto en herramientas de configuración. Un gurú probablemente habría detectado mi error. Así que va.] Me tomó un par de días para crear un Android.mk
limpio. La biblioteca resultante ejecutó todas las pruebas por primera vez. Y se ha portado de manera limpia a través de varias revoluciones de herramientas de desarrollo.
Desafortunadamente la construcción de una biblioteca que utiliza configure
sin las herramientas automáticas significa construir su propio config.h
a mano para el entorno de destino. Esto puede no ser tan malo como suena. Los sistemas IME tienden a definir mucho más en sus entornos de configure
de lo que realmente utilizan. Obtener una idea clara de las dependencias reales puede compensar el tedioso esfuerzo durante la futura refactorización.
La declaración resumida del artículo lo dice todo:
Autotool es bueno sólo en los sistemas GNU y su uso para compilación cruzada puede ser realmente tedioso, confuso, propenso a errores o incluso imposible. El método descrito aquí es un hack y debe ser utilizado bajo su propio riesgo.
Lo siento, no tengo una sugerencia más positiva.
Mi respuesta funciona mejor en tándem con la respuesta de Gene .
La creación de ./configure
del archivo de configuración se basa en la compilación (y posiblemente en la ejecución) de pequeños fragmentos de código C
para cada prueba. Las pruebas de compilación sólo se pueden probar con éxito en un entorno de compilación cruzada. Sin embargo, las pruebas de compilación y ejecución son imposibles de ejecutar en un entorno de compilación cruzada. El éxito de cada prueba establece una variable correspondiente en la plantilla config.h.in
para crear el config.h
.
Por lo tanto, para iniciar el proceso de conversión, deberá configurar CPP
, CC
, LD
y otras herramientas en el conjunto de herramientas de compilador cruzado (probablemente las del NDK
) y, a continuación, ejecutar ./configure
. Una vez hecho esto, necesitará corregir el config.h
para que coincida con su entorno de destino. Este es el paso más crítico y más propenso a errores.
En cuanto a Android.mk
, sigue un formato muy cercano a Makefile.am
que puede convertirse fácilmente en él. Puede ignorar el Makefile.in
y el Makefile
, ya que se generan desde Makefile.am
.
Para tomar un ejemplo de archivo (versión 5.11), corrí configure con las siguientes opciones,
./configure --host arm-toshiba-linux-androideabi --build x86_64-linux-gnu \ --prefix=/data/local/ host_alias=arm-linux-androideabi \ "CFLAGS=--sysroot=~/ndk/platforms/android-8/arch-arm -Wall -Wextra" \ "CPPFLAGS=--sysroot=~/ndk/platforms/android-8/arch-arm" \ CPP=arm-linux-androideabi-cpp
El siguiente paso era tomar el src/Makefile.am
como se muestra a continuación:
MAGIC = $(pkgdatadir)/magic lib_LTLIBRARIES = libmagic.la include_HEADERS = magic.h bin_PROGRAMS = file AM_CPPFLAGS = -DMAGIC='"$(MAGIC)"' AM_CFLAGS = $(CFLAG_VISIBILITY) @WARNINGS@ libmagic_la_SOURCES = magic.c apprentice.c softmagic.c ascmagic.c \ encoding.c compress.c is_tar.c readelf.c print.c fsmagic.c \ funcs.c file.h readelf.h tar.h apptype.c \ file_opts.h elfclass.h mygetopt.h cdf.c cdf_time.c readcdf.c cdf.h libmagic_la_LDFLAGS = -no-undefined -version-info 1:0:0 if MINGW MINGWLIBS = -lgnurx -lshlwapi else MINGWLIBS = endif libmagic_la_LIBADD = $(LTLIBOBJS) $(MINGWLIBS) file_SOURCES = file.c file_LDADD = libmagic.la CLEANFILES = magic.h EXTRA_DIST = magic.h.in HDR= $(top_srcdir)/src/magic.h.in BUILT_SOURCES = magic.h magic.h: ${HDR} sed -e "s/X.YY/$$(echo @VERSION@ | tr -d .)/" < ${HDR} > $@
Y crear el Android.mk
de esto.
El último y más importante paso fue modificar el config.h
para reflejar con precisión el estado del sistema de destino. Este será un proceso manual que no puedo dar una solución para, principalmente involucrando la mirada en el configure.log, mirando en los encabezados y "invocando" Google. Los frutos de este trabajo están disponibles en XDA .
He aquí una solución para hacer las cosas al revés: la construcción de la biblioteca externa y el paquete de Android de Makefiles estándar.
Como requisito previo, es necesario instalar todo lo necesario para hacer el desarrollo de la línea de comandos de Android:
- Una cadena de herramientas independiente, consulte la documentación incluida en el Android NDK;
- hormiga.
La estructura del ejemplo es: un directorio para la biblioteca externa y un directorio para las fuentes de Android al mismo nivel con un Makefile en cada directorio y un Makefile recursivo de nivel superior:
Makefile mylib/ Makefile android/ Makefile
El mylib/Makefile
genera una biblioteca estática:
AR=/path/to/standalone/bin/arm-linux-androideabi-ar CC=/path/to/standalone/bin/arm-linux-androideabi-gcc libmylib.a: mylib.o $(AR) rcs libmylib.a mylib.o mylib.o: mylib.c $(CC) -c mylib.c -o mylib.o
El android/Makefile
está proporcionando reglas para construir el paquete de Android:
- Necesitamos una dependencia para copiar
mylib
cuando es modificado; - Estamos utilizando un archivo
jni/ndkmake.c
para envolver las llamadas amylib
y proporcionar material específico de android; - El paquete android depende de las fuentes Java y de la biblioteca compartida.
El Makefile proporciona dos target: release
(el valor por defecto) y debug
para construir un paquete de lanzamiento o uno de depuración.
NDK_BUILD=/path/to/ndk-build JAVASRC=src/com/example/ndkmake/NdkMake.java release: bin/NdkMake-release-unsigned.apk debug: bin/NdkMake-debug.apk bin/NdkMake-release-unsigned.apk: libs/armeabi/libndkmake.so $(JAVASRC) ant release bin/NdkMake-debug.apk: libs/armeabi/libndkmake.so $(JAVASRC) ant debug libs/armeabi/libndkmake.so: jni/ndkmake.c jni/libmylib.a $(NDK_BUILD) jni/libmylib.a: ../mylib/libmylib.a cp ../mylib/libmylib.a jni/libmylib.a
El archivo Android.mk
proporciona reglas para incluir la biblioteca estática en la compilación, como un precompuesto. Estamos incluyendo encabezados de la biblioteca LOCAL_EXPORT_C_INCLUDES
usando LOCAL_EXPORT_C_INCLUDES
.
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := ndkmake LOCAL_SRC_FILES := ndkmake.c LOCAL_STATIC_LIBRARIES := mylib-prebuilt include $(BUILD_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := mylib-prebuilt LOCAL_SRC_FILES := libmylib.a LOCAL_EXPORT_C_INCLUDES := ../mylib/ include $(PREBUILT_STATIC_LIBRARY)
Ahora solo necesitamos un Makefile de nivel superior para construir los dos subdirectorios:
all: libmylib package libmylib: cd mylib && $(MAKE) package: cd android && $(MAKE)
Cualquier cambio en la biblioteca, en las fuentes jni o en las fuentes Java activará una reconstrucción del paquete.
- ¿Puedo usar componentes de polímero / web en una aplicación androide nativa sin Cordova?
- Solicitud de URL de visualización web de Android con cadena de consulta