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 die ExternalNativeBuild des Android-Gradle-Plug-ins CMake direkt aufrufen.

Die CMake-Toolchain-Datei

Das NDK unterstützt CMake über eine Toolchain-Datei. Toolchain-Dateien sind CMake-Dateien. die das Verhalten der Toolchain für die Cross-Kompilierung anpassen. Die Toolchain für das NDK verwendete Datei befindet sich im NDK unter <NDK>/build/cmake/android.toolchain.cmake

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

Das „neue“ Toolchain-Datei

Frühere NDKs haben mit einer neuen Implementierung der Toolchain-Datei experimentiert, die Verhaltensunterschiede zwischen der Verwendung der Toolchain-Datei des NDK und mit der integrierten CMake-Unterstützung. Dies erforderte letztlich einen erheblichen die noch nicht abgeschlossen ist, aber das Verhalten nicht verbessert hat, Deshalb verfolgen wir dieses Ziel nicht mehr.

Das „neue“ Toolchain-Datei weist im Vergleich zur Legacy-Datei auf das Verhalten zurück. Toolchain-Datei. Das Standardverhalten entspricht dem empfohlenen Workflow. Wenn Sie mit -DANDROID_USE_LEGACY_TOOLCHAIN_FILE=OFF empfehlen wir, dieses Flag zu entfernen aus Ihrem Build. Die neue Toolchain-Datei hat nie Parität mit der Legacy-Datei erreicht Toolchain-Datei, sodass es wahrscheinlich zu einem Rückgang des Verhaltens kommt.

Obwohl wir von der Verwendung der neuen Toolchain-Datei abraten, gibt es derzeit keine aus dem NDK zu entfernen. Ansonsten würden Builds beschädigt werden, Unterschiede im Verhalten der neuen und Legacy-Toolchain-Dateien die Option umbenannt, um deutlich zu machen, dass "Legacy" ist eigentlich würden die Nutzer dieser Option ebenfalls unbrauchbar sein. Wenn Sie die Methode Neue Toolchain-Datei, die Sie nicht migrieren müssen, aber alle Fehler gemeldet haben neuen Verhalten der Toolchain-Datei wahrscheinlich nicht korrigiert. die Sie migrieren müssen.

Nutzung

Logo: Gradle

Die CMake-Toolchain-Datei wird automatisch verwendet, wenn Sie externalNativeBuild Weitere Informationen finden Sie unter C++- und C++-Code zu Ihrem weitere Informationen.

Befehlszeile

Beim Erstellen mit CMake außerhalb von Gradle werden die Toolchain-Datei selbst und müssen ihre Argumente an CMake übergeben werden. Beispiel:

$ 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 Toolchain-Datei von CMake übergeben. Wenn Sie fügen Sie mit Gradle Argumente android.defaultConfig.externalNativeBuild.cmake.arguments gemäß den ExternalNativeBuild-Dokumentation Beim Erstellen über die Befehlszeile übergeben Sie Argumente an CMake mit -D. Wenn Sie beispielsweise erzwingen möchten, dass Armeabi-v7a nicht mit Neon erstellt wird erhalten Sie über -DANDROID_ARM_NEON=FALSE.

ANDROID_ABI

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

Logo: Gradle

Gradle stellt dieses Argument automatisch bereit. Nicht explizit festlegen Argument in der Datei build.gradle. Um zu steuern, worauf ABIs Gradle ausgerichtet ist, Verwende abiFilters, wie in Android-ABIs beschrieben.

Befehlszeile

Erstellen Sie Builds für ein einzelnes Ziel pro Build. Ausrichtung auf mehrere Android-Geräte ABI, du musst einmal pro ABI erstellen. Es wird empfohlen, einen anderen Build zu verwenden Verzeichnisse für jedes ABI, um Konflikte zwischen Builds zu vermeiden.

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

ANDROID_ARM_MODE

Gibt an, ob Arm- oder Daumenanweisungen für armeabi-v7a generiert werden sollen. Enthält keine für andere ABIs. Weitere Informationen finden Sie in den Android-ABIs. Dokumentation.

Wert Hinweise
Arm
Daumen Standardverhalten.

ANDROID_NATIVE_API_LEVEL

Alias für ANDROID_PLATFORM.

ANDROID_PLATFORM

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

Logo: Gradle

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

Befehlszeile

Beim direkten Aufrufen von CMake wird standardmäßig die niedrigste API-Ebene verwendet. die vom verwendeten NDK unterstützt werden. Mit NDK r20 wird dieser Wert beispielsweise auf 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 können Sie android-N angeben, ohne die mit dieser Veröffentlichung verknüpfte Nummer ermitteln. Beachten Sie, dass einige Releases hat eine API-Erhöhung ohne Brieferhöhung erhalten. Diese APIs können angegeben werden indem Sie das Suffix -MR1 anhängen. API-Level 25 ist beispielsweise android-N-MR1.

ANDROID_STL

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

Wert Hinweise
C++-geteilt Die Variante der gemeinsam genutzten Bibliothek von libc++.
C++_statisch Die statische Bibliotheksvariante von libc++.
Keine Keine Unterstützung der C++-Standardbibliothek.
Infotainmentsystem Die System-STL

Compiler-Flags verwalten

Wenn Sie für Ihren Build bestimmte Flags an den Compiler oder Verlinker übergeben müssen, finden Sie in der CMake-Dokumentation zu set_target_compile_options und den verwandte Optionen. Die Schaltfläche „Weitere Informationen“ unten auf dieser Seite enthält einige hilfreiche Anhaltspunkte.

Im Allgemeinen empfiehlt es sich, Compiler-Flags am engsten verfügbaren Umfang. Flags, die Sie auf alle Ihre Ziele anwenden möchten (z. B. -Werror) sind umständlich, pro Modul aber nur selten zu wiederholen weltweit angewendet (CMAKE_CXX_FLAGS), da dies unerwünschte Auswirkungen auf in Ihrem Projekt nutzen. In solchen Fällen können die Flags auf Verzeichnisebene (add_compile_options) angewendet.

Für eine begrenzte Teilmenge von Compiler-Flags können diese auch in Ihrer build.gradle-Datei festgelegt werden -Datei mit cppFlags oder ähnlichen Eigenschaften. Das sollten Sie nicht tun. Flaggen von Gradle an CMake übergeben, haben in einigen Fälle überschreiben die Flags, die implizit von der Implementierung übergeben werden. die für die Entwicklung von Android-Code erforderlich sind. CMake-Verhalten immer vorziehen direkt in CMake. Wenn Sie Compiler-Flags gemäß AGP buildType steuern müssen, Siehe Mit AGP-Build-Typen in CMake arbeiten.

Mit AGP-Build-Typen in CMake arbeiten

Wenn Sie das CMake-Verhalten an eine benutzerdefinierte Gradle-buildType anpassen möchten, verwenden Sie diese Build-Typ, um ein zusätzliches CMake-Flag (kein Compiler-Flag) zu übergeben, das Ihr CMake-Build-Skripts können Daten lesen. Wenn Sie beispielsweise „free“ und „Premium“ Build-Varianten, die von Ihrer build.gradle.kts gesteuert werden, und Sie müssen diese Daten an CMake:

android {
    buildTypes {
        free {
            externalNativeBuild {
                cmake {
                    arguments.add("-DPRODUCT_VARIANT_PREMIUM=OFF")
                }
            }
        }
        premium {
            externalNativeBuild {
                cmake {
                    arguments.add("-DPRODUCT_VARIANT_PREMIUM=ON")
                }
            }
        }
    }
}

Gehen Sie dann in der Datei CMakeLists.txt so vor:

if (DPRODUCT_VARIANT_PREMIUM)
  # Do stuff for the premium build.
else()
  # Do stuff for the free build.
endif()

Sie können den Namen der Variablen selbst bestimmen. Stellen Sie jedoch sicher, dass Sie keine Elemente mit ANDROID_, APP_ oder CMAKE_, um einen Konflikt oder eine Verwechslung mit vorhandene Flags.

Ein Beispiel finden Sie im Sanitizers NDK-Beispiel.

CMake-Build-Befehl verstehen

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

Das Android-Gradle-Plug-in speichert die Build-Argumente, die zum Ausführen eines CMake-Build für jedes ABI und jeden Build-Typ erstellen mit build_command.txt koppeln. Diese Dateien befinden sich hier: Verzeichnis:

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

Das folgende Snippet zeigt ein Beispiel für die CMake-Argumente zum Erstellen einer Debug-fähige Version des hello-jni-Beispiels mit Ausrichtung auf armeabi-v7a Architektur.

                    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 zu importierende vordefinierte Bibliothek als AAE bereitgestellt wird, folgen Sie Abhängigkeitsdokumente in Studio um sie zu importieren und zu verwenden. Wenn Sie nicht AGP verwenden, können Sie https://google.github.io/prefab/example-workflow.html, doch wahrscheinlich zu AGP zu migrieren.

Für Bibliotheken, die nicht als AAE verteilt werden, Anleitungen zur Verwendung Bibliotheken mit CMake verwenden, finden Sie in der add_library-Dokumentation zu IMPORTED im CMake-Handbuch.

Drittanbietercode erstellen

Es gibt einige Möglichkeiten, Drittanbietercode im Rahmen Ihres CMake-Codes zu erstellen. und welche Option am besten funktioniert, hängt von Ihrer Situation ab. Das Beste ist es oft, dies gar nicht zu tun. Erstellen Sie stattdessen automatisch angewendete Empfehlungen für das und in Ihrer Anwendung verwenden. Sie müssen nicht unbedingt Automatisch angewendete Empfehlungen veröffentlichen. Sie kann innerhalb Ihres Gradle-Projekts verwendet werden.

Sollte dies keine Option sein, gehen Sie so vor:

  • Drittanbieterquelle in Ihr Repository übertragen (d.h. kopieren) und verwenden add_subdirectory dafür verwendet. Dies funktioniert nur, wenn die andere Bibliothek ebenfalls mit CMake erstellt.
  • Definieren Sie ein ExternalProject.
  • Erstellen Sie die Bibliothek getrennt von Ihrem Projekt und folgen Sie Verwenden Sie vordefinierte Bibliotheken, um sie als vordefinierten Import zu importieren.

YASM-Unterstützung in CMake

Das NDK bietet CMake-Unterstützung für die Erstellung von Assembly-Code, der in YASM zur Ausführung auf x86 und x86-64 Architekturen. YASM ist ein Open-Source-Assembler für x86 und x86-64 Architekturen, die auf dem NASM-Assembler basieren.

Um Assembly-Code mit CMake zu erstellen, nehmen Sie die folgenden Änderungen im CMakeLists.txt:

  1. Rufen Sie enable_language mit dem Wert ASM_NASM auf.
  2. Je nachdem, ob Sie eine gemeinsam genutzte Bibliothek oder eine ausführbare add_library oder add_executable aufrufen. In Die Argumente übergeben eine Liste von Quelldateien, die aus den .asm-Dateien besteht. für das Assembly-Programm in YASM und die .c-Dateien für das zugehörige C Bibliotheken oder Funktionen.

Das folgende Snippet zeigt, wie du dein CMakeLists.txt so konfigurieren kannst, dass es ein YASM-Programm als gemeinsam genutzte Bibliothek 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 für die Erstellung eines YASM-Programms als ausführbare Datei finden Sie in der yasm-Bibliothek test im NDK-Git-Repository.

Probleme melden

Sollten Probleme mit dem NDK oder der zugehörigen CMake-Toolchain-Datei auftreten, melden Sie diese bitte. über die Problemverfolgung android-ndk/ndk auf GitHub. Für Gradle oder Probleme mit dem Android-Gradle-Plug-in: Melden Sie stattdessen einen Studio-Fehler.