首页
/ Bazel项目中使用Android NDK开发原生代码指南

Bazel项目中使用Android NDK开发原生代码指南

2025-07-05 07:20:02作者:虞亚竹Luna

概述

Bazel作为一个强大的构建工具,支持多种构建配置,其中包括使用Android Native Development Kit (NDK)工具链的配置。这使得开发者可以直接在Bazel中使用cc_librarycc_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_binaryandroid_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

最佳实践建议

  1. 对于简单的JNI调用,推荐使用android_binary自动处理依赖关系
  2. 发布版本应避免使用多ABI的Fat APK以减少包体积
  3. 低层库或明确知道构建内容时,可以使用独立构建方式
  4. 在团队协作项目中,建议将平台定义和构建配置统一管理

通过本文介绍的方法,开发者可以灵活地在Bazel项目中集成Android NDK,构建高性能的原生代码组件。