Usar bibliotecas pré-compiladas

O NDK permite o uso de bibliotecas pré-compiladas, tanto estáticas quanto compartilhadas. Há dois casos de uso principais dessa funcionalidade:

  • Distribuir bibliotecas próprias a desenvolvedores de terceiros que usam NDK sem distribuir suas 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

Você precisa declarar cada biblioteca pré-compilada que usa como um módulo independente único. Para fazer isso, siga as etapas 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 a LOCAL_SRC_FILES o caminho para a biblioteca pré-compilada fornecida. Especifique o caminho em relação ao valor da sua variável LOCAL_PATH.

    Observação: você precisa selecionar a versão da biblioteca pré-compilada adequada para a ABI de destino. Para saber mais sobre como garantir a compatibilidade da biblioteca com as ABIs, consulte Selecionar ABIs para bibliotecas pré-compiladas.

  3. Inclua PREBUILT_SHARED_LIBRARY ou PREBUILT_STATIC_LIBRARY, de acordo com a biblioteca que você está usando: compartilhada (.so) ou estática (.a).

Veja um exemplo trivial que assume que a biblioteca pré-compilada libfoo.so reside 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 cópia, sem informações de depuração, em $PROJECT/libs/<abi>. Aqui, $PROJECT é o diretório raiz do seu projeto.

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

Para referenciar a biblioteca pré-compilada de outros módulos, especifique o nome dela como o valor da variável 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 para o 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, você pode declará-lo da seguinte maneira:

    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 presente garante que o sistema de compilação exporte o caminho para o diretório include da biblioteca pré-compilada, adicionando esse caminho ao valor de LOCAL_C_INCLUDES do módulo que depende dele.

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

Depurar bibliotecas pré-compiladas

Recomendamos que você forneça bibliotecas compartilhadas pré-compiladas que contenham símbolos de depuração. O sistema de compilação do NDK sempre remove os símbolos da versão da biblioteca que instala em $PROJECT/libs/<abi>/, mas você pode usar a versão de depuração para depurar com ndk-gdb.

Selecionar ABIs para bibliotecas pré-compiladas

Não deixe de selecionar a versão correta da biblioteca compartilhada pré-compilada para sua ABI de destino. A variável TARGET_ARCH_ABI no arquivo Android.mk pode direcionar o sistema de compilação à versão adequada da biblioteca.

Por exemplo, considere que o projeto contém 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 apropriada 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ê especificou x86 como o valor TARGET_ARCH_ABI, o sistema de compilação usa a versão no diretório x86.