หากคุณเพิ่งเคยใช้ Bazel โปรดเริ่มต้นด้วยบทแนะนำการสร้าง Android ด้วย Bazel
ภาพรวม
Bazel สามารถทำงานในการกำหนดค่าการสร้างที่แตกต่างกันได้มากมาย รวมถึงการกำหนดค่าหลายรายการที่ใช้ชุดเครื่องมือ (Toolchain) ของ Android Native Development Kit (NDK) ซึ่งหมายความว่ากฎ cc_library และ cc_binary ปกติสามารถคอมไพล์สำหรับ Android ได้โดยตรงภายใน Bazel Bazel ทำได้โดยใช้กฎที่เก็บ android_ndk_repository
ข้อกำหนดเบื้องต้น
โปรดตรวจสอบว่าคุณได้ติดตั้ง Android SDK และ NDK แล้ว
หากต้องการตั้งค่า SDK และ NDK ให้เพิ่มข้อมูลโค้ดต่อไปนี้ลงใน 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.
)
ดูข้อมูลเพิ่มเติมเกี่ยวกับกฎ android_ndk_repository ได้ที่รายการ Build
Encyclopedia
หากคุณใช้ Android NDK เวอร์ชันล่าสุด (r22 ขึ้นไป) ให้ใช้การติดตั้งใช้งาน Starlark ของ android_ndk_repository
และทำตามวิธีการใน
ไฟล์ README
การเริ่มใช้งานอย่างง่าย
หากต้องการสร้าง C++ สำหรับ Android เพียงเพิ่มทรัพยากร Dependency cc_library ลงในกฎ android_binary หรือ android_library
ตัวอย่างเช่น หากมีไฟล์ BUILD ต่อไปนี้สำหรับแอป 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",
)
ไฟล์ BUILD นี้จะสร้างกราฟเป้าหมายต่อไปนี้

รูปที่ 1 สร้างกราฟของโปรเจ็กต์ Android ที่มีทรัพยากร Dependency cc_library
หากต้องการสร้างแอป เพียงเรียกใช้คำสั่งต่อไปนี้
bazel build //app/src/main:appคำสั่ง bazel build จะคอมไพล์ไฟล์ Java, ไฟล์ทรัพยากร Android และกฎ cc_library แล้วแพ็กทุกอย่างลงใน 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.MFBazel จะคอมไพล์ cc_libraries ทั้งหมดลงในไฟล์ออบเจ็กต์ที่แชร์ (.so) ไฟล์เดียว ซึ่งกำหนดเป้าหมายเป็น ABI armeabi-v7a โดยค่าเริ่มต้น หากต้องการเปลี่ยนค่านี้หรือสร้างสำหรับ
ABI หลายรายการพร้อมกัน โปรดดูส่วนเกี่ยวกับ การกำหนดค่า ABI
เป้าหมาย
ตัวอย่างการตั้งค่า
ตัวอย่างนี้มีอยู่ในที่เก็บตัวอย่างของ Bazel
ในไฟล์ BUILD.bazel มีการกำหนดเป้าหมาย 3 รายการด้วยกฎ android_binary, android_library และ cc_library
เป้าหมายระดับบนสุด android_binary จะสร้าง APK
เป้าหมาย cc_library มีไฟล์แหล่งที่มา C++ ไฟล์เดียวที่มีการติดตั้งใช้งานฟังก์ชัน 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());
}
เป้าหมาย android_library จะระบุแหล่งที่มา Java, ไฟล์ทรัพยากร และทรัพยากร Dependency ในเป้าหมาย cc_library สำหรับตัวอย่างนี้ MainActivity.java จะโหลดไฟล์ออบเจ็กต์ที่แชร์ libapp.so และกำหนดลายเซ็นเมธอดสำหรับฟังก์ชัน JNI
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("app");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
}
public native String stringFromJNI();
}
การกำหนดค่า ABI เป้าหมาย
หากต้องการกำหนดค่า ABI เป้าหมาย ให้ใช้แฟล็ก --android_platforms ดังนี้
bazel build //:app --android_platforms=comma-separated list of platformsค่าที่ส่งไปยัง --android_platforms จะเป็นป้ายกำกับของ platform เป้าหมาย โดยใช้ค่าข้อจำกัดมาตรฐานเพื่ออธิบายอุปกรณ์ เช่นเดียวกับแฟล็ก --platforms
ตัวอย่างเช่น สำหรับอุปกรณ์ Android ที่มีโปรเซสเซอร์ ARM 64 บิต คุณจะต้องกำหนดแพลตฟอร์มดังนี้
platform(
name = "android_arm64",
constraint_values = [
"@platforms//os:android",
"@platforms//cpu:arm64",
],
)
Android ทุกรายการควรใช้ข้อจำกัดระบบปฏิบัติการ platform@platforms//os:android หากต้องการย้ายข้อมูลข้อจำกัด CPU ให้ดูแผนภูมินี้
| ค่า CPU | แพลตฟอร์ม |
|---|---|
armeabi-v7a |
@platforms//cpu:armv7 |
arm64-v8a |
@platforms//cpu:arm64 |
x86 |
@platforms//cpu:x86_32 |
x86_64 |
@platforms//cpu:x86_64 |
และแน่นอนว่าสำหรับ APK แบบหลายสถาปัตยกรรม คุณจะต้องส่งป้ายกำกับหลายรายการ เช่น --android_platforms=//:arm64,//:x86_64 (สมมติว่าคุณกำหนดป้ายกำกับเหล่านั้นไว้ในไฟล์ BUILD.bazel ระดับบนสุด)
Bazel ไม่สามารถเลือกแพลตฟอร์ม Android เริ่มต้นได้ คุณจึงต้องกำหนดและระบุแพลตฟอร์มด้วย --android_platforms
ABI ต่อไปนี้พร้อมใช้งาน ทั้งนี้ขึ้นอยู่กับการแก้ไข NDK และระดับ API ของ Android
| การแก้ไข NDK | ABI |
|---|---|
| 16 และต่ำกว่า | armeabi, armeabi-v7a, arm64-v8a, mips, mips64, x86, x86_64 |
| 17 ขึ้นไป | armeabi-v7a, arm64-v8a, x86, x86_64 |
ดูข้อมูลเพิ่มเติมเกี่ยวกับ ABI เหล่านี้ได้ในเอกสารประกอบของ NDK
เราไม่แนะนำให้ใช้ APK แบบ Fat ที่มีหลาย ABI สำหรับบิลด์ที่เผยแพร่ เนื่องจากจะเพิ่มขนาดของ APK แต่ก็อาจมีประโยชน์สำหรับบิลด์การพัฒนาและการประกันคุณภาพ
การเลือกมาตรฐาน C++
ใช้แฟล็กต่อไปนี้เพื่อสร้างตามมาตรฐาน C++
| มาตรฐาน C++ | แฟล็ก |
|---|---|
| C++98 | ค่าเริ่มต้น ไม่ต้องใช้แฟล็ก |
| C++11 | --cxxopt=-std=c++11 |
| C++14 | --cxxopt=-std=c++14 |
| C++17 | --cxxopt=-std=c++17 |
เช่น
bazel build //:app --cxxopt=-std=c++11อ่านเพิ่มเติมเกี่ยวกับการส่งแฟล็กคอมไพเลอร์และลิงเกอร์ด้วย --cxxopt, --copt และ
--linkopt ใน คู่มือผู้ใช้
นอกจากนี้ คุณยังระบุแฟล็กคอมไพเลอร์และลิงเกอร์เป็นแอตทริบิวต์ใน cc_library ได้โดยใช้ copts และ linkopts เช่น
cc_library(
name = "jni_lib",
srcs = ["cpp/native-lib.cpp"],
copts = ["-std=c++11"],
linkopts = ["-ldl"], # link against libdl
)
การสร้าง cc_library สำหรับ Android โดยไม่ใช้ android_binary
หากต้องการสร้าง cc_binary หรือ cc_library แบบสแตนด์อโลนสำหรับ Android โดยไม่ใช้ android_binary ให้ใช้แฟล็ก --platforms
ตัวอย่างเช่น สมมติว่าคุณได้กำหนดแพลตฟอร์ม Android ไว้ใน my/platforms/BUILD
bazel build //my/cc/jni:target \
--platforms=//my/platforms:x86_64แนวทางนี้จะส่งผลต่อทั้งทรีการสร้าง
คุณสามารถใส่แฟล็กเหล่านี้ลงในการกำหนดค่า bazelrc (รายการละ 1 รายการสำหรับแต่ละ ABI) ใน
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>
จากนั้นหากต้องการสร้าง cc_library สำหรับ x86 ให้เรียกใช้คำสั่งต่อไปนี้
bazel build //my/cc/jni:target --config=android_x86โดยทั่วไป ให้ใช้วิธีนี้กับเป้าหมายระดับล่าง (เช่น cc_library) หรือเมื่อคุณทราบแน่ชัดว่ากำลังสร้างอะไรอยู่ ให้ใช้การเปลี่ยนการกำหนดค่าอัตโนมัติจาก android_binary สำหรับเป้าหมายระดับสูงที่คุณคาดว่าจะสร้างเป้าหมายจำนวนมากที่คุณควบคุมไม่ได้