CMake

Das Android-NDK unterstützt die Verwendung von CMake, um C- und C++-Code für Ihre Anwendung zu kompilieren. Auf dieser Seite wird erläutert, wie Sie CMake mit dem NDK über ExternalNativeBuild des Android-Gradle-Plug-ins verwenden oder wenn Sie CMake direkt aufrufen.

Die CMake-Toolchain-Datei

Der NDK unterstützt CMake über eine Toolchain-Datei. Toolchain-Dateien sind CMake-Dateien, mit denen das Verhalten der Toolchain für die Cross-Kompilierung angepasst wird. Die für den NDK verwendete Toolchain-Datei befindet sich im NDK unter <NDK>/build/cmake/android.toolchain.cmake.

Build-Parameter wie ABI, minSdkVersion usw. werden beim Aufrufen von cmake in der Befehlszeile angegeben. Eine Liste der unterstützten Argumente finden Sie im Abschnitt Toolchain-Argumente.

Nutzung

Gradle

Bei Verwendung von externalNativeBuild wird die CMake-Toolchain-Datei automatisch verwendet. Weitere Informationen finden Sie in der Android Studio-Anleitung zum Hinzufügen von C- und C++-Code in Ihr Projekt.

Befehlszeile

Wenn Sie mit CMake außerhalb von Gradle arbeiten, müssen die Toolchain-Datei selbst und ihre Argumente an CMake übergeben werden. Beispiele:

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

Toolchain-Argumente

Die folgenden Argumente können an die CMake-Toolchain-Datei übergeben werden. Wenn Sie Builds mit Gradle erstellen, fügen Sie android.defaultConfig.externalNativeBuild.cmake.arguments Argumente hinzu, wie in der ExternalNativeBuild-Dokumentation beschrieben. Wenn Sie die Erstellung über die Befehlszeile ausführen, übergeben Sie Argumente mit -D an CMake. Wenn Sie beispielsweise erzwingen möchten, dass armeabi-v7a nicht mit Neon unterstützt wird, übergeben Sie -DANDROID_ARM_NEON=FALSE.

ANDROID_ABI

Das Ziel-ABIs. Informationen zu unterstützten ABIs finden Sie unter Android-ABIs.

Gradle

Gradle stellt dieses Argument automatisch bereit. Legen Sie dieses Argument in der Datei build.gradle nicht explizit fest. Wenn Sie festlegen möchten, auf welche ABIs Gradle ausgerichtet ist, verwenden Sie abiFilters, wie unter Android-ABIs beschrieben.

Befehlszeile

CMake-Builds für ein einzelnes Ziel pro Build. Wenn du ein Targeting auf mehr als ein Android-ABI vornehmen möchtest, musst du einmal pro ABI erstellen. Es wird empfohlen, für jedes ABI unterschiedliche Build-Verzeichnisse zu verwenden, um Kollisionen zwischen Builds zu vermeiden.

Antwort Hinweise
armeabi-v7a
armeabi-v7a with NEON Wie bei armeabi-v7a.
arm64-v8a
x86
x86_64

ANDROID_ARM_MODE

Gibt an, ob für armeabi-v7a Verzweigungs- oder Daumenanweisungen erstellt werden sollen. Hat keine Auswirkungen auf andere ABIs. Weitere Informationen findest du in der Dokumentation zu Android-ABIs.

Antwort Hinweise
Arm
Daumen Standardverhalten.

ANDROID_ARM_NEON

Aktiviert oder deaktiviert NEON für armeabi-v7a. Hat keine Auswirkungen auf andere ABIs. Die Standardeinstellung ist „true“ für API-Level (minSdkVersion oder ANDROID_PLATFORM) 23 oder höher, andernfalls „false“. Weitere Informationen finden Sie in der Dokumentation zum Neon-Support.

Antwort Hinweise
RICHTIG Standardeinstellung für API-Level 23 oder höher.
FALSCH Standardeinstellung für API-Level 22 oder älter.

ANDROID_LD

Wählt die Verknüpfung aus. lld wird derzeit für den NDK getestet und kann mit diesem Argument aktiviert werden.

Antwort Hinweise
LDL Aktiviert lld.
Standard Verwenden Sie die Standardverknüpfung für das angegebene ABI.

ANDROID_NATIVE_API_LEVEL

Alias für ANDROID_PLATFORM.

ANDROID_PLATFORM

Gibt das von der Anwendung oder Bibliothek unterstützte minimale API-Level an. Dieser Wert entspricht dem minSdkVersion der Anwendung.

Gradle

Wenn Sie das Android-Gradle-Plug-in verwenden, wird dieser Wert automatisch auf die minSdkVersion der App festgelegt und sollte nicht manuell festgelegt werden.

Befehlszeile

Wenn CMake direkt aufgerufen wird, wird für diesen Wert standardmäßig die niedrigste API-Ebene verwendet, die von der verwendeten NDK unterstützt wird. Bei NDK r20 ist dieser Wert beispielsweise standardmäßig das API-Level 16.

Für diesen Parameter sind mehrere Formate zulässig:

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

Mit dem Format $API_LETTER kannst du android-N angeben, ohne die mit diesem Release verknüpfte Nummer ermitteln zu müssen. Beachten Sie, dass einige Releases eine API-Erhöhung ohne Buchstabenerhöhung erhalten haben. Diese APIs können durch Anfügen des Suffix -MR1 angegeben werden. API-Level 25 ist beispielsweise android-N-MR1.

ANDROID_STL

Gibt an, welcher STL für diese Anwendung verwendet werden soll. Weitere Informationen finden Sie unter Unterstützung von C++-Bibliotheken. Standardmäßig wird c++_static verwendet.

Antwort Hinweise
c++_geteilt Die gemeinsam genutzte Bibliotheksvariante von libc++.
c++_statisch Die statische Bibliotheksvariante von libc++.
Keine Die C++-Standardbibliothek wird nicht unterstützt.
Infotainmentsystem System-STL

Informationen zum Befehl „CMake erstellen“

Beim Beheben von CMake-Build-Problemen ist es hilfreich, die spezifischen Build-Argumente zu kennen, die Gradle bei der Cross-Kompilierung für Android verwendet.

Das Android Gradle-Plug-in speichert die Build-Argumente, mit denen ein CMake-Build für jedes ABI- und Build-Typ-Paar ausgeführt wird, im build_command.txt. Diese Dateien befinden sich im folgenden Verzeichnis:

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

Das folgende Snippet zeigt ein Beispiel für CMake-Argumente zum Erstellen eines debugfähigen Release des Beispiels hello-jni, das auf die armeabi-v7a-Architektur ausgerichtet ist.

                    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

Vordefinierte Bibliotheken verwenden

Wenn die vordefinierte Bibliothek, die Sie importieren müssen, als AAE bereitgestellt wird, folgen Sie den Abhängigkeitsdokumenten von Studio, um diese zu importieren und zu verwenden. Wenn Sie AGP nicht verwenden, können Sie dem Beispiel unter https://google.github.io/prefab/example-workflow.html folgen. Es ist jedoch wahrscheinlich einfacher, zu AGP zu migrieren.

Anleitungen zur Verwendung vordefinierter Bibliotheken mit CMake finden Sie in der add_library-Dokumentation zu IMPORTED-Zielen im CMake-Handbuch.

Drittanbietercode erstellen

Es gibt verschiedene Möglichkeiten, im Rahmen Ihres CMake-Projekts Drittanbietercode zu erstellen. Welche Option am besten funktioniert, hängt von Ihrer Situation ab. Oft ist es die beste Option, das überhaupt nicht zu tun. Erstellen Sie stattdessen ein AAE für die Bibliothek und nutzen Sie dieses in Ihrer Anwendung. Sie müssen solche automatisch angewendeten Empfehlungen nicht unbedingt veröffentlichen. Sie kann intern zu Ihrem Gradle-Projekt gehören.

Falls dies nicht möglich ist, gehen Sie so vor:

  • Der Anbieter (kopiert) die Drittanbieterquelle in Ihr Repository und erstellt sie mit add_subdirectory. Dies funktioniert nur, wenn die andere Bibliothek ebenfalls mit CMake erstellt wurde.
  • Definieren Sie ein ExternalProject.
  • Erstellen Sie die Bibliothek getrennt von Ihrem Projekt und folgen Sie der Anleitung unter Vordefinierte Bibliotheken verwenden, um sie als vordefinierte zu importieren.

YASM-Unterstützung in CMake

Das NDK bietet CMake-Unterstützung für das Erstellen von Assembly-Code, der in YASM geschrieben wurde und auf x86- und x86-64-Architekturen ausgeführt wird. YASM ist ein Open-Source-Assembler für x86- und x86-64-Architekturen, die auf dem NASM-Assembr basieren.

Wenn Sie Assembly-Code mit CMake erstellen möchten, nehmen Sie die folgenden Änderungen an der Datei CMakeLists.txt Ihres Projekts vor:

  1. Rufen Sie enable_language mit dem Wert ASM_NASM auf.
  2. Je nachdem, ob Sie eine gemeinsam genutzte Bibliothek oder eine ausführbare Binärdatei erstellen, rufen Sie add_library oder add_executable auf. Übergeben Sie in den Argumenten eine Liste der Quelldateien, die aus den .asm-Dateien für das Assembly-Programm in YASM und den .c-Dateien für die zugehörigen C-Bibliotheken oder -Funktionen besteht.

Das folgende Snippet zeigt, wie Sie CMakeLists.txt konfigurieren können, um ein YASM-Programm als gemeinsam genutzte Bibliothek zu erstellen.

cmake_minimum_required(VERSION 3.6.0)

enable_language(ASM_NASM)

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

Ein Beispiel zum Erstellen eines YASM-Programms als ausführbare Datei finden Sie im yasm-Test im NDK-Git-Repository.

Probleme melden

Wenn Probleme mit dem NDK oder der zugehörigen CMake-Toolchain-Datei auftreten, melden Sie diese über die android-ndk/ndk-Problemverfolgung auf GitHub. Bei Problemen mit Gradle oder Android Gradle-Plug-ins können Sie stattdessen einen Studio-Fehler melden.