Сценарий сборки CMake — это обычный текстовый файл, который необходимо назвать CMakeLists.txt
и который включает команды, которые CMake использует для сборки библиотек C/C++. Если в ваших собственных источниках еще нет сценария сборки CMake, вам необходимо создать его самостоятельно и включить соответствующие команды CMake. Чтобы узнать, как установить CMake, см. раздел Установка и настройка NDK и CMake .
В этом разделе описаны некоторые основные команды, которые следует включить в сценарий сборки, чтобы указать CMake, какие источники использовать при создании собственной библиотеки. Чтобы узнать больше, прочтите официальную документацию по командам CMake .
После настройки нового сценария сборки CMake вам необходимо настроить Gradle для включения вашего проекта CMake в качестве зависимости сборки, чтобы Gradle собирал и упаковывал вашу собственную библиотеку с APK вашего приложения.
Примечание. Если в вашем проекте используется ndk-build, вам не нужно создавать сценарий сборки CMake. Вы можете просто настроить Gradle для включения существующего проекта собственной библиотеки, указав путь к файлу Android.mk
.
Создайте сценарий сборки CMake.
Чтобы создать обычный текстовый файл, который можно использовать в качестве сценария сборки CMake, выполните следующие действия:
- Откройте панель «Проект» в левой части IDE и выберите представление «Проект» в раскрывающемся меню.
- Щелкните правой кнопкой мыши корневой каталог your-module и выберите «Создать» > «Файл» .
Примечание. Вы можете создать сценарий сборки в любом месте. Однако при настройке сценария сборки пути к собственным исходным файлам и библиотекам указываются относительно местоположения сценария сборки.
- Введите «CMakeLists.txt» в качестве имени файла и нажмите «ОК» .
Теперь вы можете настроить сценарий сборки, добавив команды CMake. Чтобы указать CMake создать собственную библиотеку из собственного исходного кода, добавьте команды cmake_minimum_required()
и add_library()
в свой сценарий сборки:
# Sets the minimum version of CMake required to build your native library. # This ensures that a certain set of CMake features is available to # your build. cmake_minimum_required(VERSION 3.4.1) # Specifies a library name, specifies whether the library is STATIC or # SHARED, and provides relative paths to the source code. You can # define multiple libraries by adding multiple add_library() commands, # and CMake builds them for you. When you build your app, Gradle # automatically packages shared libraries with your APK. add_library( # Specifies the name of the library. native-lib # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). src/main/cpp/native-lib.cpp )
Совет: Подобно тому, как вы можете указать CMake создать собственную библиотеку из исходных файлов, вы можете использовать команду add_executable()
, чтобы указать CMake вместо этого создать исполняемый файл из этих исходных файлов. Однако создание исполняемых файлов из собственных источников не является обязательным, а создание собственных библиотек для упаковки в APK удовлетворяет большинству требований проекта.
Когда вы добавляете исходный файл или библиотеку в сценарий сборки CMake с помощью add_library()
, Android Studio также отображает связанные файлы заголовков в представлении «Проект» после синхронизации проекта. Однако для того, чтобы CMake мог найти файлы заголовков во время компиляции, вам необходимо добавить команду include_directories()
в сценарий сборки CMake и указать путь к вашим заголовкам:
add_library(...) # Specifies a path to native header files. include_directories(src/main/cpp/include/)
Соглашение, которое CMake использует для именования файла вашей библиотеки, выглядит следующим образом:
lib library-name .so
Например, если вы укажете «native-lib» в качестве имени вашей общей библиотеки в сценарии сборки, CMake создаст файл с именем libnative-lib.so
. Однако при загрузке этой библиотеки в код Java или Kotlin используйте имя, указанное в сценарии сборки CMake:
Котлин
companion object { init { System.loadLibrary("native-lib"); } }
Ява
static { System.loadLibrary("native-lib"); }
Примечание. Если вы переименовываете или удаляете библиотеку в сценарии сборки CMake, вам необходимо очистить проект, прежде чем Gradle применит изменения или удалит старую версию библиотеки из вашего APK. Чтобы очистить проект, выберите «Сборка» > «Очистить проект» в строке меню.
Android Studio автоматически добавляет исходные файлы и заголовки в группу cpp на панели «Проект» . Используя несколько команд add_library()
, вы можете определить дополнительные библиотеки, которые CMake будет собирать из других исходных файлов.
Добавить API NDK
Android NDK предоставляет набор собственных API и библиотек, которые могут оказаться вам полезными. Вы можете использовать любой из этих API, включив библиотеки NDK в файл сценария CMakeLists.txt
вашего проекта.
Готовые библиотеки NDK уже существуют на платформе Android, поэтому вам не нужно собирать их или упаковывать в APK. Поскольку библиотеки NDK уже являются частью пути поиска CMake, вам даже не нужно указывать расположение библиотеки в вашей локальной установке NDK — вам нужно только предоставить CMake имя библиотеки, которую вы хотите использовать, и ссылку это против вашей собственной родной библиотеки.
Добавьте команду find_library()
в сценарий сборки CMake, чтобы найти библиотеку NDK и сохранить ее путь в виде переменной. Эту переменную вы используете для ссылки на библиотеку NDK в других частях сценария сборки. В следующем примере находится библиотека поддержки журналов, специфичная для Android , и сохраняется путь к ней в log-lib
:
find_library( # Defines the name of the path variable that stores the # location of the NDK library. log-lib # Specifies the name of the NDK library that # CMake needs to locate. log )
Чтобы ваша собственная библиотека могла вызывать функции в библиотеке log
, вам необходимо связать библиотеки с помощью команды target_link_libraries()
в сценарии сборки CMake:
find_library(...) # Links your native library against one or more other native libraries. target_link_libraries( # Specifies the target library. native-lib # Links the log library to the target library. ${log-lib} )
NDK также включает в себя некоторые библиотеки в качестве исходного кода, которые вам необходимо собрать и связать с вашей собственной библиотекой. Вы можете скомпилировать исходный код в собственную библиотеку, используя команду add_library()
в сценарии сборки CMake. Чтобы указать путь к вашей локальной библиотеке NDK, вы можете использовать переменную пути ANDROID_NDK
, которую Android Studio автоматически определяет для вас.
Следующая команда сообщает CMake собрать android_native_app_glue.c
, который управляет событиями жизненного цикла NativeActivity
и сенсорным вводом, в статическую библиотеку и связывает ее с native-lib
:
add_library( app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c ) # You need to link static libraries against your shared native library. target_link_libraries( native-lib app-glue ${log-lib} )
Добавьте другие готовые библиотеки
Добавление предварительно созданной библиотеки аналогично указанию другой собственной библиотеки для сборки CMake. Однако, поскольку библиотека уже собрана, вам необходимо использовать флаг IMPORTED
, чтобы сообщить CMake, что вы хотите только импортировать библиотеку в свой проект:
add_library( imported-lib SHARED IMPORTED )
Затем вам нужно указать путь к библиотеке с помощью команды set_target_properties()
, как показано ниже.
Некоторые библиотеки предоставляют отдельные пакеты для конкретных архитектур ЦП или двоичных интерфейсов приложений (ABI) и организуют их в отдельные каталоги. Этот подход помогает библиотекам использовать преимущества определенных архитектур ЦП, позволяя вам использовать только те версии библиотеки, которые вам нужны. Чтобы добавить несколько версий ABI библиотеки в сценарий сборки CMake без необходимости писать несколько команд для каждой версии библиотеки, вы можете использовать переменную пути ANDROID_ABI
. Эта переменная использует список ABI по умолчанию, которые поддерживает NDK , или отфильтрованный список ABI, которые вы вручную настраиваете для использования Gradle . Например:
add_library(...) set_target_properties( # Specifies the target library. imported-lib # Specifies the parameter you want to define. PROPERTIES IMPORTED_LOCATION # Provides the path to the library you want to import. imported-lib/src/${ANDROID_ABI}/libimported-lib.so )
Чтобы CMake нашел файлы заголовков во время компиляции, вам необходимо использовать команду include_directories()
и указать путь к файлам заголовков:
include_directories( imported-lib/include/ )
Примечание. Если вы хотите упаковать предварительно созданную библиотеку, которая не является зависимостью во время сборки — например, при добавлении предварительно созданной библиотеки, которая является зависимостью imported-lib
, вам не нужно выполнять следующие инструкции для связывания библиотеки.
Чтобы связать предварительно созданную библиотеку с вашей собственной библиотекой, добавьте ее в команду target_link_libraries()
в сценарии сборки CMake:
target_link_libraries( native-lib imported-lib app-glue ${log-lib} )
Чтобы упаковать готовую библиотеку в APK, вам необходимо вручную настроить Gradle с помощью блока sourceSets
, включив в него путь к вашему файлу .so
. После сборки APK вы можете проверить, какие библиотеки Gradle упаковывает в ваш APK, с помощью анализатора APK .
Включить другие проекты CMake
Если вы хотите создать несколько проектов CMake и включить их результаты в свой проект Android, вы можете использовать один файл CMakeLists.txt
в качестве сценария сборки CMake верхнего уровня (который вы связываете с Gradle ) и добавлять дополнительные проекты CMake в качестве зависимостей. этого сценария сборки. Следующий сценарий сборки CMake верхнего уровня использует команду add_subdirectory()
для указания другого файла CMakeLists.txt
в качестве зависимости сборки, а затем связывается с его выходными данными так же, как и с любой другой предварительно созданной библиотекой.
# Sets lib_src_DIR to the path of the target CMake project. set( lib_src_DIR ../gmath ) # Sets lib_build_DIR to the path of the desired output directory. set( lib_build_DIR ../gmath/outputs ) file(MAKE_DIRECTORY ${lib_build_DIR}) # Adds the CMakeLists.txt file located in the specified directory # as a build dependency. add_subdirectory( # Specifies the directory of the CMakeLists.txt file. ${lib_src_DIR} # Specifies the directory for the build outputs. ${lib_build_DIR} ) # Adds the output of the additional CMake build as a prebuilt static # library and names it lib_gmath. add_library( lib_gmath STATIC IMPORTED ) set_target_properties( lib_gmath PROPERTIES IMPORTED_LOCATION ${lib_build_DIR}/${ANDROID_ABI}/lib_gmath.a ) include_directories( ${lib_src_DIR}/include ) # Links the top-level CMake build output against lib_gmath. target_link_libraries( native-lib ... lib_gmath )
Вызов CMake из командной строки
Используйте следующую команду для вызова CMake для создания проекта Ninja за пределами Android Studio:
cmake
-Hpath/to/cmakelists/folder
-Bpath/to/generated/ninja/project/debug/ABI
-DANDROID_ABI=ABI // For example, arm64-v8a
-DANDROID_PLATFORM=platform-version-string // For example, android-16
-DANDROID_NDK=android-sdk/ndk/ndk-version
-DCMAKE_TOOLCHAIN_FILE=android-sdk/ndk/ndk-version/build/cmake/android.toolchain.cmake
-G Ninja
Эта команда сгенерирует проект Ninja, который можно выполнить для создания исполняемых библиотек Android (файлы .so
). CMAKE_TOOLCHAIN_FILE
необходим для использования поддержки CMake NDK. Для CMake 3.21 или более поздней версии вместо этого можно использовать встроенную поддержку NDK CMake, но необходимо использовать другую группу переменных, как описано в документации CMake по кросс-компиляции для Android .