Android-x86的源码编译

前言

Git管理单独的模块,而repo管理所有的Git库,将多个Git库组合在一起,形成一个完整的系统
使用 repo init 获取 manifests 和 repo 库,使用 repo sync 获取 manifests 中的模块
如果报错可运行 repo sync –trace 获取出错的那几个文件属于哪个模块
然后到 .repo/manifest/default.xml 中将对应的模块删掉就好了,但可能编译错误

配置环境

  1. 安装编译所需依赖
1
2
3
4
5
sudo apt install git curl gnupg zip unzip ccache xsltproc gettext repo \
gcc-multilib g++-multilib make flex m4 bc bison gperf dosfstools mtools \
libelf-dev libssl-dev libncurses5 libxml2-utils zlib1g-dev openjdk-8-jdk \
x11proto-core-dev libx11-dev libgl1-mesa-dev python-enum34 python-mako \
syslinux-utils lib32stdc++6 libc6-dev-i386 lib32ncurses-dev lib32z-dev
  1. 若找不到repo包请添加contrib源或直接从谷歌下载
1
2
3
4
5
6
7
8
9
10
sudo curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo > /usr/local/bin/repo
sudo chmod a+x /usr/local/bin/repo

# 新版repo需要python3.6以上
sudo apt install python3
sudo rm /usr/bin/python
sudo ln -s /usr/bin/python3 /usr/bin/python

# 因为repo运行时会尝试访问官方的git源更新自己,设置下面变量可以使用国内源进行更新
export REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/'
  1. 从其他源安装OpenJDK
1
2
3
4
5
6
7
# AOSP中的master分支在platform/prebuilts/jdk中有预编译版本的OpenJDK。因此主线分支无需再额外安装
# Debian 10仅提供JDK11,而编译Android 7以上需要的是JDK8,这里使用adoptopenjdk-8-hotspot
# 添加adoptopenjdk的JDK源并安装,HotSpot在CPU方面具有优势,OpenJ9在内存方面领先

wget -qO - https://adoptopenjdk.jfrog.io/adoptopenjdk/api/gpg/key/public | sudo apt-key add -
echo "deb http://mirrors.tuna.tsinghua.edu.cn/AdoptOpenJDK/deb buster main" >> /etc/apt/sources.list
apt update && apt install adoptopenjdk-8-hotspot

获取源码

  1. 设置变量
1
2
3
# 使用REPO前需要设置GIT的用户信息
git config --global user.email "username@email.com"
git config --global user.name "username"
  1. 拉取仓库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
mkdir android-source && cd android-source

repo init -u http://scm.osdn.net/gitroot/android-x86/manifest \
-b pie-x86 -m android-x86-9.0-r2.xml \
--repo-url=https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/

# 修改为国内源
sed -i 's|android.googlesource.com|mirrors.tuna.tsinghua.edu.cn/git/AOSP|g' \
.repo/manifests/android-x86-9.0-r2.xml

# REPO中init的相关参数
-u # 指定一个URL,其连接到一个maniest仓库
-m # 在manifest仓库中选择一个xml文件
-b # 选择一个maniest仓库中的一个特殊的分支
--depth=1 # 只下载最近版本的代码,只保留最近的commit版本
--mirror # 建立本地镜像,只在repo第一次初始化的时候使用
--repo-url # 设定repo的版本库地址
--repo-branch # 设定需要检出的分支
--no-repo-verify # 设定不要对repo的签名进行严格的验证

# 其他相关源
https://mirrors.ustc.edu.cn/aosp
https://mirrors.tuna.tsinghua.edu.cn/git/AOSP
https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/
  1. 同步源码
1
2
3
4
5
6
7
8
9
10
11
12
repo sync -j4 --no-tags --no-clone-bundle --current-branch

# REPO中sync的相关参数
--no-tags # 减少不需要的tag下载,可以缩减下载的代码量
--no-clone-bundle # 关闭cdn分流下载可以更好的利用网络带宽,加快下载速度
--current-branch # 只拉取当前分支,只在init时指定分支同步时也会拉些没用的
--force-sync # 如果同步失败继续同步,如果文件目录有差异强制覆盖掉

# 或者使用离线源码包初始化(不适用于Android x86,仅用于主线分支)
wget -c https://mirrors.tuna.tsinghua.edu.cn/aosp-monthly/aosp-latest.tar
tar -xvf aosp-latest.tar && cd aosp
repo sync -l # 仅检出代码

编译源码

  1. 编译目标系统
1
2
3
4
cd android-source
source build/envsetup.sh # 设置编译环境变量
lunch android_x86_64-userdebug # 选择生成的目标架构,或直接lunch来选择目标类型
m -j12 iso_img # 确认输出的配置正确后开始编译
  1. 编译后的文件
1
2
3
内核将在 out/target/product/x86_64/kernel
模块放在 out/target/product/x86_64/system/lib/modules/
镜像文件 out/target/product/x86_64/android_x86_64.iso
  1. 指定配置文件
1
2
3
# 默认配置文件在该路径中 kernel/arch/x86/configs/ ,编译时将自动使用变量 TARGET_PRODUCT 对应的 defconfig
# 通过指定 TARGET_PRODUCT=android_x86_64 来使用配置文件 android-x86_64_defconfig 编译内核及其模块
make iso_img TARGET_PRODUCT=android_x86_64
  1. 编译后的清理
1
2
3
1. 在源码目录的根目录下 make clean
2. 进到源码的 kernel/ 目录下,执行 make mrproper
3. 再退回到根目录下执行 source build/envsetup.sh ; lunch ; make

内核定制

  1. 自定义内核配置
1
2
3
4
5
6
7
8
9
10
11
# 不建议直接编辑内核配置文件,因为它可能会生成不满足依赖性等错误的配置
cd android-source
source build/envsetup.sh
lunch android_x86_64-userdebug
cp kernel/arch/x86/configs/android-x86_64_defconfig kernel/.config
cd kernel
make O=kernel/ ARCH=x86_64 menuconfig

# 将修改后的配置文件 kernel/.config 备份,O的意思是在 kernel/ 下生成 .config
# 直接在kernel目录下make menuconfig可能会导致构建规则被破坏
# 可在源码根目录下尝试修复:make -C kernel distclean ,-C 指定内核源码根目录
  1. 仅构建内核用于其他的Android X86系统
1
2
3
4
5
6
7
8
# 单独构建内核及其模块
source build/envsetup.sh
lunch android_x86_64-userdebug
make kernel

# 目标设备上的android-x86在以前安装时 /system 必须以读写模式安装才能更新内核
# 将内核 out/target/product/x86_64/kernel 复制到目标设备的根目录
# 将模块 out/target/product/x86_64/system/lib/modules 复制到目标设备的 /system/lib/modules 目录
  1. 构建包含定制内核的镜像
1
2
3
4
5
6
7
8
9
10
11
1. 如你已有合适的内核配置文件my_defconfig,可使用你的配置文件来构建包含定制内核的镜像ISO

2. 不能直接使用Linux发行版的内核配置来定制,因为Android需要内核开启特定的功能支持

3. 在kernel/configs/p/android-4.14/android-base.cfg中包含了Android P所需内核支持的选项,但是它删除了android-x86的arm特定选项如PMEM

3. 如你已有合适的内核配置文件,可以直接指定配置文件路径来构建ISO
make iso_img TARGET_PRODUCT=android_x86_64 TARGET_KERNEL_CONFIG=kernel/arch/x86/configs/my_defconfig

5. 如你已有经编译好的内核,可以直接指定内核位置来使用它生成ISO
make iso_img TARGET_PRODUCT=android_x86_64 TARGET_PREBUILT_KERNEL=out/target/product/x86_64/kernel
  1. 使用其他版本内核构建系统
1
2
3
4
5
# 使用4.9内核构建9.0-r2
cd android-source/kernel
git fetch x86 kernel-4.9-p
git checkout -t x86/kernel-4.9-p
cd ..

注意事项

  1. Win10中WSL环境下编译会通不过,envsetup.sh脚本目前仅支持bash或zsh,其他自测。

  2. 编译Android 7~10使用JDK8,5~6使用JDK7,2.3~4.4使用JDK6,1.5~2.2使用JDK5

  3. 使用12线程编译ISO历时3个小时左右,16G内存最高时占用12G,需要的磁盘空间超过150G

  4. 使用CCACHE来提高编译速度

1
2
3
4
5
6
export USE_CCACHE=1				# 开启CCACHE
export CCACHE_DIR=~/.ccache # 指定缓存存储目录
prebuilts/misc/linux-x86/ccache/ccache -M 50G # 建议的缓存大小为50G到100G

# 查看使用ccache时的情况
watch -n1 -d prebuilts/misc/linux-x86/ccache/ccache -s
  1. 获取源码时的错误解决
1
2
3
4
5
6
7
8
9
错误:error: RPC failed; curl 56 GnuTLS recv error (-9): A TLS packet with unexpected length was received.
解决:git config -l # 查看当前配置命令
git config --global http.sslVerify false # 关闭验证SSL证书
git config --global http.postBuffer 1048576000 # 设置http的Buffer到1G
git config --global core.compression -1 # 启用压缩配置

错误:fatal: unable to access 'https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/packages/apps/StorageManager/': Failed to connect to mirrors.tuna.tsinghua.edu.cn port 443: Connection refused
把这:fetch="https://aosp.tuna.tsinghua.edu.cn/"
换成:fetch="https://mirrors.ustc.edu.cn/aosp/"
  1. 编译系统时的错误解决
1
2
3
4
5
6
7
8
9
10
11
12
13
# Try increasing heap size with java option '-Xmx<size>'. 出现Xmx错误是由于电脑内存不足
# 建议修改-Xmx4096m为系统内存的二分之一,如果内存或SWAP大于等于16g可以不用修改
export JACK_SERVER_VM_ARGUMENTS="-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4096m"
prebuilts/sdk/tools/jack-admin kill-server
prebuilts/sdk/tools/jack-admin start-server

# genisoimage: option '-e' is ambiguous; possibilities: '-eltorito-boot' '-eltorito-alt-boot'
解决:vi android-source/bootable/newinstaller/Android.mk
找到:-e boot/grub/efi.img
改为:-eltorito-boot boot/grub/efi.img

# 启动时卡在Detecting android-x86 found at /dev/sda1
解决:修改grub引导添加 nomodeset xforcevesa
  1. 编译Anbox镜像
1
2
3
4
5
6
7
8
9
10
11
12
13
cd anbox
repo init -u https://github.com/anbox/platform_manifests.git -b anbox \
--repo-url=https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/ --depth=1
repo sync -j4 -c --no-tags --no-clone-bundle --force-sync

source build/envsetup.sh
lunch anbox_x86_64-userdebug
make -j8

cd anbox/vendor/anbox
scripts/create-package.sh \
out/target/product/x86_64/ramdisk.img \
out/target/product/x86_64/system.img