Bazel项目中使用Android NDK开发原生代码指南
2025-07-05 07:20:02作者:虞亚竹Luna
概述
Bazel作为一个强大的构建工具,支持多种构建配置,其中包括使用Android Native Development Kit (NDK)工具链的配置。这使得开发者可以直接在Bazel中使用cc_library
和cc_binary
规则为Android平台编译原生代码。本文将详细介绍如何在Bazel项目中集成和使用Android NDK。
准备工作
安装Android SDK和NDK
在开始之前,请确保已经安装了Android SDK和NDK。安装完成后,需要在项目的WORKSPACE
文件中进行配置:
android_sdk_repository(
name = "androidsdk", # 必须使用"androidsdk"作为名称
path = "/path/to/sdk", # 可选,如果设置了ANDROID_HOME环境变量可省略
)
android_ndk_repository(
name = "androidndk", # 必须使用"androidndk"作为名称
path = "/path/to/ndk", # 可选,如果设置了ANDROID_NDK_HOME环境变量可省略
)
注意:如果使用的是NDK r22及以上版本,需要使用Starlark实现的android_ndk_repository
规则。
快速入门
基础集成
在Android应用中集成C++代码非常简单,只需在android_binary
或android_library
规则中添加cc_library
依赖即可。例如:
cc_library(
name = "jni_lib",
srcs = ["cpp/native-lib.cpp"],
)
android_library(
name = "lib",
srcs = ["java/com/example/android/bazel/MainActivity.java"],
deps = [":jni_lib"],
)
android_binary(
name = "app",
deps = [":lib"],
)
构建完成后,Bazel会将所有cc_library
编译成一个共享对象文件(.so),默认针对armeabi-v7a
ABI。
构建命令
构建整个应用只需运行:
bazel build //app/src/main:app
完整示例解析
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());
}
Java层调用
在Java代码中加载原生库并声明native方法:
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("app"); // 注意库名与android_binary目标名一致
}
public native String stringFromJNI();
}
配置目标ABI
平台定义
要为特定ABI构建,需要使用--android_platforms
标志。首先需要定义平台目标:
platform(
name = "android_arm64",
constraint_values = [
"@platforms//os:android",
"@platforms//cpu:arm64",
],
)
构建命令
构建特定ABI的应用:
bazel build //:app --android_platforms=//:android_arm64
支持的ABI
不同NDK版本支持的ABI有所不同:
- NDK 16及以下:armeabi, armeabi-v7a, arm64-v8a, mips, mips64, x86, x86_64
- NDK 17及以上:armeabi-v7a, arm64-v8a, x86, x86_64
C++标准选择
可以通过以下方式指定C++标准:
C++标准 | 构建标志 |
---|---|
C++11 | --cxxopt=-std=c++11 |
C++14 | --cxxopt=-std=c++14 |
C++17 | --cxxopt=-std=c++17 |
也可以在cc_library
规则中直接指定:
cc_library(
name = "jni_lib",
copts = ["-std=c++11"],
)
独立构建C++库
如果不使用android_binary
,可以直接构建cc_library
:
bazel build //my/cc/jni:target --platforms=//my/platforms:x86_64
为了简化构建命令,可以在.bazelrc
中配置预设:
common:android_x86 --platforms=//my/platforms:x86
common:android_armeabi-v7a --platforms=//my/platforms:armeabi-v7a
然后通过--config
参数使用:
bazel build //my/cc/jni:target --config=android_x86
最佳实践建议
- 对于简单的JNI调用,推荐使用
android_binary
自动处理依赖关系 - 发布版本应避免使用多ABI的Fat APK以减少包体积
- 低层库或明确知道构建内容时,可以使用独立构建方式
- 在团队协作项目中,建议将平台定义和构建配置统一管理
通过本文介绍的方法,开发者可以灵活地在Bazel项目中集成Android NDK,构建高性能的原生代码组件。