CMake

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:

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