Soong 构建系统原理
Soong 构建系统原理
非常好的问题!我们来深入解析 AOSP 的 Soong 构建系统,它的编译原理、设计思想以及与传统构建系统的区别。
🌟 一句话总结
Soong 是 Google 为 AOSP 量身打造的下一代构建系统,它使用 Go 语言编写,基于 Ninja 构建引擎,通过
Android.bp文件描述模块依赖和构建规则,目标是替代旧的 Make 系统(Android.mk),实现更快、更清晰、更可维护的系统级编译。
🔧 Soong 的核心组成
| 组件 | 作用 |
|---|---|
soong_ui |
用户接口,替代 make,调用 soong_build |
soong_build (Go) |
Soong 的核心逻辑,解析 Android.bp |
Blueprint |
Soong 的底层框架(由 Google 开发),用于解析 .bp 文件 |
Android.bp |
构建配置文件(类似 JSON 的语法) |
Ninja |
实际执行编译命令的底层引擎 |
Kati |
将旧的 Android.mk 转成 Ninja 规则(兼容层) |
🔄 Soong 的编译流程(原理详解)
✅ 阶段 1:解析阶段(Parse)
1 | m |
执行时,soong_ui 会启动,它做以下事情:
- 扫描整个 AOSP 源码树中的
Android.bp和Android.mk文件 - 将
Android.bp解析成内部的模块结构(Module Graph) - 将
Android.mk通过kati转换为等效的 Soong 模块 - 生成一个巨大的
build.ninja文件
🔍 这个过程类似于:
Android.bp+Android.mk→ Soong 中间表示 →build.ninja
✅ 阶段 2:生成 Ninja 文件
Soong 会生成多个 Ninja 文件:
out/combined_build.ninja:总入口out/soong/build.ninja:由 Soong 生成的规则out/kati/Android.*.ninja:由 kati 从 Android.mk 生成的规则
这些 .ninja 文件定义了:
- 哪些文件需要编译
- 编译命令(如
clang,aapt2,javac) - 输出路径(如
out/target/product/...)
✅ 阶段 3:执行构建(Build)
Ninja 根据 build.ninja 文件,并行执行编译命令:
1 | ninja -f out/combined_build.ninja <target> |
- Ninja 只编译发生变化的文件
- 支持高度并行(
-j参数) - 依赖关系由 Soong 提前计算好
📐 Soong 的核心设计理念
| 特性 | 说明 |
|---|---|
| 🧱 模块化(Modular) | 每个组件(APK、库、可执行文件)都是一个独立模块 |
| 📄 声明式配置(Declarative) | Android.bp 是纯数据文件,不包含逻辑 |
| ⚡ 高性能解析 | Go 编写,比 shell 解析 Makefile 快得多 |
| 🔗 依赖自动分析 | 自动计算模块依赖图,避免循环依赖 |
| 🧩 可扩展性 | 支持自定义模块类型(如 android_app, cc_library) |
| 🔄 增量构建 | 结合 Ninja,只重新编译变化部分 |
📄 Android.bp vs Android.mk
| 特性 | Android.bp (Soong) |
Android.mk (Make) |
|---|---|---|
| 语法 | 类 JSON,声明式 | Makefile,命令式 |
| 可读性 | ✅ 高(结构清晰) | ❌ 低(shell 混杂) |
| 执行速度 | ✅ 快(Go 解析) | ❌ 慢(shell 解析) |
| 逻辑控制 | ❌ 不支持 if/for | ✅ 支持 shell 脚本 |
| 模块依赖 | ✅ 自动分析 | ❌ 手动管理易出错 |
| 扩展性 | ✅ 支持 Blueprint 语法 | ⚠️ 依赖 Make 函数 |
示例对比
Android.bp
1 | android_app { |
Android.mk
1 | LOCAL_PATH := $(call my-dir) |
👉 Android.bp 更简洁、安全、易维护。
🧠 Soong 的“编译原理”本质
Soong 本身 不直接编译代码,它是一个:
构建规则生成器(Build Rule Generator)
它的原理类似于:
1 | [Android.bp] → Soong (Go) → [build.ninja] → Ninja → [调用 clang/aapt2/javac/...] → 最终产物 |
所以:
- Soong 负责 “计划”:谁依赖谁?怎么编译?
- Ninja 负责 “执行”:运行编译命令
- 编译器(clang、javac)负责 “真正编译”
🛠 Soong 支持的模块类型(常见)
| 模块类型 | 用途 |
|---|---|
android_app |
编译 APK(带资源) |
cc_library |
C/C++ 静态库 |
cc_library_shared |
C/C++ 动态库(.so) |
java_library |
Java 源码(.jar) |
java_import |
Java 库(.jar) |
android_library |
Android Java 库(带资源) |
android_library_import |
导入预编译的 .aar |
prebuilt_apk |
导入已编译的 APK |
filegroup |
文件集合 |
🧪 Soong 的优势(为什么 AOSP 要换它?)
| 优势 | 说明 |
|---|---|
| ✅ 更快的解析速度 | Go 比 shell 快 10 倍以上 |
| ✅ 更好的并行构建 | Ninja 天生支持高度并行 |
| ✅ 更清晰的依赖管理 | 模块化设计,避免“Make hell” |
| ✅ 更强的类型检查 | Android.bp 有 schema 验证 |
| ✅ 更容易自动化 | JSON-like 结构,适合工具处理 |
| ✅ 统一构建系统 | 未来完全替代 Make,不再混合 |
🚫 Soong 的局限性
| 限制 | 说明 |
|---|---|
| ❌ 不支持复杂逻辑 | 不能写 if-else 或循环(有意为之) |
| ❌ 宏和变量较少 | 不能像 Make 那样灵活 |
| ❌ 调试困难 | 错误信息有时不直观 |
| ❌ 学习成本 | 需要理解 Blueprint 语法 |
💡 所以 AOSP 仍然保留
Android.mk兼容层(通过kati)
✅ 总结:Soong 编译原理图
1 | +------------------+ +------------------+ +------------------+ |
🛠️ 小技巧:查看 Soong 生成的 Ninja 文件
1 | # 查看生成的 Ninja 文件 |
✅ 一句话收尾
Soong 是 AOSP 的“构建大脑”,它用声明式配置管理千万行代码的依赖关系,再交给 Ninja 这个“执行引擎”高效编译,最终构建出完整的 Android 系统镜像。
如果你是系统开发者,理解 Soong 是掌握 AOSP 编译的关键!
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Fleming's Blog!

