Para incluir seu projeto de biblioteca nativa como uma dependência de compilação do Gradle, é necessário que o Gradle tenha o caminho para seu arquivo de script CMake ou ndk-build. Quando você cria um app, o Gradle executa o CMake ou o ndk-build e empacota bibliotecas compartilhadas no app. O Gradle também usa o script de compilação para saber quais arquivos incluir no projeto do Android Studio, para que você possa acessá-los na janela Project. Se você não tem um script de build para as origens nativas, é necessário criar um script de build CMake antes de continuar.
Cada módulo do projeto Android pode vincular apenas um arquivo de script CMake ou
ndk-build. Por exemplo, se você quiser criar e empacotar saídas de
vários projetos CMake, será necessário usar um arquivo CMakeLists.txt
como seu script de compilação CMake de nível superior, ao qual o Gradle será vinculado, e
incluir outros projetos do CMake como
dependências desse script. Da mesma forma, se você estiver usando o ndk-build,
poderá incluir outros Makefiles (link em inglês) ao arquivo de script
Android.mk
de nível superior.
Depois de vincular o Gradle a um projeto nativo, o Android Studio atualiza o painel Project para mostrar os arquivos de origem e as bibliotecas nativas no grupo cpp e os scripts de compilação externos no grupo External Build Files.
Observação: ao fazer mudanças na configuração do Gradle, aplique-as clicando em Sync Project na barra de ferramentas. Além disso, se você mudar o arquivo de script CMake ou ndk-build após vinculá-lo ao Gradle, selecione Build > Refresh Linked C++ Projects na barra de menus para sincronizar o Android Studio com as mudanças.
Usar a IU do Android Studio
Você pode usar a IU do Android Studio para vincular o Gradle a um projeto CMake ou ndk-build externo:
- Abra o painel Project à esquerda do ambiente de desenvolvimento integrado e selecione a visualização Android.
- Clique com o botão direito no módulo que você quer vincular à biblioteca nativa, por exemplo, o módulo app, e selecione Link C++ Project with Gradle/0 no menu. Você verá uma caixa de diálogo semelhante à mostrada na figura 4.
- No menu suspenso, selecione CMake ou
ndk-build.
- Se você selecionar CMake, use o campo ao lado de
Project Path para especificar o arquivo de script
CMakeLists.txt
para o projeto CMake externo. - Se você selecionar ndk-build, use o campo ao lado de
Project Path para especificar o arquivo de script
Android.mk
para o projeto ndk-build externo. O Android Studio também incluirá o arquivoApplication.mk
se ele estiver no mesmo diretório que o arquivoAndroid.mk
.
- Se você selecionar CMake, use o campo ao lado de
Project Path para especificar o arquivo de script
- Clique em OK.
Configurar manualmente o Gradle
Para configurar o Gradle manualmente e vinculá-lo à sua biblioteca nativa, é necessário adicionar
o bloco
externalNativeBuild
ao arquivo
build.gradle
do módulo e configurá-lo com o bloco
cmake
ou
ndkBuild
(links em inglês):
Groovy
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" } } }
Kotlin
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") } } }
Observação: caso queira vincular o Gradle a um projeto
existente do ndk-build, use o bloco
ndkBuild
em vez do bloco
cmake
(links em inglês) e informe um caminho relativo para o arquivo Android.mk
. O Gradle também
incluirá o arquivo Application.mk
se ele estiver
localizado no mesmo diretório que o Android.mk
.
Especificar outras configurações
Você pode especificar outros argumentos e sinalizações para o CMake ou ndk-build
configurando outro bloco
externalNativeBuild
(link em inglês) no
bloco defaultConfig
do arquivo
build.gradle
do módulo. Assim como em outras propriedades no bloco
defaultConfig
, é possível substituir essas propriedades para cada
variação de produto na configuração da compilação.
Por exemplo: se o projeto CMake ou ndk-build definir várias bibliotecas
nativas e executáveis, você poderá usar a propriedade
targets
(link em inglês) para criar e empacotar apenas um subconjunto desses
artefatos para determinada variação de produto. O exemplo de código a seguir descreve
algumas das propriedades que podem ser configuradas:
Groovy
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 {...} } }
Kotlin
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 {...} } }
Para saber mais sobre como configurar variações de produtos e variantes de build, consulte
Configurar variantes de build. Para
ver uma lista de variáveis que podem ser configuradas para o CMake com a propriedade
arguments
, consulte Usar variáveis do CMake.
Incluir bibliotecas nativas pré-compiladas
Se você quiser que o Gradle empacote bibliotecas nativas pré-compiladas que não sejam usadas em nenhum
build nativo externo, adicione-as ao diretório
src/main/jniLibs/ABI
do módulo.
Versões do Plug-in do Android para Gradle anteriores à 4.0 exigiam a inclusão de destinos
IMPORTED
do CMake no diretório jniLibs
para que elas fossem incluídas no
app. Se você estiver migrando de uma versão anterior do plug-in, poderá
encontrar um erro como este:
* 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'
Se você estiver usando o Plug-in do Android para Gradle 4.0, remova do diretório jniLibs
todas as
bibliotecas usadas pelos destinos IMPORTED
do CMake para evitar esse erro.
Especificar ABIs
Por padrão, o Gradle cria sua biblioteca nativa em arquivos .so
separados para as Interfaces binárias do aplicativo
(ABIs) compatíveis com o NDK e inclui todas elas no app. Se você quiser que
o Gradle crie e inclua somente determinadas configurações de ABI das suas bibliotecas
nativas, especifique-as com a sinalização
ndk.abiFilters
(link em inglês)
no arquivo build.gradle
no nível do módulo, conforme mostrado abaixo:
Groovy
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 {...}
}
Kotlin
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 {...}
}
Na maioria dos casos, basta especificar abiFilters
no
bloco ndk
, conforme mostrado acima, porque isso instrui o Gradle a criar
e empacotar essas versões das suas bibliotecas nativas. No entanto, caso queira
controlar o que o Gradle vai criar, independente do que você quer que ele
empacote no app, configure outra sinalização abiFilters
no bloco
defaultConfig.externalNativeBuild.cmake
(ou o bloco
defaultConfig.externalNativeBuild.ndkBuild
). O Gradle
cria essas configurações de ABI, mas só empacota as especificadas no
bloco
defaultConfig.ndk
(link em inglês).
É recomendável publicar usando Android App Bundles para reduzir ainda mais o tamanho do app, já que somente as bibliotecas nativas correspondentes à ABI do dispositivo do usuário serão enviadas com o download.
Para apps legados que publicam usando APKs (criados antes de agosto de 2021), considere
configurar
vários APKs com base na ABI, em vez de criar um APK grande com todas as
versões das bibliotecas nativas. O Gradle cria um APK separado para cada ABI
compatível e inclui apenas os arquivos necessários para cada uma. Se você
configurar vários APKs por ABI sem especificar a sinalização
abiFilters
, conforme mostrado no exemplo de código acima, o Gradle criará
todas as versões de ABI compatíveis das bibliotecas nativas, mas empacotará somente aquelas
especificadas na configuração de vários APKs. Para evitar a criação de versões
indesejadas das bibliotecas nativas, informe a mesma lista de ABIs para
a sinalização abiFilters
e para sua configuração de vários APKs por
ABI.