Usar bibliotecas pré-compiladas

O NDK permite o uso de bibliotecas pré-compiladas estáticas e compartilhadas. Há dois casos de uso principais dessa função:

  • distribuir bibliotecas próprias a outros desenvolvedores que usam NDK sem distribuir as fontes
  • usar uma versão pré-compilada das próprias bibliotecas para acelerar a compilação

Esta página explica como usar bibliotecas pré-compiladas.

Declarar uma biblioteca pré-compilada

É necessário declarar cada biblioteca pré-compilada usada como um módulo independente único. Para fazer isso, faça os procedimentos a seguir:

  1. Dê um nome ao módulo. Esse nome não precisa ser igual ao da biblioteca pré-compilada.
  2. No arquivo Android.mk do módulo, atribua o caminho para a biblioteca pré-compilada fornecida a LOCAL_SRC_FILES. Especifique o caminho em relação ao valor da variável LOCAL_PATH.

    Observação: É necessário selecionar a versão da biblioteca pré-compilada apropriada para a ABI com que pretende trabalhar. Para mais informações sobre como verificar a compatibilidade das bibliotecas com as ABIs, consulte Selecionar ABIs para bibliotecas pré-compiladas.

  3. Inclua PREBUILT_SHARED_LIBRARY ou PREBUILT_STATIC_LIBRARY para bibliotecas compartilhadas (.so) ou estáticas (.a), respectivamente.

Veja um exemplo trivial que assume que a biblioteca pré-compilada libfoo.so está no mesmo diretório do arquivo Android.mk que a descreve.

LOCAL_PATH := $(call my-dir)

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

Nesse exemplo, o nome do módulo é igual ao da biblioteca pré-compilada.

O sistema de compilação coloca uma cópia da biblioteca compartilhada pré-compilada em $PROJECT/obj/local e outra, sem informações de depuração, em $PROJECT/libs/<abi>. Aqui, $PROJECT é o diretório raiz do seu projeto.

Referenciar a biblioteca pré-compilada em outros módulos

Para referenciar a biblioteca compartilhada em outros módulos, especifique seu nome como o valor das variáveis LOCAL_STATIC_LIBRARIES ou LOCAL_SHARED_LIBRARIES nos arquivos Android.mk associados a esses outros módulos.

Por exemplo, a descrição de um módulo que usa libfoo.so pode ser a seguinte:

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

Aqui, LOCAL_MODULE é o nome do módulo que referencia a biblioteca pré-compilada e LOCAL_SHARED_LIBRARIES é o nome da biblioteca.

Exportar cabeçalhos para bibliotecas pré-compiladas

O código em foo-user.c depende de declarações específicas normalmente localizadas em um arquivo de cabeçalho, como foo.h, fornecido com a biblioteca pré-compilada. Por exemplo, foo-user.c pode ter uma linha como a seguinte:

#include <foo.h>

Nesse caso, é necessário fornecer o cabeçalho e o caminho de inclusão correspondente ao compilador durante a compilação do módulo foo-user. Uma forma simples de fazer isso é usar exportações na definição do módulo pré-compilado. Por exemplo, desde que o cabeçalho foo.h esteja no diretório include associado ao módulo pré-compilado, é possível declará-lo da seguinte forma:

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

A definição de LOCAL_EXPORT_C_INCLUDES aqui garante que o sistema de compilação exporte o caminho para o diretório include da biblioteca compartilhada, adicionando esse caminho ao valor do LOCAL_C_INCLUDES do módulo dependente dele.

Essa operação permite que o sistema de compilação encontre os cabeçalhos necessários.

Depurar bibliotecas pré-compiladas

É recomendável fornecer bibliotecas compartilhadas pré-compiladas que tenham símbolos de depuração. O sistema de compilação do NDK sempre remove os símbolos da versão da biblioteca instalada em $PROJECT/libs/<abi>/, mas é possível usar a versão de depuração para depurar com ndk-gdb.

Selecionar ABIs para bibliotecas pré-compiladas

É necessário selecionar a versão correta da biblioteca pré-compilada compartilhada para a ABI com que pretende trabalhar. A variável TARGET_ARCH_ABI no arquivo Android.mk podem apontar o sistema de compilação na versão apropriada da biblioteca.

Por exemplo, considere um projeto que tem duas versões da biblioteca libfoo.so:

armeabi/libfoo.so
x86/libfoo.so

O snippet a seguir mostra como usar TARGET_ARCH_ABI para que o sistema de compilação selecione a versão correta da 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)

Se você especificou armeabi como o valor de TARGET_ARCH_ABI, o sistema de compilação usa a versão de libfoo.so localizada no diretório armeabi. Se você tiver especificado x86 como o valor TARGET_ARCH_ABI, o sistema de compilação usará a versão do diretório x86.