NDK na Androida obsługuje użycie CMake
skompilować kod w C i C++ dla swojej aplikacji. Na tej stronie znajdują się informacje na temat korzystania
Wykonaj za pomocą NDK za pomocą ExternalNativeBuild
wtyczki Androida do obsługi Gradle lub gdy
przez bezpośrednie wywołanie CMake.
Plik łańcucha narzędzi CMake
NDK obsługuje CMake za pomocą plikutoolchain. Pliki łańcucha narzędzi to pliki CMake
które dostosowują działanie łańcucha narzędzi na potrzeby kompilacji krzyżowej. Łańcuch narzędzi
używany do NDK znajduje się w NDK pod adresem
<NDK>/build/cmake/android.toolchain.cmake
W poleceniu podane są parametry kompilacji, takie jak ABI, minSdkVersion
itp.
wiersza podczas wywoływania funkcji cmake
. Listę obsługiwanych argumentów znajdziesz w
Toolchain argumentów.
Nowy plik łańcucha narzędzi
Wcześniej organizacje NDK eksperymentowały z nową implementacją pliku łańcucha narzędzi, zmniejszyłyby różnice w działaniu między używaniem pliku NDK łańcucha narzędzi za pomocą wbudowanej obsługi CMake. Okazało się to jednak na tyle duże pracy (które nie zostały ukończone), ale nie poprawiły w rzeczywistości zachowania, więc się tym już nie zajmujemy.
Nowy w pliku łańcucha narzędzi występują zmiany w działaniu w porównaniu ze starszym plikiem
. Działanie domyślne to zalecany przepływ pracy. Jeśli
przy użyciu -DANDROID_USE_LEGACY_TOOLCHAIN_FILE=OFF
, zalecamy usunięcie tej flagi
z kompilacji. Nowy plik łańcucha narzędzi nigdy nie był zgodny ze starszą wersją
łańcucha narzędzi, więc prawdopodobnie mogą wystąpić regresje.
Chociaż odradzamy korzystanie z nowego pliku łańcucha narzędzi, planuje usunąć je z NDK. Spowodowałoby to uszkodzenie kompilacji, które bazują na różnicami w działaniu nowych i starszych plików łańcucha narzędzi. Zmieniamy też nazwę opcji, by doprecyzować, że „starsze” to zależałoby też od użytkowników tej opcji. Jeśli jesteś zadowolony z używania nowego łańcucha narzędzi, którego nie trzeba migrować, ale zauważymy, z zachowaniem nowego łańcucha narzędzi prawdopodobnie nie zostanie naprawiona. musisz przeprowadzić migrację.
Wykorzystanie
Gradle
Używanie pliku łańcucha narzędzi CMake jest automatyczne podczas korzystania
externalNativeBuild
Zapoznaj się z artykułem Dodawanie kodu C i C++ do
projekt, w którym znajdziesz więcej informacji.
Wiersz poleceń
Podczas tworzenia przy użyciu CMake poza Gradle sam plik łańcucha narzędzi 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 pęku narzędzi
Do pliku łańcucha narzędzi CMake można przekazać poniższe argumenty. Jeśli tworzysz
za pomocą Gradle, dodaj argumenty do
android.defaultConfig.externalNativeBuild.cmake.arguments
zgodnie z opisem w
Dokumentacja ExternalNativeBuild. Jeśli tworzysz plik z poziomu wiersza poleceń, przekazuj argumenty do
CMake z -D
. Na przykład aby wymusić, by armeabi-v7a nie używała neonów.
zespół pomocy, przekaż -DANDROID_ARM_NEON=FALSE
.
ANDROID_ABI
Docelowy interfejs ABI. Informacje o obsługiwanych interfejsach ABI znajdziesz w artykule o interfejsach ABI Androida.
Gradle
Gradle udostępnia ten argument automatycznie. Nie ustawiaj tej wartości wprost
w pliku build.gradle
. Aby kontrolować,
jakie wartości są kierowane przez Gradle interfejsu ABI,
użyj interfejsu abiFilters
w sposób opisany w artykule o interfejsach ABI Androida.
Wiersz poleceń
Twórz kompilacje dla 1 celu na kompilację. Aby kierować reklamy na więcej niż jednego Androida: w interfejsie ABI, trzeba utworzyć kompilację raz dla każdego interfejsu ABI. Zaleca się użycie innej kompilacji dla każdego interfejsu ABI, co pozwala uniknąć kolizji między kompilacjami.
Wartość | Uwagi |
---|---|
armeabi-v7a |
|
armeabi-v7a with NEON |
Taka sama cena jak w usłudze armeabi-v7a . |
arm64-v8a |
|
x86 |
|
x86_64 |
ANDROID_ARM_MODE
Określa, czy dla armeabi-v7a wygenerować instrukcje użycia ręki czy kciuka. Nie zawiera w innych interfejsach ABI. Więcej informacji znajdziesz w artykule o interfejsach ABI Androida. dokumentacji.
Wartość | Uwagi |
---|---|
ręka | |
kciuk | Domyślne zachowanie. |
ANDROID_NATIVE_API_LEVEL
Alias dla systemu ANDROID_PLATFORM.
ANDROID_PLATFORM
Określa minimalny poziom interfejsu API obsługiwany przez aplikację lub bibliotekę. Ten
odpowiada wartości minSdkVersion
aplikacji.
Gradle
Gdy używasz wtyczki Androida do obsługi Gradle, ta wartość jest automatycznie ustawiana na
zgodne z minSdkVersion
aplikacji i nie należy go ustawiać ręcznie.
Wiersz poleceń
W przypadku bezpośredniego wywoływania CMake domyślnie ta wartość jest ustawiona na najniższy poziom interfejsu API obsługiwane przez używany system NDK. Na przykład w trybie NDK r20 ta wartość jest domyślna do poziomu interfejsu API 16.
Ten parametr może mieć wiele formatów:
android-$API_LEVEL
$API_LEVEL
android-$API_LETTER
Format $API_LETTER
umożliwia określenie android-N
bez konieczności
określić numer powiązany z danym wydaniem. Pamiętaj, że niektóre wersje
zanotowano wzrost wartości interfejsu API bez zwiększenia litery. Te interfejsy API można określić
dodając sufiks -MR1
. Na przykład poziom interfejsu API 25 to android-N-MR1
.
ANDROID_STL
Określa protokół STL, który ma być używany w przypadku tej aplikacji. Aby uzyskać więcej informacji, zobacz C++
obsługi bibliotek. Domyślnie używana jest c++_static
.
Wartość | Uwagi |
---|---|
c++_udostępnione | Wariant biblioteki libc++ z bibliotek wspólnych. |
c++_statyczne | Wariant biblioteki statycznej libc++. |
brak | Biblioteka standardowa w C++ nie jest obsługiwana. |
system | System STL |
Zarządzanie flagami kompilatora
Jeśli musisz przekazać określone flagi do kompilatora lub łączącego kompilację, znajdziesz w dokumentacji CMake dotyczącej set_target_build_options oraz pokrewną rodzinę opcji. Opcja „Zobacz też” u dołu tej strony kilka przydatnych wskazówek.
Ogólnie rzecz biorąc, sprawdzoną metodą jest stosowanie flag kompilatora jako najwęższego
w dostępnym zakresie. Flagi, które chcesz zastosować do wszystkich celów (np.
-Werror
) może być niewygodne dla każdego modułu, ale nie powinno się tak powtarzać.
stosowane na całym świecie (CMAKE_CXX_FLAGS
), ponieważ mogą one mieć niepożądany wpływ na
zależności od innych firm w projekcie. W takich przypadkach flagi mogą być
zastosowano w zakresie katalogu (add_compile_options
).
W przypadku wąskiego podzbioru flag kompilatora można również ustawić w pliku build.gradle
za pomocą właściwości cppFlags
lub podobnych. Nie należy tego robić. Flagi
przekazywane do CMake z Gradle, będą wykazywać zaskakujące zachowania w zakresie pierwszeństwa,
zgłoszeń zastępujących flagi przekazywanych niejawnie przez implementację, które są
wymagane do tworzenia kodu na Androida. Zawsze preferuj obsługę działania CMake
bezpośrednio w CMake. Jeśli chcesz kontrolować flagi kompilatora na buildType
AGP,
Więcej informacji znajdziesz w sekcji Praca z typami kompilacji AGP w CMake.
Praca z typami kompilacji AGP w CMake
Jeśli chcesz dostosować działanie CMake do niestandardowego interfejsu Gradle buildType
, użyj tego
typu Build, aby przekazać dodatkową flagę CMake (nie flagę kompilatora),
CMake skrypty kompilacji mogą być odczytywane. Na przykład, jeśli masz „bezpłatne” i „premium”
ale należy utworzyć warianty kontrolowane przez plik build.gradle.kts
te dane do CMake:
android {
buildTypes {
free {
externalNativeBuild {
cmake {
arguments.add("-DPRODUCT_VARIANT_PREMIUM=OFF")
}
}
}
premium {
externalNativeBuild {
cmake {
arguments.add("-DPRODUCT_VARIANT_PREMIUM=ON")
}
}
}
}
}
Następnie w pliku CMakeLists.txt:
if (DPRODUCT_VARIANT_PREMIUM)
# Do stuff for the premium build.
else()
# Do stuff for the free build.
endif()
Nazwa zmiennej zależy od Ciebie, ale pamiętaj, aby unikać wszelkich elementów z atrybutem
Prefiks ANDROID_
, APP_
lub CMAKE_
, aby uniknąć kolizji i nieporozumień
już istniejących flag.
Przykład znajdziesz tutaj.
Omówienie polecenia kompilacji CMake
Przy debugowaniu problemów z kompilacją CMake warto znać konkretną kompilację argumentów używanych przez Gradle podczas kompilacji krzyżowej dla Androida.
Wtyczka Androida do obsługi Gradle zapisuje argumenty kompilacji używane do wykonywania
Tworzenie kompilacji dla każdego interfejsu ABI i typu kompilacji
możesz sparować z urządzeniem build_command.txt
. Te pliki znajdują się w następujących folderach
katalogu:
<project-root>/<module-root>/.cxx/cmake/<build-type>/<ABI>/
Poniższy fragment kodu zawiera przykładowe argumenty CMake do utworzenia
możliwa do debugowania wersja przykładowej wersji hello-jni
kierowanej na armeabi-v7a
i 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
Użyj gotowych bibliotek
Jeśli gotowa biblioteka, którą chcesz zaimportować, jest rozpowszechniana jako plik AAR, postępuj zgodnie z Dokumentacja zależności Studio aby je zaimportować i używać. Jeśli nie używasz konta AGP, https://google.github.io/prefab/example-workflow.html, ale na AGP.
W przypadku bibliotek, które nie są rozpowszechniane jako narzędzie AAR, instrukcje używania gotowych
biblioteki w CMake: zapoznaj się z dokumentacją add_library
dotyczącą IMPORTED
cele w instrukcji tworzenia kampanii CMake.
Tworzenie kodu zewnętrznego
Istnieje kilka sposobów tworzenia kodu zewnętrznego w ramach CMake wybór najlepszej opcji, zależy od Twojej sytuacji. Najlepsze często jest niemożliwe. Zamiast tego utwórz plik AAR dla i wykorzystywać je w aplikacji. Nie zawsze musisz opublikować je. Może być wewnętrzny w projekcie Gradle.
Jeśli nie ma takiej możliwości:
- Dostawca (tj. skopiuj) zewnętrzne źródło do repozytorium i wykorzystaj add_subdirectory, by go utworzyć. To działa tylko wtedy, gdy druga biblioteka również w CMake.
- Zdefiniuj ExternalProject.
- Zbuduj bibliotekę niezależnie od projektu i postępuj zgodnie Użyj gotowych bibliotek, aby zaimportować go jako gotową.
Obsługa YASM w CMake
NDK zapewnia obsługę CMake dla kodu montażu budynku napisanego w YASM – uruchamianie na architekturze x86 i x86-64 i różnych architektur. YASM to narzędzie open source asystujące dla systemów x86 i x86-64 na podstawie asemblera NASM.
Aby skompilować kod asemblera za pomocą CMake, wprowadź następujące zmiany w pliku
CMakeLists.txt
:
- Wywołaj metodę
enable_language
z wartościąASM_NASM
. - W zależności od tego, czy tworzysz bibliotekę współdzieloną, czy plik wykonywalny
binarny, wywołaj
add_library
lubadd_executable
. W argumentów, przekaż listę plików źródłowych składającą się z plików.asm
dla programu montażu w YASM oraz dla plików.c
dla powiązanego języka C bibliotekami i funkcjami.
Z tego fragmentu dowiesz się, jak możesz skonfigurować: CMakeLists.txt
stworzyć 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 w postaci pliku wykonywalnego znajdziesz w dokumencie test w repozytorium NDK git.
Zgłaszanie problemów
Jeśli napotkasz problemy z pakietem NDK lub jego plikiem narzędzi CMake, zgłoś je za pomocą narzędzia do śledzenia błędów android-ndk/ndk na GitHubie. W przypadku Gradle lub Problemy z wtyczką Android do obsługi Gradle, zamiast tego zgłoś błąd w Studio.