CMake

O Android NDK é compatível com o uso do CMake (link em inglês) para criar o código C e C++ para seu 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 por meio de 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_NATIVE_API_LEVEL=$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 aoandroid.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 saber mais, consulte a documentação do 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 compilação do CMake

Ao depurar problemas de compilação do CMake, é útil conhecer os argumentos de compilação 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 compilação para o cmake_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 da amostra hello-jni (link em inglês) destinada à arquitetura armeabi-v7a.

Executable : ${HOME}/Android/Sdk/cmake/3.6.3155560/bin/cmake
arguments :
-H${HOME}/Dev/github-projects/googlesamples/android-ndk/hello-jni/app/src/main/cpp
-B${HOME}/Dev/github-projects/googlesamples/android-ndk/hello-jni/app/.cxx/cmake/arm7Debug/armeabi-v7a
-GAndroid Gradle - Ninja
-DANDROID_ABI=armeabi-v7a
-DANDROID_NDK=${HOME}/Android/Sdk/ndk-bundle
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${HOME}/Dev/github-projects/googlesamples/android-ndk/hello-jni/app/build/intermediates/cmake/arm7/debug/obj/armeabi-v7a
-DCMAKE_BUILD_TYPE=Debug
-DCMAKE_MAKE_PROGRAM=${HOME}/Android/Sdk/cmake/3.6.3155560/bin/ninja
-DCMAKE_TOOLCHAIN_FILE=${HOME}/Android/Sdk/ndk-bundle/build/cmake/android.toolchain.cmake
-DANDROID_NATIVE_API_LEVEL=23
-DANDROID_TOOLCHAIN=clang
jvmArgs :

Como usar bibliotecas pré-compiladas

Para ver instruções sobre como usar bibliotecas pré-compiladas com o CMake, consulte a documentação de add_library sobre destinos IMPORTED no manual do CMake (link em inglês).

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:

  1. Chame enable_language (link em inglês) com o valor definido como ASM_NASM.
  2. Chame add_library ou add_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.

Informar problemas

Caso tenha problemas com o NDK ou o arquivo do conjunto de ferramentas do CMake, informe-os por meio do Issue Tracker android-ndk/ndk no GitHub (link em inglês).