跳转至

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:编译指定路径下所有模块,并且包含依赖。

获取到编译产物后,可以通过如下的两种方式安装:

  1. 通过 adb push 到 SDCard 下的 Download 路径安装或者直接使用 adb install 安装。
  2. 通过 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