Чтобы включить проект собственной библиотеки в качестве зависимости сборки Gradle, вам необходимо предоставить Gradle путь к файлу сценария CMake или ndk-build. Когда вы создаете свое приложение, Gradle запускает CMake или ndk-build и упаковывает общие библиотеки вместе с вашим приложением. Gradle также использует сценарий сборки, чтобы знать, какие файлы следует вставить в проект Android Studio, чтобы вы могли получить к ним доступ из окна проекта . Если у вас нет сценария сборки для собственных источников, вам необходимо создать сценарий сборки CMake, прежде чем продолжить.
Каждый модуль в вашем проекте Android может быть связан только с одним файлом сценария CMake или ndk-build. Так, например, если вы хотите собрать и упаковать выходные данные из нескольких проектов CMake, вам нужно использовать один файл CMakeLists.txt
в качестве сценария сборки CMake верхнего уровня (с которым вы затем связываете Gradle) и добавлять другие проекты CMake в качестве зависимостей. этого сценария сборки. Аналогично, если вы используете ndk-build, вы можете включить другие файлы Makefile в файл сценария Android.mk
верхнего уровня.
После того как вы свяжете Gradle с собственным проектом, Android Studio обновит панель «Проект» , чтобы отобразить исходные файлы и собственные библиотеки в группе cpp , а также ваши внешние сценарии сборки в группе «Внешние файлы сборки» .
Примечание. При внесении изменений в конфигурацию Gradle обязательно примените изменения, нажав «Синхронизировать проект». на панели инструментов. Кроме того, при внесении изменений в файл сценария CMake или ndk-build после того, как вы уже связали его с Gradle, вам следует синхронизировать Android Studio с вашими изменениями, выбрав «Сборка» > «Обновить связанные проекты C++» в строке меню.
Используйте пользовательский интерфейс Android Studio
Вы можете связать Gradle с внешним проектом CMake или ndk-build, используя пользовательский интерфейс Android Studio:
- Откройте панель «Проект» в левой части IDE и выберите представление Android .
- Щелкните правой кнопкой мыши модуль, который вы хотите связать с собственной библиотекой, например модуль приложения , и выберите в меню «Связать проект C++ с Gradle» . Вы должны увидеть диалоговое окно, подобное показанному на рисунке 4.
- В раскрывающемся меню выберите CMake или ndk-build .
- Если вы выберете CMake , используйте поле рядом с «Путь к проекту» , чтобы указать файл сценария
CMakeLists.txt
для вашего внешнего проекта CMake. - Если вы выберете ndk-build , используйте поле рядом с «Путь к проекту» , чтобы указать файл сценария
Android.mk
для вашего внешнего проекта ndk-build. Android Studio также включает файлApplication.mk
если он находится в том же каталоге, что и ваш файлAndroid.mk
.
Рисунок 4. Связывание внешнего проекта C++ с помощью диалогового окна Android Studio.
- Если вы выберете CMake , используйте поле рядом с «Путь к проекту» , чтобы указать файл сценария
- Нажмите ОК .
Настройте Gradle вручную
Чтобы вручную настроить Gradle для связи с вашей собственной библиотекой, вам необходимо добавить блок externalNativeBuild
в файл build.gradle
на уровне модуля и настроить его с помощью блока cmake
или ndkBuild
:
android {
...
defaultConfig {...}
buildTypes {...}
// Encapsulates your external native build configurations.
externalNativeBuild {
// Encapsulates your CMake build configurations.
cmake {
// Provides a relative path to your CMake build script.
path "CMakeLists.txt"
}
}
}
android {
...
defaultConfig {...}
buildTypes {...}
// Encapsulates your external native build configurations.
externalNativeBuild {
// Encapsulates your CMake build configurations.
cmake {
// Provides a relative path to your CMake build script.
path = file("CMakeLists.txt")
}
}
}
Примечание. Если вы хотите связать Gradle с существующим проектом ndk-build, используйте блок ndkBuild
вместо блока cmake
и укажите относительный путь к файлу Android.mk
. Gradle также включает файл Application.mk
если он находится в том же каталоге, что и ваш файл Android.mk
.
Укажите дополнительные конфигурации
Вы можете указать дополнительные аргументы и флаги для CMake или ndk-build, настроив другой блок externalNativeBuild
в блоке defaultConfig
вашего файла build.gradle
на уровне модуля. Подобно другим свойствам в блоке defaultConfig
, вы можете переопределить эти свойства для каждого варианта продукта в вашей конфигурации сборки.
Например, если ваш проект CMake или ndk-build определяет несколько собственных библиотек и исполняемых файлов, вы можете использовать свойство targets
для сборки и упаковки только подмножества этих артефактов для данного варианта продукта. В следующем примере кода описаны некоторые свойства, которые можно настроить:
android {
...
defaultConfig {
...
// This block is different from the one you use to link Gradle
// to your CMake or ndk-build script.
externalNativeBuild {
// For ndk-build, instead use the ndkBuild block.
cmake {
// Passes optional arguments to CMake.
arguments "-DANDROID_ARM_NEON=TRUE", "-DANDROID_TOOLCHAIN=clang"
// Sets a flag to enable format macro constants for the C compiler.
cFlags "-D__STDC_FORMAT_MACROS"
// Sets optional flags for the C++ compiler.
cppFlags "-fexceptions", "-frtti"
}
}
}
buildTypes {...}
productFlavors {
...
demo {
...
externalNativeBuild {
cmake {
...
// Specifies which native libraries or executables to build and package
// for this product flavor. The following tells Gradle to build only the
// "native-lib-demo" and "my-executible-demo" outputs from the linked
// CMake project. If you don't configure this property, Gradle builds all
// executables and shared object libraries that you define in your CMake
// (or ndk-build) project. However, by default, Gradle packages only the
// shared libraries in your app.
targets "native-lib-demo",
// You need to specify this executable and its sources in your CMakeLists.txt
// using the add_executable() command. However, building executables from your
// native sources is optional, and building native libraries to package into
// your app satisfies most project requirements.
"my-executible-demo"
}
}
}
paid {
...
externalNativeBuild {
cmake {
...
targets "native-lib-paid",
"my-executible-paid"
}
}
}
}
// Use this block to link Gradle to your CMake or ndk-build script.
externalNativeBuild {
cmake {...}
// or ndkBuild {...}
}
}
android {
...
defaultConfig {
...
// This block is different from the one you use to link Gradle
// to your CMake or ndk-build script.
externalNativeBuild {
// For ndk-build, instead use the ndkBuild block.
cmake {
// Passes optional arguments to CMake.
arguments += listOf("-DANDROID_ARM_NEON=TRUE", "-DANDROID_TOOLCHAIN=clang")
// Sets a flag to enable format macro constants for the C compiler.
cFlags += listOf("-D__STDC_FORMAT_MACROS")
// Sets optional flags for the C++ compiler.
cppFlags += listOf("-fexceptions", "-frtti")
}
}
}
buildTypes {...}
productFlavors {
...
create("demo") {
...
externalNativeBuild {
cmake {
...
// Specifies which native libraries or executables to build and package
// for this product flavor. The following tells Gradle to build only the
// "native-lib-demo" and "my-executible-demo" outputs from the linked
// CMake project. If you don't configure this property, Gradle builds all
// executables and shared object libraries that you define in your CMake
// (or ndk-build) project. However, by default, Gradle packages only the
// shared libraries in your app.
targets += listOf("native-lib-demo",
// You need to specify this executable and its sources in your CMakeLists.txt
// using the add_executable() command. However, building executables from your
// native sources is optional, and building native libraries to package into
// your app satisfies most project requirements.
"my-executible-demo")
}
}
}
create("paid") {
...
externalNativeBuild {
cmake {
...
targets += listOf("native-lib-paid",
"my-executible-paid")
}
}
}
}
// Use this block to link Gradle to your CMake or ndk-build script.
externalNativeBuild {
cmake {...}
// or ndkBuild {...}
}
}
Чтобы узнать больше о настройке разновидностей продукта и вариантов сборки, перейдите в раздел Настройка вариантов сборки . Список переменных, которые можно настроить для CMake с помощью свойства arguments
, см. в разделе Использование переменных CMake .
Включить готовые собственные библиотеки
Если вы хотите, чтобы Gradle упаковывал готовые собственные библиотеки, которые не используются ни в одной внешней собственной сборке, добавьте их в каталог src/main/jniLibs/ ABI
вашего модуля.
Версии подключаемого модуля Android Gradle до 4.0 требуют включения IMPORTED
целей CMake в каталог jniLibs
, чтобы они могли быть включены в ваше приложение. Если вы переходите с более ранней версии плагина, вы можете столкнуться с такой ошибкой:
* What went wrong:
Execution failed for task ':app:mergeDebugNativeLibs'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade
> More than one file was found with OS independent path 'lib/x86/libprebuilt.so'
Если вы используете плагин Android Gradle 4.0, переместите все библиотеки, используемые IMPORTED
целями CMake, из каталога jniLibs
, чтобы избежать этой ошибки.
Укажите ABI
По умолчанию Gradle собирает вашу собственную библиотеку в отдельные файлы .so
для двоичных интерфейсов приложений (ABI), которые поддерживает NDK, и упаковывает их все в ваше приложение. Если вы хотите, чтобы Gradle собирал и упаковывал только определенные конфигурации ABI ваших собственных библиотек, вы можете указать их с помощью флага ndk.abiFilters
в файле build.gradle
на уровне модуля, как показано ниже:
android {
...
defaultConfig {
...
externalNativeBuild {
cmake {...}
// or ndkBuild {...}
}
// Similar to other properties in thedefaultConfig
block,
// you can configure the ndk block for each product flavor
// in your build configuration.
ndk {
// Specifies the ABI configurations of your native
// libraries Gradle should build and package with your app.
abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a',
'arm64-v8a'
}
}
buildTypes {...}
externalNativeBuild {...}
}
android {
...
defaultConfig {
...
externalNativeBuild {
cmake {...}
// or ndkBuild {...}
}
// Similar to other properties in thedefaultConfig
block,
// you can configure the ndk block for each product flavor
// in your build configuration.
ndk {
// Specifies the ABI configurations of your native
// libraries Gradle should build and package with your app.
abiFilters += listOf("x86", "x86_64", "armeabi", "armeabi-v7a",
"arm64-v8a")
}
}
buildTypes {...}
externalNativeBuild {...}
}
В большинстве случаев вам нужно указать только abiFilters
в блоке ndk
, как показано выше, поскольку он сообщает Gradle как собрать, так и упаковать эти версии ваших собственных библиотек. Однако, если вы хотите контролировать, что Gradle должен создавать, независимо от того, что вы хотите, чтобы он упаковал в ваше приложение, настройте еще один флаг abiFilters
в блоке defaultConfig.externalNativeBuild.cmake
(или блоке defaultConfig.externalNativeBuild.ndkBuild
). Gradle создает эти конфигурации ABI, но упаковывает только те, которые вы указываете в блоке defaultConfig.ndk
.
Рекомендуется публиковать с помощью пакетов приложений Android, чтобы еще больше уменьшить размер вашего приложения, поскольку при загрузке будут доставлены только собственные библиотеки, соответствующие ABI устройства пользователя.
Для публикации устаревших приложений с использованием APK (созданных до августа 2021 г.) рассмотрите возможность настройки нескольких APK на основе ABI — вместо создания одного большого APK со всеми версиями собственных библиотек Gradle создает отдельный APK для каждого ABI, который вы хотите поддерживать, и только упаковывает файлы, необходимые каждому ABI. Если вы настраиваете несколько APK для каждого ABI без указания флага abiFilters
, как показано в примере кода выше, Gradle создает все поддерживаемые версии ABI ваших собственных библиотек, но упаковывает только те, которые вы указываете в конфигурации с несколькими APK. Чтобы избежать создания ненужных версий собственных библиотек, предоставьте один и тот же список ABI как для флага abiFilters
, так и для конфигурации нескольких APK для каждого ABI.