Marka

Pakiet Android NDK obsługuje użycie CMake do kompilowania kodu C i C++ aplikacji. Na tej stronie opisujemy, jak używać CMake z pakietem NDK za pomocą ExternalNativeBuild wtyczki Androida do obsługi Gradle lub bezpośrednio wywołując CMake.

Plik łańcucha narzędzi CMake

NDK obsługuje CMake za pomocą pliku łańcucha narzędzi. Pliki łańcucha narzędzi to pliki CMake, które dostosowują zachowanie łańcucha narzędzi na potrzeby kompilacji krzyżowej. Plik łańcucha narzędzi używany w pakiecie NDK znajduje się w pakiecie NDK pod adresem <NDK>/build/cmake/android.toolchain.cmake.

Parametry kompilacji, takie jak ABI, minSdkVersion itp., są podawane w wierszu poleceń podczas wywoływania cmake. Listę obsługiwanych argumentów znajdziesz w sekcji Argumenty łańcucha narzędzi narzędzi.

Wykorzystanie

Gradle

Podczas korzystania z externalNativeBuild korzystanie z pliku łańcucha narzędzi CMake jest automatyczne. Więcej informacji znajdziesz w przewodniku Dodawanie kodu C i C++ do projektu w Android Studio.

Wiersz poleceń

Gdy tworzysz kompilację za pomocą CMake poza Gradle, sam plik łańcucha narzędzi i jego argumenty muszą być przekazywane do CMake. Na przykład:

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

Argumenty łańcucha narzędzi

Poniższe argumenty można przekazywać do pliku łańcucha narzędzi CMake. Jeśli kompilujesz za pomocą Gradle, dodaj argumenty do android.defaultConfig.externalNativeBuild.cmake.arguments zgodnie z opisem w dokumentacji ExternalNativeBuild. Jeśli tworzysz kompilację z poziomu wiersza poleceń, przekaż argumenty do CMake w -D. Jeśli na przykład chcesz, żeby armeabi-v7a nie korzystała z obsługi neonów, przekaż -DANDROID_ARM_NEON=FALSE.

ANDROID_ABI

Docelowy interfejs ABI. Informacje o obsługiwanych interfejsach ABI znajdziesz w artykule na temat interfejsów ABI Androida.

Gradle

Gradle udostępnia ten argument automatycznie. Nie ustawiaj tego argumentu bezpośrednio w pliku build.gradle. Aby określić, jakie interfejsy ABI są docelowe Gradle, użyj abiFilters w sposób opisany w artykule Interfejsy ABI Androida.

Wiersz poleceń

Kompilacje CMake dla jednego miejsca docelowego na kompilację. Aby kierować reklamy na więcej niż 1 interfejs ABI na Androida, musisz utworzyć jedną kompilację na każdy z nich. Zaleca się używanie różnych katalogów kompilacji dla każdego interfejsu ABI, aby uniknąć kolizji między kompilacjami.

Wartość Uwagi
armeabi-v7a
armeabi-v7a with NEON Taka sama funkcja jak w przypadku armeabi-v7a.
arm64-v8a
x86
x86_64

ANDROID_ARM_MODE

Określa, czy w przypadku armeabi-v7a mają być generowane instrukcje użycia ręki czy kciuka. nie ma wpływu na inne interfejsy ABI. Więcej informacji znajdziesz w dokumentacji interfejsów ABI Androida.

Wartość Uwagi
włączyć (wykrywanie)
kciuk Domyślne zachowanie.

ANDROID_ARM_NEON

Włącza lub wyłącza tryb NEON dla armeabi-v7a. Nie ma wpływu na inne interfejsy ABI. Wartość domyślna to true w przypadku interfejsu API na poziomie 23 (minSdkVersion lub ANDROID_PLATFORM) lub nowszym. W przeciwnym razie ma wartość false (fałsz). Więcej informacji znajdziesz w dokumentacji pomocy firmy Neon.

Wartość Uwagi
PRAWDA Wartość domyślna dla interfejsu API na poziomie 23 lub nowszym.
FAŁSZ Domyślnie dla interfejsu API na poziomie 22 lub wyższym.

ANDROID_LD

Wybiera tag łączący, którego chcesz użyć. lld jest obecnie w fazie eksperymentalnej i można ją włączyć za pomocą tego argumentu.

Wartość Uwagi
LD Włącza LD.
domyślnie Użyj domyślnego tagu łączącego dla danego interfejsu ABI.

ANDROID_NATIVE_API_LEVEL

Alias dla systemu ANDROID_PLATFORM.

ANDROID_PLATFORM

Określa minimalny poziom interfejsu API obsługiwany przez aplikację lub bibliotekę. Ta wartość odpowiada parametrowi minSdkVersion aplikacji.

Gradle

Gdy używasz wtyczki Androida do obsługi Gradle, ta wartość jest automatycznie ustawiana na zgodność z parametrem minSdkVersion aplikacji i nie powinna być ustawiana ręcznie.

Wiersz poleceń

W przypadku bezpośredniego wywoływania wartości CMake domyślnie przyjmuje się najniższy poziom interfejsu API obsługiwany przez używany pakiet NDK. Na przykład w przypadku pakietu NDK r20 wartość domyślna to poziom API 16.

W przypadku tego parametru akceptowane są różne formaty:

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

Format $API_LETTER pozwala określić android-N bez konieczności określania liczby powiązanej z tą wersją. Pamiętaj, że w przypadku niektórych wersji interfejs API został zwiększony bez zwiększenia liczby liter. Te interfejsy API można określić, dołączając sufiks -MR1. Na przykład poziom API 25 to android-N-MR1.

ANDROID_STL

Określa, którego STL ma użyć w tej aplikacji. Więcej informacji znajdziesz w artykule na temat obsługi bibliotek C++. Domyślnie używana będzie c++_static.

Wartość Uwagi
c++_udostępniony Wariant biblioteki udostępnionej libc++.
C++_static Statyczna wersja biblioteki libc++.
brak Brak obsługi biblioteki standardowej C++.
system STL systemu

Omówienie polecenia kompilacji CMake

Podczas debugowania problemów z kompilacją CMake warto znać konkretne argumenty kompilacji używane przez Gradle podczas kompilacji na Androida.

Wtyczka Androida do obsługi Gradle zapisuje w build_command.txt argumenty kompilacji używane do wykonywania kompilacji CMake dla każdej pary interfejsu ABI i typu kompilacji. Te pliki znajdują się w tym katalogu:

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

Poniższy fragment kodu zawiera przykładowe argumenty CMake do utworzenia możliwej do debugowania wersji przykładowego hello-jni kierowanego na architekturę 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

Użyj gotowych bibliotek

Jeśli gotowa biblioteka, którą chcesz zaimportować, jest rozpowszechniana w ramach AAR, postępuj zgodnie z dokumentacją Studio dotyczącą zależności, aby zaimportować i używać tych plików. Jeśli nie korzystasz z pakietu AGP, możesz skorzystać ze strony https://google.github.io/prefab/example-workflow.html, ale jego migracja do tego standardu jest prawdopodobnie znacznie łatwiejsza.

W przypadku bibliotek, które nie są rozpowszechniane w ramach AAR, instrukcje używania gotowych bibliotek z CMake można znaleźć w dokumentacji add_library dotyczącej celów IMPORTED w instrukcji obsługi CMake.

Tworzenie kodu spoza witryny

Istnieje kilka sposobów tworzenia kodu zewnętrznego w projekcie CMake. To, która opcja sprawdzi się najlepiej, zależy od Twojej sytuacji. Często najlepszym rozwiązaniem jest nierobienie tego w ogóle. Zamiast tego utwórz AAR dla biblioteki i wykorzystaj go w swojej aplikacji. Nie musisz publikować usługi AAR. Może być wewnętrzny w projekcie Gradle.

Jeśli nie jest dostępna:

  • Dostawca (tj. skopiuj) zewnętrzne źródło do swojego repozytorium i skompiluj je za pomocą elementu add_subdirectory. Działa to tylko wtedy, gdy inna biblioteka również jest skompilowana w CMake.
  • Zdefiniuj projekt ExternalProject.
  • Utwórz bibliotekę niezależnie od swojego projektu i postępuj zgodnie ze wskazówkami Użyj gotowych bibliotek, aby zaimportować ją jako gotową.

Obsługa YASM w CMake

NDK zapewnia obsługę CMake w celu tworzenia kodu składania napisanego w YASM na potrzeby architektur x86 i x86-64. YASM to oprogramowanie open source oparte na architekturze NASM i przeznaczone do architektur x86 i x86-64.

Aby skompilować kod asemblera za pomocą CMake, wprowadź te zmiany w pliku CMakeLists.txt projektu:

  1. Wywołaj metodę enable_language z wartością ustawioną na ASM_NASM.
  2. W zależności od tego, czy tworzysz bibliotekę współdzieloną czy wykonywalny plik binarny, wywołaj add_library lub add_executable. Przekaż w argumentach listę plików źródłowych złożonych z plików .asm dla programu asemblera w YASM i plików .c dla powiązanych bibliotek lub funkcji C.

Poniższy fragment kodu pokazuje, jak możesz skonfigurować CMakeLists.txt, aby utworzyć program YASM jako bibliotekę współdzieloną.

cmake_minimum_required(VERSION 3.6.0)

enable_language(ASM_NASM)

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

Przykład tworzenia programu YASM jako pliku wykonywalnego znajdziesz w teście yasm w repozytorium git NDK.

Zgłaszanie problemów

Jeśli napotkasz problemy z NDK lub jego plikiem łańcucha narzędzi CMake, zgłoś je za pomocą narzędzia do śledzenia problemów android-ndk/ndk na GitHubie. W przypadku problemów z Gradle lub wtyczką Androida do obsługi Gradle zgłoś błąd w Studio.