如果您是第一次使用 Bazel,請先從使用 Bazel 教學課程。
總覽
Bazel 可在許多不同的建構設定中執行,包括使用
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
規則,請參閱「建構
百科全書入口。
如果您使用的是最新版 Android NDK (r22 以上版本),請使用
android_ndk_repository
的 Starlark 實作。
請遵循指示:
其讀物。
快速入門
如要建構 Android 適用的 C++,只要將 cc_library
依附元件新增至
android_binary
或 android_library
規則。
以下列 Android 應用程式專用 BUILD
檔案為例:
# 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. 使用 cc_library 依附元件的 Android 專案建構圖表。
如要建構應用程式,只要執行:
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.MF
Bazel 會將所有 cc_libraries 編譯成單一共用物件 (.so
) 檔案,
預設會指定 armeabi-v7a
ABI。如要變更此類別,或是針對
同時參閱「設定目標
ABI。
設定範例
在 BUILD.bazel
檔案中,android_binary
定義了三個目標,
android_library
和 cc_library
規則
android_binary
頂層目標會建構 APK。
cc_library
目標包含具有 JNI 函式的單一 C++ 來源檔案
實作:
#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 來源、資源檔案和
依附於 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
和 --platforms
旗標一樣,傳遞至 --android_platforms
的值是
platform
的標籤
標準限制值描述您的裝置。
舉例來說,如果 Android 裝置搭載 64 位元 ARM 處理器,您就必須 例如:
platform(
name = "android_arm64",
constraint_values = [
"@platforms//os:android",
"@platforms//cpu:arm64",
],
)
所有 Android platform
都應使用 @platforms//os:android
OS 限制。如要遷移 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 平台,
使用 --android_platforms
來指定。
根據 NDK 修訂版本和 Android API 級別,下列 ABI 如下: 可使用:
NDK 修訂版本 | ABI |
---|---|
16 以下 | armeabi、armeabi-v7a、arm64-v8a、mips、mips64、x86、x86_64 |
17 以上版本 | armeabi-v7a、arm64-v8a、x86、x86_64 |
請參閱 NDK 說明文件 ,進一步瞭解這些 ABI。
我們不建議對發布子版本使用多重 ABI Fat APK,因為這類 APK 會增加 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
)
在不使用 android_binary
的情況下,為 Android 建構 cc_library
為 Android 建構獨立的 cc_binary
或 cc_library
,但不使用
android_binary
,請使用 --platforms
旗標。
舉例來說,假設您已在
my/platforms/BUILD
:
bazel build //my/cc/jni:target \
--platforms=//my/platforms:x86_64
使用這個方法時,整個建構樹狀結構都會受到影響。
這些旗標可放入 bazelrc
設定 (每個 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>
接著,如要為 x86
建構 cc_library
,請執行:
bazel build //my/cc/jni:target --config=android_x86
一般來說,這個方法適用於低層級目標 (例如 cc_library
),或
確切知道要建構什麼內容仰賴自動設定
將超出 android_binary
的層級用於預期成效目標
建立很多您無法控管的目標