1. 简介
从 Android 7 开始,Android 源码编译时默认使用 Ninja,编译时,会先把 makefile 和 bp 转换成 ninja 再进行编译。这个转换过程非常慢(需要遍历处理所有关联的 makefile、bp 文件),即使只是通过 mm 或 mmm 编译某个模块,也会有很多因素触发 ninja 文件的重新生成,而这对基于源码开发的模块很不友好,编译好慢!
2. 初识 ninja
AOSP 在源码中已经内置了一个 ninja 执行文件,路径为:./prebuilts/build-tools/linux-x86/bin/ninja
我们先看看它的 help:
| 1 | ➜ ~ ./prebuilts/build-tools/linux-x86/bin/ninja -h | 
简单使用的话,我们关注它的两个参数就行了
- -f:这个参数指定的就是输入文件,也就是 makefile 和 bp 转换后的 ninja 文件,一般位于- ./out目录,后面会说
- targets:目标,这个和 makefile 是类似的,就是我们最终需要的产物,例如:Launcher3QuickStep、SystemUI。那么这些 targets 名是哪里定义的呢?要知道对应模块的对应的 target 名,只需要:- 若模块使用的是 Android.mk:查找 LOCAL_PACKAGE_NAME或LOCAL_MODULE等对应的值
- 若模块使用的是 Android.bp:查找 module 中 name 对应的值
 
- 若模块使用的是 Android.mk:查找 
举个栗子:
| 1 | ➜ android-10.0.0_r11 ./prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-aosp_walleye.ninja Launcher3QuickStep | 
就这样,不需要通过 mm 或者 mmm 命令,目标产物同样生成了。我们看看耗时:
| 1 | ➜ android-10.0.0_r11 time ./prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-aosp_walleye.ninja Launcher3QuickStep | 
可以看到,整个编译在 18s 完成了,相比动辄七八分钟的 mmm,效率提升还是很可观的。
3. 注意事项
虽然 ninja 很方便,但要用它来编译单个模块,还是有一些限制和注意事项的:
- 使用前需把对应模块编译一遍,用于生产 ninja 文件(全编或 mmm都可以)
- 全编后,生成的 ninja 文件为:./out/combined-[TARGET-PRODUCT].ninja
- mmm编译后,生成的 ninja 文件为:- ./out/combined-[TARGET-PRODUCT]-_[path_to_your_module_makefile].ninja,比如:- ./out/combined-aosp_walleye-_packages_apps_Launcher3_Android.mk.ninja
- 如果修改了 Android.mk 或 Android.bp,需使用传统的 make 命令进行编译以重新生成包含新依赖规则的 ninja 文件
- 可以把 ninja 放到 PATH 环境变量中,这样就不用每次都敲 ./prebuilts/build-tools/linux-x86/bin/ninja 这个路径了
4. 最后
为 Launcher 和 SystemUI 准备一份开箱即用的指令,尽情玩耍吧~
Launcher:
| 1 | ./prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-qssi-_packages_apps_Launcher3_Android.mk.ninja Launcher3QuickStep | 
SystemUI:
| 1 | ./prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-qssi-_frameworks_base_packages_SystemUI_Android.mk.ninja SystemUI | 
