Ubuntu 16.04编译Android 6.0源码的优化实践

📅 2026/7/20 23:15:56 👁️ 阅读次数 📝 编程学习
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 P50(64GB内存+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 multiverse

2.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-dev)
  • ccache对二次编译加速至关重要

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 if=Android6_r1.part1 of=test.bin bs=1M count=10 md5sum test.bin

对比分卷压缩包内的校验值,确保网络传输没有出错。

4.2 ART编译问题修复

art/build/Android.common_build.mk的修改需要结合两个地方:

  1. 第75行修改条件判断:
ifeq ($(WITHOUT_HOST_CLANG),false)
  1. 还需要在同一个文件的第230行附近添加:
CLANG := false

这个问题的本质是Ubuntu 16.04默认的clang版本(3.8)与Android 6.0的编译系统存在兼容性问题。通过彻底禁用clang改用gcc可以避免复杂的版本降级操作。

5. 编译过程优化技巧

5.1 ccache配置

除了设置USE_CCACHE=1外,还需要调整缓存策略:

ccache -o compression=true ccache -o max_size=50G ccache -o sloppiness=include_file_mtime,include_file_ctime

这样配置后,二次编译时间可以缩短60%以上。

5.2 并行编译参数

make -jN的参数选择有讲究:

  1. 首先获取CPU核心数:
nproc --all
  1. 推荐计算公式:N = (核心数 × 2) + 2
  2. 监控系统负载,避免OOM:
watch -n 1 'free -m; ps -aux | grep make'

5.3 内存管理

在16GB内存的机器上,建议添加交换文件:

sudo fallocate -l 8G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile

编译完成后可以禁用:

sudo swapoff /swapfile sudo rm /swapfile

6. 典型错误排查指南

6.1 dex2oat失败

错误特征:

FAILED: out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.dex Error: Could not create the Java Virtual Machine.

解决方案:

  1. 检查JAVA_HOME是否指向OpenJDK 7
  2. 修改build/core/dex_preopt.mk:
DEX2OAT := /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. 后续开发建议

  1. 使用repo工具管理源码修改:
repo init -u https://android.googlesource.com/platform/manifest -b android-6.0.1_r77 repo sync -j4
  1. 增量编译技巧:
make -j8 showcommands | tee build.log

这样可以保留完整的编译日志,方便问题定位。

  1. 模块化编译示例(仅编译Settings应用):
mmm packages/apps/Settings/

这套环境经过我在三台不同配置的机器上验证(Intel i7/Xeon E5/Ryzen 7),最关键的教训是:所有路径必须全英文,JDK版本必须严格匹配,遇到错误先检查前序步骤是否完全正确。现在每次有新同事需要搭建环境,我都会让他们先完整阅读这篇指南,通常可以避免90%的常见问题。