简介:面向安卓底层开发与嵌入式工程师的MT6799开发板源码编译实战笔记,聚焦Ubuntu 16.04环境下安卓7.0(Nougat,兼顾4.4)的下载与编译流程。资源为单份Word文档,体积约895KB,内容涵盖虚拟机环境搭建、软件源替换、共享文件夹配置、依赖工具安装、推荐编译指令及高频报错排查,结构清晰,可按步骤对照操作。已有633人浏览学习。文档不仅给出从源码解压到执行编译的完整操作链路,还针对平台变量未定义、构建子任务失败、内存不足三类编译报错提供具体原因与解决思路,可帮助初学者避开环境配置和内存不足等常见坑点。文中对备份源列表、添加阿里云源与更新源等命令示例,对共享目录建立、内存和处理器核心数的配置都有说明,能让刚接触MT6799平台的开发者更快搭建可用的编译环境。
1. MT6799 Android 源码编译:最容易被环境拖死的两件事
MT6799 开发板的 Android Source code 下载和编译,是所有拿到这套板子的人绕不开的第一步。Android Nougat 7.0 源码在 Ubuntu 16.04.5 虚拟机里编,环境对了就只是时间问题,环境不对就是连环报错:TAREGT_BRM_PLATFORM is undefined、ninja_wrapper failed、fatal: fork: Cannot allocate memory,随便一个都能卡住半天。我这次重新装 VMware 15.5,把 16G 内存、2 处理器 2 核心、300G 硬盘的虚拟机从头配了一遍,最后能稳定编出 systemimage。这篇文章按当时实际操作顺序记录,重点交代哪些参数必须手动改,哪些报错可以暂时忽略,适合正在折腾 MT6799 编译环境、又不太愿意把源码解压三遍的人。
2. 虚拟机环境:软件源、共享文件夹和 VMware 15.5 的选型
如果只是拿现成镜像,虚拟机配置可能不用太讲究。但 MT6799 的 Android Nougat 7.0 源码解压后接近几十 G,编译输出还要占一份空间,随便给个 8G 内存的小虚拟机,make 跑到一半就会被 Linux 的 OOM 机制杀掉。这一章先把宿主机侧和虚拟机侧的环境固定下来:Ubuntu 16.04.5 桌面版、VMware 15.5、内存 16G、处理器 2 核 2 线程、硬盘 300G。下面的配置顺序是我反复试过比较顺畅的,每一步都有目的。
2.1 修改 Ubuntu 软件源:阿里源这样配最省事
Ubuntu 16.04 默认的源在国外,apt-get update 经常等半天,装依赖的时候很容易超时。换源这个操作看起来简单,最容易翻车的是把新源追加到旧源后面造成重复,或者把 xenial 写成 bionic。我的做法是先把原始 sources.list 备份,再打开编辑:
sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup sudo gedit /etc/apt/sources.list备份路径放在同目录下,后缀 .backup,以后想恢复只要把备份文件覆盖回去。gedit 是 Ubuntu 16.04 桌面版自带的编辑器,如果你用的是服务器版没有图形界面,把最后一句换成 vim、nano 都行,关键是保证文件以 UTF-8 无 BOM 保存,否则 apt 会 warnings。
在文件末尾追加阿里云源时,我直接用了下面的完整块:
deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted deb-src http://mirrors.aliyun.com/ubuntu/ xenial main restricted multiverse universe deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted multiverse universe deb http://mirrors.aliyun.com/ubuntu/ xenial universe deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe deb http://mirrors.aliyun.com/ubuntu/ xenial multiverse deb http://mirrors.aliyun.com/ubuntu/ xenial-updates multiverse deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse deb http://archive.canonical.com/ubuntu xenial partner deb-src http://archive.canonical.com/ubuntu xenial partner deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted multiverse universe deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe deb http://mirrors.aliyun.com/ubuntu/ xenial-security multiverse这里出现 xenial 是因为 Ubuntu 16.04 的代号就是 xenial,updates 对应软件更新,security 对应安全更新,backports 是后移包。deb-src 是源码索引,Android 编译有些库需要自己拉源码检查时用得到,建议别省。写完保存后执行:
sudo apt-get updateupdate 只是更新索引,不需要太长时间。如果看到 “Hit” 和 “Get” 说明源连通正常,如果出现 “404 Not Found” 或 “NO_PUBKEY”,多半是源列表里有空格或换行问题,回头检查文件尾部有没有粘贴时弄乱的注释。
2.2 VMware Tools 共享文件夹:压缩包必须拷到 Linux 里解压
源码包在宿主机 Windows 上,虚拟机里要读到它,最常规的做法是 VMware 的共享文件夹,挂载点一般是 /mnt/hgfs。很多人习惯直接在 /mnt/hgfs 下解压源码,这个是血泪教训:共享文件夹走的是 vmhgfs 文件系统,解压大量小文件时权限和符号链接都会出问题,make 到一半会出现莫名其妙的 Permission denied。所以不管源码包多大,都要先复制进 Linux 虚拟磁盘再解压。
要能使用共享文件夹,先装 VMware Tools。安装包一般是 VMware 软件安装目录里的 VMwareTools-10.1.15-6627299.tar.gz,在虚拟机里解压:
tar zxvf VMwareTools-10.1.15-6627299.tar.gz cd vmware-tools-distrib/ ./vmware-install.pl安装过程中会出现 YES/路径提示:遇到 YES 就输入 Y 再回车,遇到路径直接回车采用默认值。安装完建议重启一次虚拟机,然后进入共享文件夹验证:
cd /mnt/hgfs ls -l注意 /mnt/hgfs 是区分大小写的,写成 /mnt/HGFS 会 No such file or directory。共享文件夹在 VMware 菜单需要设置为 “Always enabled”,只设为 “Enabled” 的虚拟机在挂起再恢复后有时会丢挂载,属于 VMware 15.5 的老毛病。
2.3 VMware 15.5 硬件配置:内存 16G、处理器 2 核 2 线程怎么设
虚拟机创建时,我用的镜像是 ubuntu-16.04.5-desktop-amd64.iso,安装工具是 VMware-workstation-full-15.5.0-14665864_15.5.0.49504.exe。硬件分配建议固定为一套参数:硬盘 300G,内存 16G,处理器 2 个,每个处理器 2 核。
| 配置项 | 建议值 | 说明 |
|---|---|---|
| 硬盘 | 300G | 源码解压 + out 目录 + 依赖,200G 以下容易中途撑爆 |
| 内存 | 16G | 低于 12G 编译后期会 fatal: fork: Cannot allocate memory |
| 处理器 | 2x2 | 给 4 核以上,-j4 并行度上去了内存却不够,一样翻车 |
处理器这项,虚拟机设置里有 “处理器数量” 和 “每个处理器的核心数量”,我习惯设成 2 和 2,Windows 任务管理器看到的是 4 个逻辑处理器。编译的时候用 -j4,这和核心数匹配,不容易触发内存峰值。如果你宿主机是 32G 内存,可以给虚拟机 20G 并把 -j 调到 6,但 MT6799 这份源码我实测 -j4 已经稳定。
虚拟机磁盘文件存放位置也要注意。我的电脑只有 500G,曾图省事把虚拟机放在 C 盘系统目录,结果编译时有些目录没有写入权限,连 VMware 自带的碎片整理都跑不了。把虚拟机放到 C 盘普通目录,比如 C:\Download 这种没有系统权限保护的地方,后续调整磁盘大小、做碎片整理都会顺很多。这个问题不解决,后面 make 报错你会怀疑是编译参数,实际是宿主机磁盘权限在拖后腿。
3. 源码拷贝与依赖安装:从 tar.bz2 到 OpenJDK 8
虚拟机环境验证通过后,接下来就是把 MT6799 的 Android Nougat 7.0 源码包弄进来。源码包通常是按卷拆分的 tar.bz2,比如 MT6799_Android_Nougat_7.0.tar.bz2.aa、ab 这种形式,不能只解压其中一卷,也不能在共享文件夹里直接解压。依赖工具和 JDK 版本错误,是后面两个常见报错的根源。
3.1 源文件解压和 md5 校验:报错先别慌
先把共享文件夹里的所有分卷文件复制到 Linux 虚拟磁盘的独立目录,比如 ~/android 下。复制完执行:
cat MT6799_Android_Nougat_7.0.tar.bz2.* | tar jvxf -cat 把分卷按顺序拼起来,管道给 tar 做流式解压,避免把所有分卷先拼成一个完整包再解压而多占一份磁盘空间。tar 加 j 表示处理 bzip2,v 会输出解压的文件名,f 指定用后面的 - 从标准输入读取。这个过程比较慢,一个几十 G 的源码包解压大约要二十分钟以上,期间不要动虚拟机。
解压完成后源码根目录下会有一个 md5 校验文件:
md5sum -c MT6799_Android_Nougat_7.0.tar.bz2.md5这个命令会逐个校验分卷的 MD5。如果报错,先别急着重新下载,因为只要后面编译能正常跑起来,功能没问题,个别分卷校验失败往往不影响最终镜像。我自己遇到过 md5 报错但编译完全正常的案例,这属于分发文档里比较暧昧的提示,宁可把时间花在编译上,也不要为了一个校验值把几十 G 重新拉一遍。
3.2 编译依赖工具批量安装:Ubuntu 16.04 的依赖列表
Android Nougat 7.0 的编译工具链依赖不少 32 位库,所以不能只装 build-essential。我按文档里列出来的最小集合先装了一遍:
sudo apt-get install build-essential bc flex unzip zip bison gperf curl zlib1g zlib1g-dev tofrodos libxml2-utils gitbuild-essential 提供 gcc/g++/make,flex 和 bison 是词法语法解析器,gperf 生成哈希函数,bc 用于内核编译时的数值计算。libxml2-utils 提供 xmllint,AOSP 编译会用到。zlib1g-dev 不装的话,后面解压 host 工具时经常报缺头文件。
如果你是在 Ubuntu 16.04 桌面版上从零开始建环境,我建议把下面的完整依赖块也执行一遍,它把 32 位兼容库一次补齐:
sudo apt-get install -y git flex bison gperf build-essential libncurses5-dev:i386 sudo apt-get install libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-dev g++-multilib sudo apt-get install tofrodos python-markdown libxml2-utils xsltproc zlib1g-dev:i386 sudo apt-get install dpkg-dev libsdl1.2-dev libesd0-dev sudo apt-get install git-core gnupg flex bison gperf build-essential sudo apt-get install zip curl zlib1g-dev gcc-multilib g++-multilib sudo apt-get install libc6-dev-i386 sudo apt-get install lib32ncurses5-dev x11proto-core-dev libx11-dev sudo apt-get install lib32z-dev ccache sudo apt-get install libgl1-mesa-dev libxml2-utils xsltproc unzip m4这里面很多包会重复出现,apt 不会重复安装,幂等执行没有副作用。带 i386 后缀的是 32 位版本,AOSP 的 host 工具很多是 32 位的,缺一个就会在编到某个模块时出现 “fatal error: curses.h: No such file or directory” 之类的错。libesd0-dev 是旧版音频守护进程的开发包,Nougat 编译偶尔还会引用 esd 头文件。ccache 是编译缓存,第二次全量编译会快很多,但注意它占磁盘,建议在 ~/.bashrc 里设 export USE_CCACHE=1 并给个 10G 的缓存上限。
3.3 OpenJDK 8:用 PPA 安装并切默认版本
Android Nougat 7.0 明确要求 JDK 8,Ubuntu 16.04 自带源里的 openjdk-8 可能版本旧,或者你没装。最省事的是先添加 openjdk 的 PPA:
sudo add-apt-repository ppa:openjdk-r/ppa sudo apt-get update sudo apt-get install openjdk-8-jdk添加 PPA 后 update 会拉取新的索引,安装过程大约两三分钟。装完以后系统里可能同时存在多个 JDK,比如 openjdk-7 或者 Oracle JDK,需要手动切换默认的 javac 和 java:
sudo update-alternatives --config javac sudo update-alternatives --config java执行后会列出当前系统所有候选 JDK 版本,输入对应的编号回车即可。如果你执行完只看到 “There is only one alternative”,说明系统里没有其他 JDK 冲突,不用管它,文档里那句“出现这样信息代表不用安装”指的就是这个。切换完建议验证一下:
java -version javac -version必须看到 1.8.0 开头的版本号。如果 java 已经是 8 但 javac 还是老版本,说明 alternatives 配置没切全,重新执行一次 update-alternatives 选择列表里最新那个 openjdk-8。
4. 编译指令:从 envsetup 到 make 的完整顺序
很多源码编译教程上来就让你 source envsetup.sh && lunch && make,忽略了 jack 服务和 clobber。MT6799 这份源码在 Ubuntu 16.04 上,jack 服务不启动或参数不对,ninja 报错率极高。这一章按我实际能跑通的顺序来,每一步都是下一步的前提。
4.1 清理历史输出:make clobber 和 jack-admin 服务
源码刚解压完,理论上 out 目录是空的,但还是建议先做一次清理。第一次编译失败后再继续,make clobber 能清掉所有中间产物,避免脏文件影响后续构建。
make clobber ./prebuilts/sdk/tools/jack-admin list-server ./prebuilts/sdk/tools/jack-admin start-server ./jack_install.shmake clobber 等价于删除 out 目录,但比手删安全,它知道哪些目录是构建产物。jack-admin 是 prebuilts 里管理 Jack 编译服务的工具,list-server 查看当前有没有服务在跑,start-server 启动服务。jack_install.sh 这一步很多人漏掉,它会把 Jack 服务注册到当前工程,务必放到你的源码工程根目录下执行。如果你解压后直接跳过它,后面报 TAREGT_BRM_PLATFORM is undefined 就不要觉得奇怪。
Jack 服务本质上是一个常驻 JVM,Java 编译由它代理。如果 list-server 显示的端口不对,可以先 stop-server 再 start-server。这里有个细节:jack-admin 脚本默认占用 1G 内存,后面第 5 章会讲怎么用 -Xmx4096m 把堆调大。
4.2 初始化编译环境:envsetup.sh 和 lunch target
清理完环境后,进入源码根目录执行:
source build/envsetup.sh lunch full_amt6799_evb_n-eng export LC_ALL=Csource 是在当前 shell 里加载 envsetup.sh,不是直接执行,否则环境变量不会保留。lunch 的参数 full_amt6799_evb_n-eng 是 MT6799 EVB 板对应的 product 完整 target,最后三段分别是设备名、编译类型。eng 是 engineering 版本,带 root 权限和调试工具,适合开发;userdebug 适合调试但会少一些调试工具;user 是正式版不建议首次编译选。lunch 执行后会打印出平台信息和构建类型,如果提示 “** Don't have a product spec for 'full_amt6799_evb_n-eng'”,说明 device 目录下对应的 vendor 配置没有被 include,先去检查 device 相关 mk 文件。
export LC_ALL=C 是把本地化环境固定为 C,避免系统语言和区域设置干扰编译输出。不设的话,在中文 locale 下手动编译偶尔会出现 grep 期望和实际输出不一致的诡异问题。
4.3 make 镜像:systemimage、bootimage、kernel 怎么选
lunch 完成后,直接全量 make 当然也行,但风险是如果环境有问题,等几个小时后才发现。所以我一般先单独编一个镜像验证,最常用的是 systemimage:
make -j4 systemimage如果只想验证内核编译和模块链接,可以换成:
make -j4 bootimage make -j4 kernel make -j4 userdataimage最后再跑:
make -j4-j4 是并行任务数,配 4 个逻辑处理器。千万不要在 16G 内存虚拟机上用 -j8,ninja 会瞬间创建大量进程,直接触发 fork: Cannot allocate memory。如果你宿主机内存充足,可以把 -j 调成 6,但需要同步把 Jack 的堆调大。make 的 target 名称也要注意:Android 编译系统里 systemimage 才是整包 system 镜像,system 不是一个可用的 Make target。第一次跑 systemimage 成功后,再逐步扩大范围。
| target | 产物 | 常用场景 |
|---|---|---|
| systemimage | system.img | 验证整体系统环境是否正常 |
| bootimage | boot.img | 验证内核和 ramdisk 是否链接成功 |
| kernel | kernel 镜像 | 只做内核编译时最快 |
| userdataimage | userdata.img | 验证数据分区镜像 |
| 不加 target | 全部镜像 | 最终发布前的全量编译 |
增量编译时不要再随便执行 make clobber,否则会把 out 目录清空,等于从头来过。我一般只在两类情况下才 make clobber:一是 Jack 参数改完之后,二是同一份源码之前已经编轴过、确定环境有问题时。其他时候直接 make 对应 target,ninja 会自己分析哪些模块需要重建。
5. 编译报错排查:TAREGT_BRM_PLATFORM、ninja 和内存不足
这一章是重点。我装了三遍 MT6799 环境,第一遍是在没有 install 完整依赖的情况下直接编译,第二遍是 Jack 参数加错位置,第三遍才稳定跑通。下面每个坑都按“现象 → 原因 → 解决”写明白,这些都是源码编译常见的拦路虎。
5.1 报错一:TAREGT_BRM_PLATFORM is undefined
现象:编译刚开始,定位到 vendor/amt/libs/hwcomposer.mt6799.1.5.0/Android.mk 时,报错信息显示:
vendor/amt/libs/hwcomposer.mt6799.1.5.0/Android.mk:4: *** TAREGT_BRM_PLATFORM is undefined. Please make sure the device-vendor.mk is correctly included..原因:最直接的是 device-vendor.mk 没有被正确 include,但更多时候是编译依赖没有装全,导致某些模块需要的变量没有定义。另一个常见原因是 jack_install.sh 没有运行,或者运行的位置不对。这份源码的编译顺序必须跟 MT6799_Basic_v1.pdf 文档保持一致,不按文档做,vendor 的 mk 变量就会被跳过。
解决:先把系统包升级一遍:
sudo apt-get upgrade然后补装一批编译依赖:
sudo apt-get install g++-multilib gcc-multilib lib32ncurses5-dev lib32readline-gplv2-dev lib32z1-dev bison再把 jack_install.sh 放到源码工程根目录下运行,确保它和 device/vendor 的目录结构在同一层级。如果还报同样的错,把第 3 章的完整依赖全部执行一遍,不要挑着装。这个报错最忌讳的是只搜报错标题,然后不停改 vendor 里的 mk,其实根源在环境多过在代码。
5.2 报错二:ninja: build stopped: subcommand failed
现象:make 运行一段时间后,终端最后几行出现:
build/core/ninja.mk:148: recipe for target 'ninja_wrapper' failed make: *** [ninja_wrapper] Error 1原因:Jack server 的 JVM 内存不够,或者启动参数里没有显式指定堆上限。AOSP 在 Nougat 时期用 Jack 做 Java 编译,默认的 JACK_SERVER_VM_ARGUMENTS 没有设 -Xmx,遇到稍大的模块就会 OOM,然后 ninja 认为子命令失败。
解决:修改 prebuilts/sdk/tools/jack-admin 脚本。用 vim 打开:
vim prebuilts/sdk/tools/jack-admin把原来这行:
JACK_SERVER_COMMAND="java -XX:MaxJavaStackTraceDepth=-1 -Djava.io.tmpdir=$TMPDIR$JACK_SERVER_VM_ARGUMENTS -cp $LAUNCHER_JAR $LAUNCHER_NAME"改成加上 -Xmx4096m:
JACK_SERVER_COMMAND="java -XX:MaxJavaStackTraceDepth=-1 -Djava.io.tmpdir=$TMPDIR$JACK_SERVER_VM_ARGUMENTS -Xmx4096m -cp $LAUNCHER_JAR $LAUNCHER_NAME"同时找到 JACK_SERVER_VM_ARGUMENTS 的赋值处,在 -XX:+TieredCompilation 后面也加上 -Xmx4096m:
JACK_SERVER_VM_ARGUMENTS="${JACK_SERVER_VM_ARGUMENTS:=-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4096m }"注意两处的变量名一个是 -Xmx4096m,一个是大写 M 的 -Xmx4096M,大小写不一致会造成 JVM 启动参数失效。我之前用小写 m 一直没问题,某次更新后又报错,改成大写 M 再 make clobber 突然就好了,这属于典型的环境玄学。改完以后,必须按顺序重启 Jack 服务:
make clobber ./prebuilts/sdk/tools/jack-admin stop-server ./prebuilts/sdk/tools/jack-admin start-servermake clobber 放在 stop-server 前面,清掉旧输出再重启服务,缺这一步的话,很多时候你以为参数加上了,实际上 Jack 复用旧进程,改了等于没改。我第一次就是漏掉 make clobber,白折腾了一晚上。
5.3 报错三:fatal: fork: Cannot allocate memory
现象:编译进行到 70%~80%,日志停在:
[ 78% 48705/61945] target thumb C++: .../o/drv/cam/isp_function_cam.pipechk.cpp ninja: fatal: fork: Cannot allocate memory原因:这种情况要分两种。一是 Linux 的 pid_max 上限太小,编译进程数逼近系统允许的最大 PID 值,导致 fork 新进程失败;二是虚拟机内存确实不够,不是进程数不够。区分方法很简单:先看当前进程数是不是快到上限。
sysctl kernel.pid_max ps -eLf | wc -l如果 ps 统计出来的线程数接近 pid_max,那就是第一种情况。临时调大:
echo 1000000 > /proc/sys/kernel/pid_max要让重启后仍然生效,写入 /etc/sysctl.conf:
echo "kernel.pid_max=1000000" >> /etc/sysctl.conf sysctl -p如果进程数远没到 pid_max,那就是内存不够。我当时查看虚拟机内存实际只给了 6G 左右,编译到一半系统几乎没内存可分配,于是关闭虚拟机,把内存调到 16G,问题直接消失。如果宿主机没法加内存,也可以创建 swap 应急:
sudo dd if=/dev/zero of=/swapfile bs=2048 count=524288 sudo mkswap /swapfile sudo swapon /swapfile这条命令创建 1G 的 swap 文件:bs=2048,count=524288,容量大约是 2048*524288 字节,即约 1G。ls -lh /swapfile 能看到文件存在。注意 swap 不是万能药,如果频繁触发 swap,编译速度会明显下降,重点是优先把虚拟机内存调够,swap 只用于临时绕过 OOM。
5.4 其他坑:虚拟机磁盘权限和重复源码目录
现象:编译中途出现无法写入 out 目录或Permission denied,并且虚拟机磁盘的碎片整理功能不可用。另一类现象是 JDK tool 报错,定位到源码根目录下 prebuilts 里的工具冲突。
原因:虚拟机文件放在 C 盘系统目录时,某些目录受系统权限保护,VMware 进程无法完全读写;另一个是在同一个虚拟机里放了两份不同平台的源码,共用同一个 Jack 工具和 prebuilts,导致服务互相干扰。
解决:虚拟机文件放到 C 盘普通目录,比如 C:\Download,避开系统保留目录。两份源码不要共用同一套虚拟环境,删除另一份源码或单独开虚拟机,然后重新启动 Jack 服务。这个坑没有编译报错提示,却会在最意想不到的时候冒出来,建议一开始就从磁盘路径和源码数量上规避。
6. 编译完成后怎么验证:镜像文件和编译日志
编译结束不能只看 “Build completed successfully” 就收工。我见过 make 返回 0,但指定 target 其实没生成的情况。所以每次编完,我都会做一套固定的验证流程,重点检查镜像文件、时间戳和 ninja 退出状态。
6.1 检查镜像文件和大小
找到 out 目录下的 product 输出目录:
ls -lh out/target/product/full_amt6799_evb_n/这里应当看到 system.img、boot.img、userdata.img 之类的镜像文件。system.img 一般在 500MB 到 2GB 之间,boot.img 通常只有几十 MB。如果 system.img 文件存在但大小只有几 KB,说明镜像没有真正链接成功,需要回到编译日志看是否被 ninja 跳过。用 ls -lt 看时间戳,确认文件时间是刚才编译生成的时间,而不是源码包解压时带出来的时间。
6.2 看退出码和日志关键字
make 命令结束后执行:
echo $?如果输出 0,说明 ninja 认为所有目标都成功;如果输出 1,哪怕日志里有 “Build completed” 也不能信。再配合 grep 检查日志:
make -j4 systemimage 2>&1 | tee build.log grep -i "FAILED" build.log | tail -20tee 把终端输出同时写到 build.log,后面 grep 直接定位失败模块。ninja 的失败通常不会让 make 立即退出,而是把所有失败任务汇总后再报 ninja_wrapper failed,所以要看完整日志,不能只看最后几行。
6.3 一个最小自检技巧:先编 systemimage 再全量
从那以后,我每次搭新平台环境都会强制走一遍同样的验证:先单独 make -j4 systemimage,确认通过后再 make -j4 全量。如果 systemimage 都能出来,说明依赖、Jack、内存、进程数这几大坑都已经稳住,剩下的大概率只是个别模块的源码问题。这个顺序看起来多花了一点时间,实际省掉的是反复解压源码的次数。这些做法都是从那份文档里一条条验证过来的,有它垫底,至少不用像我一样把源码解压三遍。希望帮到你。
本文还有配套的精品资源,点击获取