CMake

L'NDK di Android supporta l'utilizzo di CMake per compilare il codice C e C++ per l'applicazione. In questa pagina viene spiegato come utilizzare CMake con NDK tramite ExternalNativeBuild del plug-in Android per Gradle o quando si chiama direttamente CMake.

Il file Toolchain CMake

L'NDK supporta CMake tramite un file Toolchain. I file Toolchain sono file CMake che personalizzano il comportamento della Toolchain per il cross-compilazione. Il file della Toolchain utilizzato per l'NDK si trova nell'NDK all'indirizzo <NDK>/build/cmake/android.toolchain.cmake.

I parametri di build come ABI, minSdkVersion e così via vengono forniti nella riga di comando durante la chiamata di cmake. Per un elenco degli argomenti supportati, consulta la sezione Argomenti della catena di strumenti.

Utilizzo

Gradle

L'utilizzo del file strumentochain CMake è automatico se si utilizza externalNativeBuild. Per ulteriori informazioni, consulta la guida di Android Studio su come aggiungere il codice C e C++ al progetto.

Riga di comando

Quando crei con CMake al di fuori di Gradle, il file Toolchain stesso e i suoi argomenti devono essere passati a CMake. Ecco alcuni esempi:

$ cmake \
    -DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
    -DANDROID_ABI=$ABI \
    -DANDROID_PLATFORM=android-$MINSDKVERSION \
    $OTHER_ARGS

Argomenti di Toolchain

I seguenti argomenti possono essere passati al file Toolchain CMake. Se crei con Gradle, aggiungi argomenti a android.defaultConfig.externalNativeBuild.cmake.arguments come descritto nella documentazione di External NativeBuild. Se crei dalla riga di comando, passa argomenti a CMake con -D. Ad esempio, per forzare armeabi-v7a a creare sempre con il supporto Neon, supera -DANDROID_ARM_NEON=TRUE.

ANDROID_ABI

L'ABI di destinazione. Per informazioni sulle ABI supportate, consulta l'articolo sulle ABI Android.

Gradle

Gradle fornisce questo argomento automaticamente. Non impostare esplicitamente questo argomento nel file build.gradle. Per controllare quali ABI vengono scelte come target da Gradle, utilizza abiFilters come descritto in ABI Android.

Riga di comando

Crea build per un singolo target per build. Per scegliere come target più di un'ABI Android, devi creare una volta per ABI. Ti consigliamo di utilizzare directory di build diverse per ogni ABI, in modo da evitare collisioni tra le build.

Valore Notes
armeabi-v7a
armeabi-v7a with NEON Uguale a -DANDROID_ABI=armeabi-v7a -DANDROID_ARM_NEON=ON.
arm64-v8a
x86
x86_64

ANDROID_ARM_MODE

Specifica se generare istruzioni per le braccia o il pollice per armeabi-v7a. Non ha alcun effetto per altre ABI. Per ulteriori informazioni, consulta la documentazione sulle ABI Android.

Valore Notes
un braccio
pollice Comportamento predefinito.

ANDROID_ARM_NEON

Abilita o disabilita NEON per armeabi-v7a. Non ha effetto per altre ABI. Il valore predefinito è true per il livello API (minSdkVersion o ANDROID_PLATFORM) 23 o successivo, altrimenti false. Per ulteriori informazioni, consulta la documentazione del supporto Neon.

Valore Notes
VERO Predefinita per il livello API 23 o versioni successive.
FALSO Valore predefinito per il livello API 22 o versioni precedenti.

ANDROID_LD

Seleziona il linker da utilizzare. lld è attualmente sperimentale per NDK e può essere attivato con questo argomento.

Valore Notes
lld Attiva lld.
predefinita Utilizza il linker predefinito per l'ABI specificata.

ANDROID_NATIVE_API_LEVEL

Alias per ANDROID_PLATFORM.

ANDROID_PLATFORM

Specifica il livello API minimo supportato dall'applicazione o dalla libreria. Questo valore corrisponde al minSdkVersion dell'applicazione.

Gradle

Quando utilizzi il plug-in Android per Gradle, questo valore viene impostato automaticamente in modo da corrispondere al minSdkVersion dell'applicazione e non deve essere impostato manualmente.

Riga di comando

Quando si chiama direttamente CMake, questo valore viene impostato in modo predefinito sul livello API più basso supportato dall'NDK in uso. Ad esempio, con NDK r20 questo valore viene impostato per impostazione predefinita sul livello API 16.

Per questo parametro sono accettati più formati:

  • android-$API_LEVEL
  • $API_LEVEL
  • android-$API_LETTER

Il formato $API_LETTER consente di specificare android-N senza dover determinare il numero associato alla release. Tieni presente che alcune release hanno ricevuto un aumento dell'API senza un aumento di lettere. Queste API possono essere specificate aggiungendo il suffisso -MR1. Ad esempio, il livello API 25 è android-N-MR1.

ANDROID_STL

Specifica il codice STL da utilizzare per questa applicazione. Per ulteriori informazioni, consulta l'articolo di assistenza per la libreria di C++. Per impostazione predefinita, viene utilizzato il criterio c++_static.

Valore Notes
C++_shared La variante della libreria condivisa di libc++.
C++_statico La variante della libreria statica di libc++.
Nessuna selezione Nessun supporto per la libreria standard C++.
di infotainment Il codice STL del sistema

Informazioni sul comando CMake build

Durante il debug dei problemi di build di CMake è utile conoscere gli argomenti specifici di build utilizzati da Gradle durante il cross-compilazione per Android.

Il plug-in Android per Gradle salva gli argomenti della build utilizzati per l'esecuzione di una build CMake per ogni coppia ABI e tipo di build in build_command.txt. Questi file si trovano nella seguente directory:

<project-root>/<module-root>/.cxx/cmake/<build-type>/<ABI>/

Lo snippet seguente mostra un esempio di argomenti CMake per creare una release di cui è possibile eseguire il debug dell'esempio hello-jni che ha come target l'architettura 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

Utilizzare le librerie predefinite

Se la libreria predefinita da importare è distribuita come AAR, segui la documentazione sulle dipendenze di Studio per importarla e utilizzarla. Se non utilizzi AGP, puoi seguire https://google.github.io/prefab/example-workflow.html, ma probabilmente è molto più semplice eseguire la migrazione ad AGP.

Per le librerie che non sono distribuite come AAR, per istruzioni sull'utilizzo di librerie predefinite con CMake, consulta la documentazione di add_library relativa ai target IMPORTED nel manuale di CMake.

Creazione di codice di terze parti

Esistono diversi modi per creare codice di terze parti nell'ambito del progetto CMake e l'opzione più adatta dipende dalla situazione. Spesso la soluzione migliore è non farlo affatto. Devi invece creare un AAR per la libreria e utilizzarlo nella tua applicazione. Non è necessario pubblicare questo AAR. Può essere interno al progetto Gradle.

Se non è possibile:

  • Fornitore (ovvero copia) il codice sorgente di terze parti nel tuo repository e utilizza add_subdirectory per crearlo. Funziona solo se anche l'altra libreria è stata creata con CMake.
  • Definisci un valore ExternalProject.
  • Crea la libreria separatamente dal tuo progetto e consulta la sezione Utilizzare le librerie predefinite per importarla come predefinita.

Supporto di YASM in CMake

L'NDK fornisce il supporto CMake per la creazione di codice di assemblaggio scritto in YASM per l'esecuzione su architetture x86 e x86-64. YASM è un assemblatore open source per architetture x86 e x86-64 basato sull'assemblatore NASM.

Per creare il codice dell'assemblaggio con CMake, apporta le seguenti modifiche nell'elemento CMakeLists.txt del tuo progetto:

  1. Chiama enable_language con il valore impostato su ASM_NASM.
  2. A seconda che tu stia creando una libreria condivisa o un file binario eseguibile, chiama add_library o add_executable. Negli argomenti, passa un elenco di file di origine costituiti dai file .asm per il programma Assembly in YASM e dai file .c per le librerie C o le funzioni associate.

Lo snippet seguente mostra come configurare CMakeLists.txt per creare un programma YASM come libreria condivisa.

cmake_minimum_required(VERSION 3.6.0)

enable_language(ASM_NASM)

add_library(test-yasm SHARED jni/test-yasm.c jni/print_hello.asm)

Per un esempio di come creare un programma YASM come eseguibile, vedi yasm test nel repository Git NDK.

Segnalare problemi

Se riscontri problemi con NDK o con il relativo file Toolchain CMake, segnalali tramite l'Issue Tracker android-ndk/ndk su GitHub. In caso di problemi con il plug-in Gradle o Android Gradle, segnala un bug di Studio.