Cómo usar bibliotecas compiladas previamente

El NDK admite el uso de bibliotecas previamente compiladas, 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 previamente compiladas.

Cómo declarar una biblioteca previamente compilada

Debes declarar cada biblioteca previamente compilada 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 previamente compilada.
  2. En el archivo Android.mk del módulo, asigna a LOCAL_SRC_FILES la ruta de acceso a la biblioteca previamente compilada 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 previamente compilada 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 desde otros módulos

Para hacer referencia a una biblioteca previamente compilada 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 previamente compiladas

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 previamente compilada. 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 previamente compiladas

Recomendamos que proporciones bibliotecas previamente compiladas 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.

Cómo seleccionar ABI para bibliotecas previamente compiladas

Debes asegurarte de seleccionar la versión de la biblioteca previamente compilada que hayas compartido y que sea correcta para la 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.