Uso de bibliotecas compiladas previamente

El NDK admite el uso de bibliotecas compiladas previamente, tanto estáticas como compartidas. Hay dos casos prácticos principales para esta función:

  • La distribución de las bibliotecas propias a desarrolladores del NDK de terceros sin distribuir tus fuentes.
  • El uso de una versión compilada previamente de las bibliotecas propias para acelerar la compilación.

En esta página se explica la manera de usar bibliotecas compiladas previamente.

Cómo declarar una biblioteca previamente compilada

Debes declarar cada biblioteca compilada previamente que uses como módulo independiente. Para hacerlo, sigue estos pasos:

  1. Dale un nombre al módulo. No es necesario que sea el mismo que el de la biblioteca compilada previamente.
  2. En el archivo Android.mk del módulo, asigna a LOCAL_SRC_FILES la ruta de acceso a la biblioteca compilada previamente que proporcionarás. Especifica la ruta de acceso relacionada con el valor de la variable LOCAL_PATH.

  3. Incluye PREBUILT_SHARED_LIBRARY o PREBUILT_STATIC_LIBRARY, según si usas una biblioteca compartida (.so) o estática (.a).

Aquí te mostramos un ejemplo simple en el que se supone que la biblioteca libfoo.so compilada previamente está en el mismo directorio que el archivo Android.mk que la describe.

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := foo-prebuilt
LOCAL_SRC_FILES := libfoo.so
include $(PREBUILT_SHARED_LIBRARY)

En este ejemplo, el nombre del módulo es el mismo que el de la biblioteca compilada previamente.

El sistema de compilación guarda una copia de la biblioteca compilada previamente compartida en $PROJECT/obj/local y otra sin información de depuración en $PROJECT/libs/<abi>. Aquí, $PROJECT es el directorio raíz de tu proyecto.

Cómo hacer referencia a la biblioteca previamente compilada previamente desde otros módulos

Para hacer referencia a una biblioteca compilada previamente desde otros módulos, especifica su nombre como el valor de la variable LOCAL_STATIC_LIBRARIES o LOCAL_SHARED_LIBRARIES en los archivos Android.mk asociados con los otros módulos.

Por ejemplo, la descripción de un módulo que usa libfoo.so podría ser la siguiente:

include $(CLEAR_VARS)
LOCAL_MODULE := foo-user
LOCAL_SRC_FILES := foo-user.c
LOCAL_SHARED_LIBRARIES := foo-prebuilt
include $(BUILD_SHARED_LIBRARY)

En este ejemplo, LOCAL_MODULE es el nombre del módulo que hace referencia a la compilación previa; LOCAL_SHARED_LIBRARIES es el nombre de la compilación previa en sí.

Cómo exportar encabezados para bibliotecas compiladas previamente

El código de foo-user.c depende de declaraciones específicas que, en general, están en un archivo de encabezado, como foo.h, distribuido con la biblioteca compilada previamente. Por ejemplo, foo-user.c podría tener una línea como la siguiente:

#include <foo.h>

En ese caso, debes proporcionar el encabezado y la ruta de acceso al compilador cuando compiles el módulo foo-user. Una forma sencilla de hacer eso es usar exportaciones en la definición del módulo compilado previamente. Por ejemplo, siempre que el encabezado foo.h esté en el directorio include asociado con el módulo compilado previamente, podrás declararlo de la siguiente manera:

include $(CLEAR_VARS)
LOCAL_MODULE := foo-prebuilt
LOCAL_SRC_FILES := libfoo.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)

La definición LOCAL_EXPORT_C_INCLUDES garantiza que el sistema de compilación exporte la ruta de acceso al directorio include de la biblioteca compilada previamente y que la anexe al valor de LOCAL_C_INCLUDES para el módulo que depende de ella.

Esta operación permite que el sistema de compilación busque los encabezados necesarios.

Cómo depurar bibliotecas compiladas previamente

Recomendamos que proporciones bibliotecas compiladas previamente compartidas y con símbolos de depuración. El sistema de compilación del NDK siempre quita los símbolos de la versión de la biblioteca que instala en $PROJECT/libs/<abi>/, pero puedes usar la versión de depuración para hacer depuraciones con ndk-gdb.

Selección de ABI para bibliotecas compiladas previamente

Debes asegurarte de seleccionar la versión de la biblioteca compilada previamente compartida que sea correcta para el ABI de destino. La variable TARGET_ARCH_ABI del archivo Android.mk puede apuntar el sistema de compilación a la versión adecuada de la biblioteca.

Por ejemplo, supongamos que tu proyecto tiene dos versiones de la biblioteca libfoo.so:

armeabi/libfoo.so
x86/libfoo.so

En el siguiente fragmento, se muestra cómo usar TARGET_ARCH_ABI de modo que el sistema de compilación seleccione la versión adecuada de la biblioteca:

include $(CLEAR_VARS)
LOCAL_MODULE := foo-prebuilt
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libfoo.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)

Si especificaste armeabi como el valor de TARGET_ARCH_ABI, el sistema de compilación usará la versión de libfoo.so ubicada en el directorio armeabi. Si especificaste x86 como el valor TARGET_ARCH_ABI, el sistema de compilación usará la versión del directorio x86.