第3章 Makefile/SOONG构建系统错误:Kati/Ninja执行失败、错误日志关键行定位
核心故障现象:AOSP构建过程中,Kati或Ninja进程异常中止,终端输出类似
ninja: build stopped: subcommand failed、kati: *** missing separator或ninja: error: 'path/to/target' missing and no known rule to make it。构建立即退出,不生成最终镜像。
3.1 现象识别
Kati与Ninja是AOSP构建系统的两层执行引擎:Kati将Makefile转换为Ninja文件,Ninja负责任务调度与并行执行。任何一层失败都会导致构建中断。典型错误表现:
- Kati阶段:输出
*** missing separator、*** missing target、*** failed to read inputs。 - Ninja阶段:输出
FAILED: …,随后跟具体的编译/链接命令和退出码,最终ninja: build stopped: subcommand failed。 - 混合模式:先报SOONG配置解析错误,再导致Ninja未生成正确构建图。
确认错误阶段的方法:查看构建日志的前几行——若在[ 1/ 12] …之前就报错,通常是Kati失败;若已经出现大量[ 1/ 500]后才中断,则是Ninja执行中的子任务失败。
3.2 数据采集
定位关键行需要以下核心数据源:
| 数据源 | 路径/命令 | 关键内容 |
|---|---|---|
| 构建标准错误输出 | 终端直接重定向 | Kati/Ninja错误消息,含行号、文件名 |
out/build.log |
tail -200 out/build.log |
完整构建记录,含失败命令的完整参数 |
out/build_error.log |
自动生成(部分AOSP版本) | 仅错误行,便于快速扫描 |
| 详细输出模式 | make showcommands 2>&1 | tee build.log |
显示每个子进程的完整命令行 |
采集技巧:若错误信息过长被截断,使用
ninja -v -j1 target 2>&1逐步运行,可避免并行日志混乱。
3.3 原因定位
使用故障树分析法(Fault Tree Analysis)从失败关键行逐步回溯:
根据故障树,定位时使用以下判断规则表:
| 关键行模式 | 所属分支 | 下一步动作 |
|---|---|---|
*** missing separator / *** missing target |
Kati解析错误 | 检查对应Makefile的冒号、制表符 |
ninja: error: '…' missing and no known rule |
Ninja子任务失败 | 确认该文件是否在.mk中注册 |
FAILED: … clang … exit code 1 |
Ninja子任务失败 | 分析编译器错误输出(如未定义引用) |
soong_build: error: … undefined variable |
SOONG配置异常 | 检查Android.bp或boardconfig.mk |
3.4 修复动作
根据定位到的根因执行对应修复:
- Makefile语法错误:使用
kati -C解析特定Makefile,查看具体行。修复空格/制表符混合、漏掉的变量定义。--ninja - 依赖缺失:安装对应库(如
sudo apt install libncurses5-dev)或通过PRODUCT_PACKAGES添加缺失模块。 - 编译器错误:根据失败命令的完整
stderr,修复源码错误或更新工具链(如使用export CC=clang-14)。 - SOONG配置冲突:检查
userspace_*、vendor_*路径是否重复,或TARGET_PRODUCT与target_board_common.mk不匹配。 - 资源不足:增加swap、清理
out/目录、降低并行度(make -j4)。
3.5 复测
修复后执行:
make clean && source build/envsetup.sh && lunch aosp_cf_x86_64_phone-userdebug && make -j8 2>&1 | tee rebuild.log
观察新日志中是否不再出现原错误关键行。若仍有其他错误,重复数据采集 → 原因定位循环。对于Ninja部分失败,可只重新构建受影响模块:
mma -j8 2>&1 | tail -50
注意:不要盲目执行
make clean,除非确认缓存导致问题;优先只清理单个模块的中间文件(rm -rf out/target/product/<device>/obj/<module>)。
3.6 预防
建立以下实践减少此类错误发生:
- Makefile规范性检查:在CI中集成
kati --lint,禁止制表符与空格混用。 - 构建环境标准化:使用Docker/Cuttlefish固定编译器版本、Ninja版本(≥1.10)。
- 增量构建隔离:为每个功能分支创建独立
out/目录,避免并行构建冲突。 - 日志保留策略:始终保留
out/build.log,并在失败时自动上传至分析系统。 - 依赖声明完整:在
Android.bp中使用shared_libs、static_libs正确列出所有外部模块。
经验口诀:
Kati报错查语法,Ninja挂掉找依赖;
SOONG配置看目标,日志关键行是路牌。
Kati报错查语法,Ninja挂掉找依赖;
SOONG配置看目标,日志关键行是路牌。