Ubuntu 16.04编译Android 6.0源码的优化实践
1. 环境准备为什么选择Ubuntu 16.04 LTS三年前我在尝试编译Android 6.0源码时发现大多数教程都基于Ubuntu 14.04环境。但当时16.04 LTS刚发布不久作为长期支持版本它在硬件兼容性和工具链更新方面有明显优势。实测表明同样的硬件配置下16.04的编译效率比14.04提升约20%这主要得益于内核调度优化和文件系统改进。物理机安装是另一个关键决策点。我曾用VMware虚拟机测试编译不仅需要配置复杂的共享文件夹源码目录大小超过30GB编译过程中还频繁出现内存不足导致的进程崩溃。后来改用双系统方案在ThinkPad P5064GB内存NVMe SSD上完整编译仅需3小时而虚拟机方案耗时超过15小时。重要提示/home分区至少分配120GB空间Android 6.0完整编译后out目录会占用约80GB空间加上源码本身和中间文件实际需要更多空间缓冲。2. 依赖管理Ubuntu 16.04的特殊配置2.1 软件源优化阿里云镜像源确实能显著提升包下载速度但需要注意16.04的代号是xenial而非示例中的quantal这是12.10的代号。正确的源配置应该是deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ xenial-proposed main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse2.2 关键依赖项经过多次验证以下依赖组合在16.04上最稳定sudo apt-get install -y git-core gnupg flex bison gperf build-essential \ zip curl zlib1g-dev gcc-multilib g-multilib libc6-dev-i386 \ lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache \ libgl1-mesa-dev libxml2-utils xsltproc unzip m4 libsdl1.2-dev特别注意libsdl1.2-dev必须保留不能简化为libsdl-dev需要显式指定i386架构的库如lib32ncurses5-devccache对二次编译加速至关重要3. JDK版本陷阱与解决方案Android 6.0要求OpenJDK 7但Ubuntu 16.04默认仓库已移除了OpenJDK 7。通过PPA安装时要注意密钥验证sudo add-apt-repository ppa:openjdk-r/ppa sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EB9B1D8886F44E2A sudo apt-get update sudo apt-get install openjdk-7-jdk环境变量配置有个细节容易被忽略在/etc/profile中设置JAVA_HOME时实际路径需要根据CPU架构调整。对于x86_64机器应该是export JAVA_HOME/usr/lib/jvm/java-7-openjdk-amd64而32位系统则需要改为export JAVA_HOME/usr/lib/jvm/java-7-openjdk-i386验证时不要只看java -version输出还要检查javac版本javac -version两者必须都是1.7.x版本否则会出现微妙的编译错误。4. 源码处理与关键修改4.1 源码合并校验当使用cat合并分卷压缩包时建议先用dd命令验证文件完整性dd ifAndroid6_r1.part1 oftest.bin bs1M count10 md5sum test.bin对比分卷压缩包内的校验值确保网络传输没有出错。4.2 ART编译问题修复art/build/Android.common_build.mk的修改需要结合两个地方第75行修改条件判断ifeq ($(WITHOUT_HOST_CLANG),false)还需要在同一个文件的第230行附近添加CLANG : false这个问题的本质是Ubuntu 16.04默认的clang版本(3.8)与Android 6.0的编译系统存在兼容性问题。通过彻底禁用clang改用gcc可以避免复杂的版本降级操作。5. 编译过程优化技巧5.1 ccache配置除了设置USE_CCACHE1外还需要调整缓存策略ccache -o compressiontrue ccache -o max_size50G ccache -o sloppinessinclude_file_mtime,include_file_ctime这样配置后二次编译时间可以缩短60%以上。5.2 并行编译参数make -jN的参数选择有讲究首先获取CPU核心数nproc --all推荐计算公式N (核心数 × 2) 2监控系统负载避免OOMwatch -n 1 free -m; ps -aux | grep make5.3 内存管理在16GB内存的机器上建议添加交换文件sudo fallocate -l 8G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile编译完成后可以禁用sudo swapoff /swapfile sudo rm /swapfile6. 典型错误排查指南6.1 dex2oat失败错误特征FAILED: out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.dex Error: Could not create the Java Virtual Machine.解决方案检查JAVA_HOME是否指向OpenJDK 7修改build/core/dex_preopt.mkDEX2OAT : /usr/bin/java -jar $(DEX2OATD)改为DEX2OAT : /usr/lib/jvm/java-7-openjdk-amd64/bin/java -jar $(DEX2OATD)6.2 文件权限问题错误特征/bin/bash: out/host/linux-x86/bin/acp: Permission denied解决方法chmod -R 755 out find . -name *.sh -exec chmod 755 {} \;6.3 Python版本冲突Ubuntu 16.04默认Python3会导致部分脚本失败临时切换版本sudo update-alternatives --config python选择Python 2.7后再重新编译。7. 编译后验证与调试成功编译后建议运行以下检查# 检查镜像完整性 file out/target/product/generic/system.img # 验证内核版本 strings out/target/product/generic/ramdisk.img | grep Linux # 启动模拟器并获取日志 emulator -show-kernel -verbose adb logcat | grep -i error如果遇到模拟器黑屏可以尝试emulator -gpu host -no-audio这通常是由于16.04的图形驱动兼容性问题导致。8. 后续开发建议使用repo工具管理源码修改repo init -u https://android.googlesource.com/platform/manifest -b android-6.0.1_r77 repo sync -j4增量编译技巧make -j8 showcommands | tee build.log这样可以保留完整的编译日志方便问题定位。模块化编译示例仅编译Settings应用mmm packages/apps/Settings/这套环境经过我在三台不同配置的机器上验证Intel i7/Xeon E5/Ryzen 7最关键的教训是所有路径必须全英文JDK版本必须严格匹配遇到错误先检查前序步骤是否完全正确。现在每次有新同事需要搭建环境我都会让他们先完整阅读这篇指南通常可以避免90%的常见问题。