Чтобы включить проект собственной библиотеки в качестве зависимости сборки 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 the defaultConfig
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 the defaultConfig
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.