Se você não conhece o Bazel, comece pelo laboratório Como criar para o Android com Tutorial do Bazel.
Visão geral
O Bazel pode ser executado em várias configurações de build diferentes, incluindo várias que usam
o conjunto de ferramentas do Native Development Kit (NDK) do Android. Isso significa que o normal
As regras cc_library
e cc_binary
podem ser compiladas para Android diretamente
o Bazel O Bazel usa o repositório android_ndk_repository
para fazer isso.
regra.
Pré-requisitos
Verifique se você instalou o SDK e o NDK do Android.
Para configurar o SDK e o NDK, adicione o seguinte snippet ao WORKSPACE
:
android_sdk_repository(
name = "androidsdk", # Required. Name *must* be "androidsdk".
path = "/path/to/sdk", # Optional. Can be omitted if `ANDROID_HOME` environment variable is set.
)
android_ndk_repository(
name = "androidndk", # Required. Name *must* be "androidndk".
path = "/path/to/ndk", # Optional. Can be omitted if `ANDROID_NDK_HOME` environment variable is set.
)
Para mais informações sobre a regra android_ndk_repository
, consulte a documentação
Entrada na enciclopédia.
Se estiver usando uma versão recente do Android NDK (r22 e mais recentes), use o
Implementação do Starlark de android_ndk_repository
.
Siga as instruções
README dele.
Início rápido
Para criar em C++ para Android, basta adicionar dependências cc_library
ao seu
android_binary
ou android_library
.
Por exemplo, considerando o seguinte arquivo BUILD
de um app Android:
# In <project>/app/src/main/BUILD.bazel
cc_library(
name = "jni_lib",
srcs = ["cpp/native-lib.cpp"],
)
android_library(
name = "lib",
srcs = ["java/com/example/android/bazel/MainActivity.java"],
resource_files = glob(["res/**/*"]),
custom_package = "com.example.android.bazel",
manifest = "LibraryManifest.xml",
deps = [":jni_lib"],
)
android_binary(
name = "app",
deps = [":lib"],
manifest = "AndroidManifest.xml",
)
Esse arquivo BUILD
resulta no seguinte gráfico de destino:
Figura 1. Gráfico de build do projeto Android com dependências da cc_library.
Para criar o app, basta executar:
bazel build //app/src/main:app
O comando bazel build
compila os arquivos Java, os arquivos de recursos do Android e
cc_library
regras e empacota tudo em um APK:
$ zipinfo -1 bazel-bin/app/src/main/app.apk
nativedeps
lib/armeabi-v7a/libapp.so
classes.dex
AndroidManifest.xml
...
res/...
...
META-INF/CERT.SF
META-INF/CERT.RSA
META-INF/MANIFEST.MF
O Bazel compila todas as cc_libraries em um único arquivo de objeto compartilhado (.so
).
segmentado para a ABI armeabi-v7a
por padrão. Para mudar isso ou criar para
várias ABIs ao mesmo tempo, consulte a seção sobre como configurar o
ABI.
Exemplo de configuração
Este exemplo está disponível nos exemplos do Bazel repositório.
No arquivo BUILD.bazel
, três destinos são definidos com android_binary
,
android_library
e cc_library
.
O destino de nível superior android_binary
cria o APK.
O destino cc_library
contém um único arquivo de origem C++ com uma função JNI
implementação:
#include <jni.h>
#include <string>
extern "C"
JNIEXPORT jstring
JNICALL
Java_com_example_android_bazel_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
O destino android_library
especifica as origens Java, os arquivos de recursos e as
dependência de um destino cc_library
. Neste exemplo, MainActivity.java
é carregado.
o arquivo de objeto compartilhado libapp.so
e define a assinatura do método para o JNI
função:
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("app");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
}
public native String stringFromJNI();
}
Como configurar a ABI de destino
Para configurar a ABI de destino, use a sinalização --android_platforms
da seguinte maneira:
bazel build //:app --android_platforms=comma-separated list of platforms
Assim como a sinalização --platforms
, os valores transmitidos para --android_platforms
são
os rótulos de platform
usando valores de restrição padrão para descrever seu dispositivo.
Por exemplo, para um dispositivo Android com um processador ARM de 64 bits, você definiria em sua plataforma assim:
platform(
name = "android_arm64",
constraint_values = [
"@platforms//os:android",
"@platforms//cpu:arm64",
],
)
Todos os platform
do Android precisam usar o @platforms//os:android
Restrição de SO. Para migrar a restrição de CPU, confira este gráfico:
Valor da CPU | Plataforma |
---|---|
armeabi-v7a |
@platforms//cpu:armv7 |
arm64-v8a |
@platforms//cpu:arm64 |
x86 |
@platforms//cpu:x86_32 |
x86_64 |
@platforms//cpu:x86_64 |
E, é claro, para um APK de multiarquitetura, você passa vários identificadores, por exemplo:
exemplo: --android_platforms=//:arm64,//:x86_64
(supondo que você os tenha definido em
seu arquivo BUILD.bazel
de nível superior).
O Bazel não consegue selecionar uma plataforma Android padrão, então é preciso definir uma e
especificado com --android_platforms
.
Dependendo da revisão do NDK e do nível da API do Android, as seguintes ABIs são disponíveis:
Revisão do NDK | Interfaces binárias de aplicativo (ABIs, na sigla em inglês) |
---|---|
16 e inferior | armeabi, armeabi-v7a, arm64-v8a, mips, mips64, x86, x86_64 |
A partir de 17 anos | armeabi-v7a, arm64-v8a, x86, x86_64 |
Consulte a documentação do NDK para mais informações sobre essas ABIs.
APKs multi-ABI não são recomendados para builds de lançamento, porque eles aumentam o tamanho do APK, mas pode ser útil para builds de desenvolvimento e controle de qualidade.
Como selecionar um padrão C++
Use as seguintes flags para criar de acordo com um padrão C++:
C++ padrão | Sinalização |
---|---|
C++98 | Padrão, sem necessidade de sinalização |
C++11 | --cxxopt=-std=c++11 |
C++14 | --cxxopt=-std=c++14 |
C++17 | --cxxopt=-std=c++17 |
Exemplo:
bazel build //:app --cxxopt=-std=c++11
Leia mais sobre como transmitir flags do compilador e do vinculador com --cxxopt
, --copt
e
--linkopt
no Manual do usuário.
As flags do compilador e do vinculador também podem ser especificadas como atributos no cc_library
.
usando copts
e linkopts
. Exemplo:
cc_library(
name = "jni_lib",
srcs = ["cpp/native-lib.cpp"],
copts = ["-std=c++11"],
linkopts = ["-ldl"], # link against libdl
)
Como criar um cc_library
para Android sem usar android_binary
Para criar um cc_binary
ou cc_library
autônomo para Android sem usar uma
android_binary
, use a sinalização --platforms
.
Por exemplo, supondo que você definiu plataformas Android em
my/platforms/BUILD
:
bazel build //my/cc/jni:target \
--platforms=//my/platforms:x86_64
Com essa abordagem, toda a árvore de build é afetada.
Essas sinalizações podem ser colocadas em uma configuração bazelrc
(uma para cada ABI), em
project/.bazelrc
:
common:android_x86 --platforms=//my/platforms:x86
common:android_armeabi-v7a --platforms=//my/platforms:armeabi-v7a
# In general
common:android_<abi> --platforms=//my/platforms:<abi>
Em seguida, para criar um cc_library
para x86
, por exemplo, execute:
bazel build //my/cc/jni:target --config=android_x86
Em geral, use esse método para metas de baixo nível (como cc_library
) ou quando
você sabe exatamente o que está criando, dependem da configuração automática
transições de android_binary
para destinos de alto nível em que você espera
para criar muitos destinos que não controla.