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:
- Wywołaj metodę
enable_language
z wartością ustawioną naASM_NASM
. - W zależności od tego, czy tworzysz bibliotekę współdzieloną czy wykonywalny plik binarny, wywołaj
add_library
lubadd_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.