Android 编译和刷机 —— 源码编译
版本类型
Android 的工程名按照编译类型可以分成三种:user、userdebg 和 eng。
- user:最接近生产环境的稳定版本,适合最终用户使用。
- userdebug:适合开发人员和测试人员,提供调试和开发功能,但保持一定的稳定性和接近生产环境的配置。
- eng:专为工程师和内部测试设计,包含最全面的调试工具和最低的限制,主要用于开发和深度测试。
编译 Android 源码
编译全部源码
编译 Android 源码的命令如下:
cd AOSP
source build/envsetup.sh
lunch
进入到 AOSP 源码目录,然后调用 envsetup.sh
初始化环境。lunch
后需要选择对应的工程,可以填写数字或者对应的工程名称。
You're building on Linux
Lunch menu... pick a combo:
1. aosp_arm-eng
2. aosp_arm64-eng
3. aosp_mips-eng
4. aosp_mips64-eng
5. aosp_x86-eng
6. aosp_x86_64-eng
7. full_fugu-userdebug
8. aosp_fugu-userdebug
9. mini_emulator_arm64-userdebug
10. m_e_arm-userdebug
11. m_e_mips64-eng
12. m_e_mips-userdebug
13. mini_emulator_x86_64-userdebug
14. mini_emulator_x86-userdebug
15. aosp_dragon-userdebug
16. aosp_dragon-eng
17. aosp_marlin-userdebug
18. aosp_sailfish-userdebug
19. aosp_flounder-userdebug
20. aosp_angler-userdebug
21. aosp_bullhead-userdebug
22. hikey-userdebug
23. aosp_shamu-userdebug
Which would you like? [aosp_arm-eng]
执行完 lunch
命令后,就可以正式开始编译 Android 源码。
make -j8
编译完成后,在源码的根目录 out/target/product/
下会生成编译产物和文件:
- system.img: 包含 Android 操作系统的核心部分,如系统应用程序和库,是系统的主要镜像。
- ramdisk.img: 包含根文件系统的初步镜像,提供启动时的基本文件和配置。
- userdata.img: 存储用户的数据和应用程序,是用户存储空间的镜像。
- recovery.img: 包含恢复模式的镜像,用于系统恢复和维修操作。
- boot.img: 包含内核和启动程序,是启动 Android 系统时加载的镜像。
- vendor.img: 存储供应商提供的特定驱动程序和库,通常包括硬件相关的代码和驱动。
单仓库编译
AOSP 除了支持全部编译(整编),还支持单仓库编译(单编)源码。初始化环境后,进入到需要编译的模块中,然后执行编译命令:
source build/envsetup.sh
lunch
cd AOSP/packages/apps/Settings
mm
编译完成后,会提示生成的文件路径。比如编译 Setting 会提示在 out/target/product/generic_x86/system/priv-app/Settings
生成了 Settings.apk
文件。
除了使用 mm
命令编译以外,还可以使用如下的命令:
- mmm:编译指定目录下的模块,不编译它所依赖的其它模块。
- mma:编译当前目录下的模块及其依赖项。
- mmma:编译指定路径下所有模块,并且包含依赖。
获取到编译产物后,可以通过如下的两种方式安装:
- 通过
adb push
到 SDCard 下的 Download 路径安装或者直接使用adb install
安装。 - 通过
make snod
命令重新生成 system.img,允许模拟器查看。
在 Docker 上编译 Android 源码
谷歌推荐使用 Docker 编译 Android 源码。在 Ubuntu 上安装 Docker,可以参见 此文档 。在编译前,需要确保 Docker 能够正常运行。
Step 1:把 Android 源码挂载到 Docker 根路径
# 第一次创建。执行如下命令,每次都会创建一个容器
docker run -it -v ~/Android/AOSP:/Android/AOSP ubuntu:20.04
# 非第一次创建,先获取上次创建容器的 ID,然后启动这个 ID
docker ps -a
docker start -i <ID>
Danger
区分第一次创建 Docker 还是不是第一次创建非常重要,否则会导致后续安装的软件失效。
Step 2:初始化编译环境和选择编译的工程
source build/envsetup.sh
lunch
Step 3:开始编译 Android 工程
make -j50
要是报无法 libncurses.so.5
无法找的错误,可以参考 FAQs 章节。
在
启动模拟器
启动 emulator 模拟器:
emulator
源码结构
目录 | 描述 | 子目录及描述 |
---|---|---|
frameworks/ |
Android 框架的源代码 | base/ : 核心框架代码native/ : 本地代码opt/ : 可选功能support/ : 支持库 |
system/ |
系统服务和工具的代码 | core/ : 核心服务extras/ : 额外服务tools/ : 构建工具 |
hardware/ |
硬件抽象层(HAL)的源代码 | interfaces/ : HAL 接口libhardware/ : HAL 实现库 |
device/ |
特定设备的配置和代码 | <manufacturer>/ : 制造商目录<device>/ : 设备目录 |
vendor/ |
供应商特定的代码和文件 | <manufacturer>/ : 供应商目录 |
packages/ |
系统应用和包 | apps/ : 系统应用providers/ : 内容提供者services/ : 系统服务 |
build/ |
构建系统和工具的源代码 | core/ : 构建核心代码env/ : 构建环境配置tools/ : 构建工具 |
kernel/ |
Android 内核的源代码 | <kernel_version>/ : 内核版本目录 |
art/ |
Android Runtime(ART)的源代码 | runtime/ : 运行时系统实现 |
external/ |
外部项目的源代码和库 | <project>/ : 外部项目源代码 |
tools/ |
开发和构建工具的源代码 | sdk/ : Android SDK 工具lint/ : 代码检查工具 |
dalvik/ |
Dalvik 虚拟机的源代码(已被 ART 取代) | |
testing/ |
测试框架和工具的源代码 | common/ : 通用测试工具support/ : 支持库 |
docs/ |
文档和开发指南 | |
scripts/ |
构建和开发过程中的脚本和工具 |
FAQs
缺少 libncurses5 库文件
报错信息如下:
FAILED: out/target/product/generic_x86/obj/RENDERSCRIPT_BITCODE/libclcore.bc_intermediates/rs_mesh.bc
/bin/bash -c "PWD=/proc/self/cwd prebuilts/clang/host/linux-x86/clang-3289846/bin/clang -Iframeworks/rs/script_api/include -Iexternal/clang/lib/Headers -MD -DRS_VERSION=24 -std=c99 -c -O3 -fno-builtin -emit-llvm -target renderscript32-linux-androideabi -fsigned-char -D__i386__ -Wno-deprecated -Werror -Werror -Wall -Wextra -Iframeworks/rs/cpu_ref -DRS_DECLARE_EXPIRED_APIS -x renderscript frameworks/rs/driver/runtime/rs_mesh.c -o out/target/product/generic_x86/obj/RENDERSCRIPT_BITCODE/libclcore.bc_intermediates/rs_mesh.bc"
prebuilts/clang/host/linux-x86/clang-3289846/bin/clang.real: error while loading shared libraries: libncurses.so.5: cannot open shared object file: No such file or directory
可以看到报错的地方在 libncurses.so.5
库文件上,解决办法:
sudo apt install libncurses5
在 Docker 上,需要运行:
apt-get install -y libncurses5
缺少 unzip 工具
在 Ubuntu 系统上运行:
sudo apt install unzip
在 Docker 上,需要运行:
apt-get install -y unzip
内存空间不足
Google 建议编译 AOSP 的内存不低于 32 GB,个人电脑很难达到这个配置。在执行完成 make -j8
后会报如下的错误;
FAILED: out/soong/build.ninja
cd "$(dirname "out/host/linux-x86/bin/soong_build")" && BUILDER="$PWD/$(basename "out/host/linux-x86/bin/soong_build")" && cd / && env -i "$BUILDER" --top "$TOP" --soong_out "out/soong" --out "out" -o out/soong/build.ninja --globListDir build --globFile out/soong/globs-build.ninja -t -l out/.module_paths/Android.bp.list --available_env out/soong/soong.environment.available --used_env out/soong/soong.environment.used.build Android.bp
Killed
11:54:56 soong bootstrap failed with: exit status 1
ninja: build stopped: subcommand failed.
#### failed to build some targets (01:04 (mm:ss)) ####
看到 soong_build 失败并显示 Killed 通常表明构建过程中发生了严重的问题,可能与系统资源(如内存)不足有关。可以通过增加交换空间来缓解内存不足的问题。 增加 Swap 空间的步骤如下:
Step 1:查看当前的 Swap 空间
free -m
total used free shared buff/cache available
Mem: 3908 3211 244 1 451 415
Swap: 3907 0 3907
cat /proc/swaps
Filename Type Size Used Priority
/swap.img file 4001788 0 -2
Step 2:停止已有的 Swap 空间
sudo swapoff /swap.img
Step 3:删除 Swap 空间
sudo rm /swap.img
Step 4:重建 Swap 空间
# 16GB
sudo dd if=/dev/zero of=/swap.img bs=1M count=16384
Step 5:启用 Swap 空间
sudo chmod 600 /swap.img
sudo mkswap -f /swap.img
sudo swapon /swap.img
Step 6:检查 Swap 空间
free -m
cat /proc/swaps