Android.bp 文件编写
一、核心概念:从 Make 到 Soong
背景
- Android.mk: 用于 Android 7.0 (Nougat) 之前,基于 GNU Make。
- Android.bp : 用于 Android 7.0 及之后,旨在取代 Android.mk,基于 Soong 构建系统。
- 目的 : 解决 Make 构建系统在大型项目中的缓慢、易错、难以扩展和测试的问题。
Soong 构建系统
- 定义 : Soong 是专为 Android 构建设计的新系统,利用 Kati (Make 克隆工具) 和 Ninja (构建系统组件) 来加速构建过程。
- 优点: 提供更好的并发处理能力和灵活性。
二、Android.bp 文件格式与语法
基本结构
-
模块化 : 文件由模块组成,每个模块以模块类型 开头,后跟一组
name: "value"格式的属性。 -
示例 :
bpcc_binary { name: "gzip", srcs: ["src/test/minigzip.c"], shared_libs: ["libz"], stl: "none", } -
强制属性 : 每个模块必须 有
name属性,且该值在所有Android.bp文件中必须唯一。
数据类型
属性是强类型的,支持以下类型:
- 布尔值 :
true或false - 整数 :
int - 字符串 :
"string" - 字符串列表 :
["string1", "string2"] - 映射 :
{key1: "value1", key2: ["value2"]}- 值可以是任何类型,包括嵌套映射。
- 列表和映射的最后一个值后可以有一个终止逗号。
常用语法元素
-
Glob 模式 : 用于匹配文件(如
srcs属性)。*: 普通通配符,如*.java。**: 匹配零个或多个路径元素,如java/**/*.java匹配java/Main.java和java/com/android/Main.java。
-
变量: 支持顶级变量赋值。
bpgzip_srcs = ["src/test/minigzip.c"], cc_binary { name: "gzip", srcs: gzip_srcs, // 使用变量 // ... } -
注释 : 支持 C 风格多行
/* */和 C++ 风格单行//注释。 -
运算符 : 使用
+运算符来附加字符串、字符串列表和映射。对整数求和。附加映射会合并键,并附加重复键的值。 -
条件语句 (限制) : Android.bp 本身不支持条件语句 (如
if)。复杂条件逻辑在 Soong 的 Go 语言层处理。在 bp 文件中,通常使用映射属性来实现条件选择。bpcc_library { srcs: ["generic.cpp"], arch: { arm: { srcs: ["arm.cpp"], }, x86: { srcs: ["x86.cpp"], }, }, }
三、关键机制与模块类型
1. 默认模块 (xx_defaults)
-
作用: 定义一组可被其他模块继承的通用属性,避免重复书写,提高可维护性。
-
类型 :
cc_defaults,java_defaults,doc_defaults,stubs_defaults等。 -
用法 : 通过
defaults: [":default_module_name"]继承。 -
示例 :
bpcc_defaults { name: "gzip_defaults", shared_libs: ["libz"], stl: "none", } cc_binary { name: "gzip", defaults: ["gzip_defaults"], // 继承上面的属性 srcs: ["src/test/minigzip.c"], // 然后添加自己特有的属性 }
2. 依赖管理
-
引入第三方 JAR :
bpjava_import { name: "CarServicelib.jar", // 模块名 jars: ["libs/CarServicelib.jar"], // JAR文件路径 } android_app { // ... static_libs: [ "CarServicelib.jar" ], // 依赖上面定义的模块 } -
引入 AndroidX 库 :
bpandroid_app { // ... static_libs: [ "androidx.cardview_cardview", "androidx.recyclerview_recyclerview", "androidx-constraintlayout_constraintlayout" ], }
四、常用模块属性详解
以下是一些在构建 Android 应用和库时极其常用的属性:
| 属性 | 适用模块类型 | 说明 | 示例 |
|---|---|---|---|
name |
全部 | 模块的唯一标识符,强制属性。 | name: "MyApp" |
srcs |
cc_*, java_*, android_app |
源文件列表。可使用 glob 模式。 | srcs: ["src/**/*.java"] |
resource_dirs |
android_app |
资源文件目录(res, assets 等)。 | resource_dirs: ["res"] |
static_libs |
android_app, java_library |
依赖的静态库(包括引入的库如 AndroidX)。 | static_libs: ["androidx.appcompat_appcompat"] |
shared_libs |
cc_*, android_app |
依赖的共享(动态)库。 | shared_libs: ["liblog"] |
cflags/cppflags |
cc_* |
C/C++ 编译器标志。 | cflags: ["-Wall", "-Werror"] |
javacflags |
java_* |
Java 编译器标志。 | javacflags: ["-Xlint:unchecked"] |
certificate |
android_app |
指定签名证书。 | certificate: "platform" (系统签名) |
privileged |
android_app |
标记为特权应用(需要签名和配置)。 | privileged: true |
platform_apis |
android_app |
使用系统隐藏 API(而非 SDK)。 | platform_apis: true |
product_specific |
android_app |
APK 将被安装到 product 分区。 | product_specific: true |
dex_preopt |
android_app |
控制 DEX 预优化,影响启动速度。 | dex_preopt: { enabled: false } |
defaults |
全部 | 继承一个默认模块的配置。 | defaults: ["my_defaults"] |
五、模块编译实例
1. 编译可执行程序 (C/C++)
bp
cc_binary {
name: "my_native_tool", // 生成的可执行文件名称
srcs: ["src/main.c", "src/utils.c"],
shared_libs: ["liblog", "libcutils"], // 依赖的动态库
cflags: ["-Wall", "-Werror"],
vendor: true, // 可选,标识为 vendor 模块
}
2. 编译无源码 APK (预编译)
bp
android_app {
name: "PrebuiltApp",
srcs: ["app/PrebuiltApp.apk"], // 直接指向预编译的APK文件
certificate: "platform", // 指定签名方式
privileged: true, // 如果是特权应用
product_specific: true, // 指定安装分区
// 通常不需要 resource_dirs 和 static_libs
}
3. 编译有源码 APK
bp
android_app {
name: "CarDialerApp", // 生成的APK名称
srcs: ["src/**/*.java"], // Java源代码
resource_dirs: ["res"], // 资源目录
platform_apis: true, // 使用系统隐藏API
certificate: "platform", // 系统平台签名
// 依赖的静态库(包括AndroidX和自己项目的库)
static_libs: [
"androidx.recyclerview_recyclerview",
"androidx.cardview_cardview",
"car-ui-lib",
"my-common-library", // 假设的自定义库
],
// 覆盖系统中已有的同名应用
overrides: ["Dialer"],
}