O Android NDK oferece suporte ao uso do CMake (link em inglês) para
criar o código C e C++ do app. Esta página discute como usar o
CMake com o NDK pelo ExternalNativeBuild
do Plug-in do Android para Gradle ou ao
invocar o CMake diretamente.
O arquivo do conjunto de ferramentas do CMake
O NDK é compatível com o CMake graças a um arquivo do conjunto de ferramentas (link em inglês). Esses arquivos são do CMake e personalizam o comportamento do conjunto de ferramentas para compilação cruzada. O arquivo do conjunto de ferramentas usado para o NDK está localizado no NDK em <NDK>/build/cmake/android.toolchain.cmake
.
Parâmetros de compilação como ABI, minSdkVersion
etc. são fornecidos na linha de
comando ao invocar cmake
. Para ver uma lista de argumentos compatíveis, consulte a
seção Argumentos do conjunto de ferramentas.
Uso
Gradle
O uso do arquivo do conjunto de ferramentas do CMake é automático ao usar
externalNativeBuild
. Consulte o guia Adicionar código C e C++ ao seu
projeto do Android Studio para saber mais.
Linha de comando
Ao criar com o CMake fora do Gradle, o próprio arquivo do conjunto de ferramentas e os respectivos argumentos precisam ser transmitidos para o CMake. Exemplo:
$ cmake \
-DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=$ABI \
-DANDROID_PLATFORM=android-$MINSDKVERSION \
$OTHER_ARGS
Argumentos do conjunto de ferramentas
Os argumentos a seguir podem ser transmitidos para o arquivo do conjunto de ferramentas do CMake. Se estiver criando com o Gradle, adicione argumentos ao android.defaultConfig.externalNativeBuild.cmake.arguments
, conforme descrito nos documentos do ExternalNativeBuild (link em inglês). Se estiver criando a partir da linha de comando, transmita argumentos para o CMake com -D
. Por exemplo, para forçar o armeabi-v7a a sempre criar com a compatibilidade com Neon, transmita -DANDROID_ARM_NEON=TRUE
.
ANDROID_ABI
ABI desejada. Para ver informações sobre as ABIs compatíveis, consulte ABIs do Android.
Gradle
O Gradle fornece esse argumento automaticamente. Não defina esse argumento explicitamente no seu arquivo build.gradle
. Para controlar quais ABIs o Gradle visa, use abiFilters
conforme descrito em ABIs do Android.
Linha de comando
O CMake cria para um único destino por build. Para segmentar mais de uma ABI do Android, é necessário criar uma vez por ABI. É recomendável usar diretórios de compilação diferentes para cada ABI de modo a evitar colisões entre builds.
Valor | Observações |
---|---|
armeabi-v7a |
|
armeabi-v7a with NEON |
Igual a -DANDROID_ABI=armeabi-v7a -DANDROID_ARM_NEON=ON . |
arm64-v8a |
|
x86 |
|
x86_64 |
ANDROID_ARM_MODE
Especifica se serão geradas instruções de arm ou thumb para armeabi-v7a. Não tem efeito para outras ABIs. Para saber mais, consulte a documentação ABIs do Android.
Valor | Observações |
---|---|
arm | |
thumb | Comportamento padrão. |
ANDROID_ARM_NEON
Ativa ou desativa NEON para armeabi-v7a. Não tem efeito para outras ABIs. O padrão
é verdadeiro para a API de nível 23 ou mais recente (minSdkVersion
ou ANDROID_PLATFORM
). Caso contrário, o valor
será falso. Para mais informações, consulte a documentação de suporte da Neon.
Valor | Observações |
---|---|
TRUE | Padrão para a API de nível 23 ou mais recente. |
FALSE | Padrão para a API de nível 22 ou anterior. |
ANDROID_LD
Seleciona qual vinculador usar. No momento, lld (link em inglês) é experimental para o NDK e pode ser ativado com esse argumento.
Valor | Observações |
---|---|
lld | Ativa lld. |
padrão | Use o vinculador padrão para a ABI especificada. |
ANDROID_NATIVE_API_LEVEL
Alias para ANDROID_PLATFORM.
ANDROID_PLATFORM
Especifica o nível mínimo da API compatível com o app ou a biblioteca. Esse valor corresponde à minSdkVersion
do app.
Gradle
Ao usar o Plug-in do Android para Gradle, esse valor é definido automaticamente para corresponder à minSdkVersion
do app e não pode ser definido manualmente.
Linha de comando
Ao invocar o CMake diretamente, esse valor assume como padrão a API de nível mais baixo compatível com o NDK em uso. Por exemplo, para o NDK r20, esse valor assume como padrão a API de nível 16.
Vários formatos são aceitos para esse parâmetro:
android-$API_LEVEL
$API_LEVEL
android-$API_LETTER
O formato $API_LETTER
permite que você especifique android-N
sem a necessidade de determinar o número associado a essa versão. Algumas versões receberam um aumento de API sem aumento de letras. Essas APIs podem ser especificadas anexando o sufixo -MR1
. Por exemplo, a API de nível 25 é android-N-MR1
.
ANDROID_STL
Especifica o STL que será usado para esse app. Para saber mais, consulte Compatibilidade
com a biblioteca C++. Por padrão, c++_static
será usado.
Valor | Observações |
---|---|
c++_shared | A variante da biblioteca compartilhada de libc++. |
c++_static | A variante da biblioteca estática de libc++. |
none | Não há compatibilidade padrão com a biblioteca C++. |
system | A STL do sistema |
Entender o comando de build do CMake
Ao depurar problemas de build do CMake, é útil conhecer os argumentos de build específicos que o Gradle usa ao fazer compilação cruzada para o Android.
O Plug-in do Android para Gradle salva os argumentos de compilação usados para executar um
build do CMake para cada par de ABI e tipo de build para o build_command.txt
. Esses arquivos são encontrados no seguinte diretório:
<project-root>/<module-root>/.cxx/cmake/<build-type>/<ABI>/
O snippet a seguir mostra um exemplo dos argumentos do CMake para criar uma
versão depurável do exemplo hello-jni
(link em inglês) destinada à arquitetura
armeabi-v7a
.
Executable : ${HOME}/Android/Sdk/cmake/3.10.2.4988404/bin/cmake
arguments :
-H${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/src/main/cpp
-DCMAKE_FIND_ROOT_PATH=${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/.cxx/cmake/universalDebug/prefab/armeabi-v7a/prefab
-DCMAKE_BUILD_TYPE=Debug
-DCMAKE_TOOLCHAIN_FILE=${HOME}/Android/Sdk/ndk/22.1.7171670/build/cmake/android.toolchain.cmake
-DANDROID_ABI=armeabi-v7a
-DANDROID_NDK=${HOME}/Android/Sdk/ndk/22.1.7171670
-DANDROID_PLATFORM=android-23
-DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a
-DCMAKE_ANDROID_NDK=${HOME}/Android/Sdk/ndk/22.1.7171670
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/build/intermediates/cmake/universalDebug/obj/armeabi-v7a
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/build/intermediates/cmake/universalDebug/obj/armeabi-v7a
-DCMAKE_MAKE_PROGRAM=${HOME}/Android/Sdk/cmake/3.10.2.4988404/bin/ninja
-DCMAKE_SYSTEM_NAME=Android
-DCMAKE_SYSTEM_VERSION=23
-B${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/.cxx/cmake/universalDebug/armeabi-v7a
-GNinja
jvmArgs :
Build command args: []
Version: 1
Usar bibliotecas pré-compiladas
Se a biblioteca pré-compilada que você precisa importar for distribuída como um AAR, siga os documentos de dependência do Studio para importar e usar essas bibliotecas. Se você não estiver usando o AGP, você pode seguir as etapas em https://google.github.io/prefab/example-lifecycle.html (link em inglês), mas é muito mais fácil migrar para o AGP.
No caso de bibliotecas que não são distribuídas como um AAR, para ver instruções sobre como usar bibliotecas
pré-compiladas com o CMake, consulte a documentação add_library
sobre destinos
IMPORTED
no manual do CMake (link em inglês).
Criar com código de terceiros
Há várias maneiras de usar código de terceiros como parte do seu projeto CMake, e a opção que funciona melhor depende da sua situação. Em geral, a melhor opção é não fazer isso. Em vez disso, crie um AAR para a biblioteca e consuma-o no aplicativo. Não é necessário publicar esse AAR. Ele pode ser interno ao seu projeto do Gradle.
Se não for possível, faça o seguinte:
- Forneça (ou seja, copie) a fonte de terceiros no seu repositório e use add_subdirectory para criá-lo. Isso só funcionará se a outra biblioteca também for criada com o CMake.
- Defina um ExternalProject.
- Crie a biblioteca separada do projeto e siga as instruções da seção Usar bibliotecas pré-compiladas para que ela seja importada como pré-compilada.
Compatibilidade com YASM no CMake
O NDK oferece compatibilidade com o CMake para criação do código Assembly escrito em YASM (link em inglês) para execução em arquiteturas x86 e x86-64. O YASM é um assembler de código aberto para arquiteturas x86 e x86-64, baseado no assembler NASM.
Para criar o código Assembly com o CMake, faça as seguintes mudanças no CMakeLists.txt
do projeto:
- Chame
enable_language
(link em inglês) com o valor definido comoASM_NASM
. - Chame
add_library
ouadd_executable
, dependendo se você está criando uma biblioteca compartilhada ou um binário executável. Nos argumentos, transmita uma lista de arquivos de origem composta pelos arquivos.asm
para o programa Assembly no YASM e arquivos.c
para as funções ou bibliotecas C associadas.
O snippet a seguir mostra como configurar CMakeLists.txt
para
criar um programa YASM como uma biblioteca compartilhada.
cmake_minimum_required(VERSION 3.6.0)
enable_language(ASM_NASM)
add_library(test-yasm SHARED jni/test-yasm.c jni/print_hello.asm)
Para ver um exemplo de como criar um programa YASM como executável, consulte o teste yasm (link em inglês) no repositório git do NDK.
Denunciar problemas
Caso tenha problemas com o NDK ou o arquivo do conjunto de ferramentas do CMake, nos informe pelo Issue Tracker android-ndk/ndk no GitHub (link em inglês). Para problemas com o Gradle ou com o Plug-in do Android para Gradle, informe um bug do Studio.