7、编译命令详解:lunch、make、m/mm/mmm/mma、编译产物分析
编译命令,说白了就是你和构建系统对话的方式。我刚入行那会儿,面对一长串命令完全懵圈——lunch 是干嘛的?m 和 mm 有什么区别?编译完那一堆文件哪些是我要的?
今天咱们就把这些命令掰开揉碎,一个个讲清楚。
7.1 lunch:选目标,定乾坤
lunch 是编译的第一步。它的作用很简单——告诉系统:你要给哪个设备编译?什么版本?
执行 lunch 后,你会看到类似这样的输出:
$ lunch
You're building on Linux
Lunch menu... pick a combo:
1. aosp_arm-eng
2. aosp_arm64-eng
3. aosp_x86_64-eng
4. aosp_car_x86_64-userdebug
5. aosp_husky-userdebug
...
选一个编号,或者直接传参数:
$ lunch aosp_husky-userdebug
这里 aosp_husky 是设备名,userdebug 是构建类型。构建类型有三种:
| 类型 | 说明 | 适用场景 |
|---|---|---|
| eng | 工程版,带 root 和调试工具 | 开发调试 |
| userdebug | 用户调试版,有 root 但更接近正式版 | 测试、性能分析 |
| user | 用户版,无 root,有签名保护 | 正式发布 |
7.2 make:全量编译,简单粗暴
make 是最基础的编译命令。不加参数就是编译整个系统:
$ make -j16
-j16 表示用 16 个线程并行编译。这个数字怎么定?我一般设成 CPU 核心数的两倍。比如 8 核机器就用 -j16。
你也可以指定编译某个模块:
$ make framework
$ make libcamera_client
但 make 有个问题——它每次都会重新解析整个构建系统,光解析就要花几十秒。所以后来 Google 推出了更快的命令。
7.3 m / mm / mmm / mma:模块编译四兄弟
这四个命令是 Android 构建系统的精华。我一个个说。
m:从根目录编译
m 相当于 make,但更快。它不需要重新 source 环境变量:
$ m framework
m 会自动找到 Android 根目录,然后编译指定模块。我个人最常用这个。
mm:编译当前目录模块
mm 只编译你当前所在的模块目录。比如你在 frameworks/base/ 下:
$ mm
它只会编译 frameworks/base 这个模块,及其依赖。速度极快,适合改了一两个文件后快速验证。
mmm:编译指定目录
mmm 可以指定任意路径:
$ mmm frameworks/base/services/core
这个命令我经常用来编译某个子目录下的模块,不用 cd 过去。
mma:编译当前目录及依赖
mma 是 mm 的增强版。它会检查当前模块依赖的所有模块,一并编译:
$ mma
我曾经踩过一个坑:改了 AIDL 接口,用 mm 编译,结果运行时崩溃——因为依赖的模块没更新。后来我就改用 mma 了。
7.4 编译产物分析
编译完,东西都放在 out/ 目录下。我带你看看关键文件:
out/
├── target/
│ └── product/
│ └── husky/
│ ├── system.img # 系统镜像
│ ├── vendor.img # 厂商镜像
│ ├── boot.img # 内核+ramdisk
│ ├── userdata.img # 用户数据分区
│ ├── ramdisk.img # 启动 ramdisk
│ ├── obj/ # 中间产物(.o .so .dex)
│ └── symbols/ # 带符号表的 so 文件
└── host/ # 主机工具
└── linux-x86/
└── bin/ # adb、fastboot 等
几个重点:
- system.img:Android 系统核心,包含 framework、app、库文件
- vendor.img:厂商定制部分,驱动、HAL 等
- boot.img:Linux 内核 + 启动 ramdisk
- obj/:编译中间产物,调试时很有用
- symbols/:带符号表的 so 文件,分析 crash 日志必备
7.5 核心流程 SVG 图
下面这张图总结了编译命令的选择逻辑:
7.6 实用技巧总结
最后分享几个我日常用的命令组合:
# 快速编译 framework 并生成 system.img
$ m framework
$ make systemimage
# 只编译某个模块并打包 vendor
$ mmm vendor/google/xxx
$ make vendorimage
# 编译并生成刷机包
$ m -j16
$ make otapackage # 生成 update.zip
编译命令就这些。记住一个原则:小改用 mm,中改用 mma,大改用 m。别一上来就全量编译,浪费时间。也别太自信只用 mm,漏了依赖编译——我吃过这个亏。
公众号:蓝海资料掘金营,微信deep3321