Jika Anda baru menggunakan Bazel, mulailah dengan tutorial Membangun Android dengan Bazel.
Ringkasan
Bazel dapat berjalan di berbagai konfigurasi build yang berbeda, termasuk beberapa yang menggunakan
Toolchain Android Native Development Kit (NDK). Artinya, aturan
cc_library
dan cc_binary
normal dapat dikompilasi untuk Android secara langsung dalam
Bazel. Bazel melakukannya dengan menggunakan aturan repositori
android_ndk_repository
.
Prasyarat
Pastikan Anda telah menginstal Android SDK dan NDK.
Untuk menyiapkan SDK dan NDK, tambahkan cuplikan berikut ke WORKSPACE
Anda:
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.
)
Untuk mengetahui informasi selengkapnya tentang aturan android_ndk_repository
, lihat entri
Ensiklopedia Build.
Jika Anda menggunakan Android NDK versi terbaru (r22 dan yang lebih baru), gunakan
implementasi Starlark dari android_ndk_repository
.
Ikuti petunjuk di
README.
Mulai cepat
Untuk membangun C++ untuk Android, cukup tambahkan dependensi cc_library
ke aturan android_binary
atau android_library
Anda.
Misalnya, dengan file BUILD
berikut untuk aplikasi 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",
)
File BUILD
ini menghasilkan grafik target berikut:
Gambar 1. Membuat grafik project Android dengan dependensi cc_library.
Untuk membuat aplikasi, cukup jalankan:
bazel build //app/src/main:app
Perintah bazel build
mengompilasi file Java, file resource Android, dan
aturan cc_library
, serta memaketkan semuanya menjadi 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
Bazel mengompilasi semua cc_libraries menjadi satu file objek bersama (.so
),
yang ditargetkan untuk ABI armeabi-v7a
secara default. Untuk mengubah setelan ini atau membuat beberapa ABI secara bersamaan, lihat bagian tentang mengonfigurasi ABI target.
Contoh penyiapan
Contoh ini tersedia di repositori contoh Bazel.
Dalam file BUILD.bazel
, tiga target ditentukan dengan aturan android_binary
,
android_library
, dan cc_library
.
Target tingkat atas android_binary
membuat APK.
Target cc_library
berisi satu file sumber C++ dengan implementasi
fungsi JNI:
#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());
}
Target android_library
menentukan sumber Java, file resource, dan
dependensi pada target cc_library
. Dalam contoh ini, MainActivity.java
memuat
file objek bersama libapp.so
, dan menentukan tanda tangan metode untuk fungsi
JNI:
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("app");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
}
public native String stringFromJNI();
}
Mengonfigurasi ABI target
Untuk mengonfigurasi ABI target, gunakan flag --android_platforms
sebagai berikut:
bazel build //:app --android_platforms=comma-separated list of platforms
Sama seperti flag --platforms
, nilai yang diteruskan ke --android_platforms
adalah
label target platform
, yang menggunakan nilai batasan standar untuk mendeskripsikan perangkat Anda.
Misalnya, untuk perangkat Android dengan prosesor ARM 64-bit, Anda harus menentukan platform seperti ini:
platform(
name = "android_arm64",
constraint_values = [
"@platforms//os:android",
"@platforms//cpu:arm64",
],
)
Setiap platform
Android harus menggunakan batasan OS @platforms//os:android
. Untuk memigrasikan batasan CPU, periksa diagram ini:
Nilai CPU | Platform |
---|---|
armeabi-v7a |
@platforms//cpu:armv7 |
arm64-v8a |
@platforms//cpu:arm64 |
x86 |
@platforms//cpu:x86_32 |
x86_64 |
@platforms//cpu:x86_64 |
Tentu saja, untuk APK multi-arsitektur, Anda meneruskan beberapa label, misalnya: --android_platforms=//:arm64,//:x86_64
(dengan asumsi Anda telah menentukannya di
file BUILD.bazel
level teratas).
Bazel tidak dapat memilih platform Android default, sehingga platform tersebut harus ditentukan dan
ditentukan dengan --android_platforms
.
Bergantung pada revisi NDK dan level API Android, ABI berikut ini tersedia:
Revisi NDK | ABI |
---|---|
16 dan yang lebih lama | armeabi, armeabi-v7a, arm64-v8a, mips, mips64, x86, x86_64 |
17 ke atas | armeabi-v7a, arm64-v8a, x86, x86_64 |
Lihat dokumen NDK untuk informasi selengkapnya tentang ABI ini.
APK Lemak Multi-ABI tidak direkomendasikan untuk build rilis karena memperbesar ukuran APK, tetapi dapat berguna untuk pengembangan dan build UM (Uji Mutu).
Memilih standar C++
Gunakan flag berikut untuk membangun sesuai dengan standar C++:
Standar C++ | Bendera |
---|---|
C++98 | Default, tidak perlu tanda |
C++11 | --cxxopt=-std=c++11 |
C++14 | --cxxopt=-std=c++14 |
C++17 | --cxxopt=-std=c++17 |
Contoh:
bazel build //:app --cxxopt=-std=c++11
Baca selengkapnya tentang meneruskan tanda compiler dan penaut dengan --cxxopt
, --copt
, dan
--linkopt
di Panduan Pengguna.
Tanda compiler dan penaut juga dapat ditentukan sebagai atribut di cc_library
menggunakan copts
dan linkopts
. Contoh:
cc_library(
name = "jni_lib",
srcs = ["cpp/native-lib.cpp"],
copts = ["-std=c++11"],
linkopts = ["-ldl"], # link against libdl
)
Membuat cc_library
untuk Android tanpa menggunakan android_binary
Untuk membuat cc_binary
atau cc_library
mandiri untuk Android tanpa menggunakan
android_binary
, gunakan flag --platforms
.
Misalnya, dengan asumsi Anda telah menentukan platform Android di
my/platforms/BUILD
:
bazel build //my/cc/jni:target \
--platforms=//my/platforms:x86_64
Dengan pendekatan ini, seluruh struktur pohon build akan terpengaruh.
Flag ini dapat dimasukkan ke dalam konfigurasi bazelrc
(satu untuk setiap ABI), di
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>
Kemudian, untuk membangun cc_library
untuk x86
, misalnya, jalankan:
bazel build //my/cc/jni:target --config=android_x86
Secara umum, gunakan metode ini untuk target level rendah (seperti cc_library
) atau jika
Anda benar-benar tahu persis apa yang Anda buat; andalkan transisi konfigurasi
otomatis dari android_binary
untuk target level tinggi yang Anda harapkan
untuk membangun banyak target yang tidak Anda kontrol.