Android编译
准备工作
硬件要求
磁盘的空间保持在300GB以上,编译会占用大量的硬盘空间。
软件要求
在AOSP开源中,主分支使用Ubuntu长期版本开发和测试的,因此推荐使用Ubuntu进行编译,下面列出不同版本的Ubuntu能够编译哪些Android版本:
Android版本 | 编译的Ubuntu版本 |
---|---|
Android 11.0 | Ubuntu 20.04 |
Android 8.0 - Android 10.0 | Ubuntu 18.04 |
Android7.0 | Ubuntu 16.04 |
Android 6.0 | Ubuntu 14.04 |
Android 2.3.x至Android 5.x | Ubuntu 12.04 |
Android 1.5至Android 2.2.x | Ubuntu 10.04 |
除了操作系统外,JDK的版本也需要注意:
Android版本 | 编译的JDK版本 |
---|---|
Android 7.x 至 Android 11.0 | OpenJDK 8 |
Android 5.x至android 6.0 | OpenJDK 7 |
Android 2.3.x至Android 4.4.x | Oracle JDK 6 |
Android 1.5至Android 2.2.x | Oracle JDK 5 |
搭建Android系统开发环境,我们这里如下版本的工具:
虚拟机:VMware-workstation-full-15.5.0
Linux系统:ubuntu-20.04.2.0-desktop-amd64.iso
连接工具:FinalShell或xShell
Android系统:android-10.0.0_r41
JDK版本:openjdk-8
基础软件
使用VM安装Ubuntu后,需要配置镜像源,具体步骤如下:
Settings -> About -> Software Updates -> Download from -> other
刷新缓存后,就可以开始安装需要的软件:
VIM安装
安装VIM
sudo apt install vim
SSH安装
安装SSH
sudo apt install ssh
配置ssh客户端,去掉PasswordAuthentication yes前面的#号,保存退出
sudo vim /etc/ssh/ssh_config
配置ssh服务器,把PermitRootLogin prohibit-password改成PermitRootLogin yes,保存退出。
sudo vim /etc/ssh/sshd_config
重启ssh服务
sudo /etc/init.d/ssh restart
此时,就可以通过xShell或finalShell等工具远程连接Linux系统。
JDK安装
由于最新的Android系统的JDK编译版本是1.8,所以我们选择openJdk1.8安装:
sudo apt install openjdk-8-jre-headless
安装完成后,通过java -version即可查看默认的Java版本:
Git安装
检查git是否安装,输入git version命令即可,如果没有安装则可以使用如下命令安装:
sudo apt install git
配置git的账户名和密码信息
git config --global user.name "Your Name"
git config --global user.email "youremail@domain.com"
Python安装
一般Ubuntu都会内置Python,我们可以通过如下命令查看系统中内置的Python版本:
whereis python # 查看ubuntu系统中所有的python版本
由于系统编译会使用到python3,这里创建软连接
sudo ln -s /usr/bin/python3 /usr/bin/python
源码下载
Repo是Google开发的用于管理Android版本库的一个工具。repo并不是用来取代Git,而是用Python对Git进行了一定的封装,简化了对多个Git版本库的管理。对应repo管理的任何一个版本库,都需要使用Git命令进行操作。
在下载源码之前,我们先创建android目录,然后对目录仓库进行初始化:
cd ~
sodu mkdir android
cd android
git init
Repo工具
下载 repo 工具:
mkdir ~/bin
export PATH=~/bin:$PATH
curl -sSL 'https://gerrit-googlesource.proxy.ustclug.org/git-repo/+/master/repo?format=TEXT' |base64 -d > ~/bin/repo
chmod a+x ~/bin/repo
如果google的地址下载失败或无法下载,更改root下的repo的REPO_URL : https://gerrit-googlesource.proxy.ustclug.org/git-repo
# repo default configuration
#
REPO_URL = os.environ.get('REPO_URL', None)
if not REPO_URL:
REPO_URL = 'https://gerrit-googlesource.proxy.ustclug.org/git-repo'
REPO_REV = os.environ.get('REPO_REV')
if not REPO_REV:
REPO_REV = 'stable'
# URL to file bug reports for repo tool issues.
BUG_URL = 'https://bugs.chromium.org/p/gerrit/issues/entry?template=Repo+tool+issue'
# increment this whenever we make important changes to this script
VERSION = (2, 15)
# increment this if the MAINTAINER_KEYS block is modified
KEYRING_VERSION = (2, 3)
# Each individual key entry is created by using:
# gpg --armor --export keyid
MAINTAINER_KEYS = """
源码同步
在下载源码前,我们需要在如下网站选择相应的Android版本
https://source.android.com/setup/start/build-numbers#source-code-tags-and-builds
选择相应的版本后,输入如下命令进行初始化:
# 初始化操作,后面-b参数是相应的版本号
repo init -u git://mirrors.ustc.edu.cn/aosp/platform/manifest -b android-10.0.0_r41
如果出现repo has been initialized in xxx 说明成功了,此时直接同步即可:
repo sync
同步的时间会根据网络的情况而不尽相同,耐心等待即可。
编译和运行
编译源码
在编译源码之前,需要添加相应的依赖:
sudo apt-get install libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-dev g++-multilib
sudo apt-get install -y git flex bison gperf build-essential libncurses5-dev:i386
sudo apt-get install tofrodos python-markdown libxml2-utils xsltproc zlib1g-dev:i386
sudo apt-get install dpkg-dev libsdl1.2-dev libesd0-dev
sudo apt-get install git-core gnupg flex bison gperf build-essential
sudo apt-get install zip curl zlib1g-dev gcc-multilib g++-multilib
sudo apt-get install libc6-dev-i386
sudo apt-get install lib32ncurses5-dev x11proto-core-dev libx11-dev
sudo apt-get install libgl1-mesa-dev libxml2-utils xsltproc unzip m4
sudo apt-get install lib32z-dev ccache
sudo apt-get install libssl-dev
初始化编译环境
source build/envsetup.sh
选择编译目标,就是选择编译出来的镜像运行在什么样的设备上
lunch 或 lunch xxxx
lunch命令是envsetup.sh里定义的一个命令,用来让用户选择编译目标。
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. aosp_car_arm-userdebug
8. aosp_car_arm64-userdebug
9. aosp_car_x86-userdebug
10. aosp_car_x86_64-userdebug
11. mini_emulator_arm64-userdebug
12. m_e_arm-userdebug
13. m_e_mips64-eng
14. m_e_mips-userdebug
15. mini_emulator_x86_64-userdebug
16. mini_emulator_x86-userdebug
17. uml-userdebug
18. aosp_cf_x86_auto-userdebug
19. aosp_cf_x86_phone-userdebug
20. aosp_cf_x86_tablet-userdebug
21. aosp_cf_x86_tablet_3g-userdebug
22. aosp_cf_x86_tv-userdebug
23. aosp_cf_x86_wear-userdebug
24. aosp_cf_x86_64_auto-userdebug
25. aosp_cf_x86_64_phone-userdebug
26. aosp_cf_x86_64_tablet-userdebug
27. aosp_cf_x86_64_tablet_3g-userdebug
28. aosp_cf_x86_64_tv-userdebug
29. aosp_cf_x86_64_wear-userdebug
30. cf_x86_auto-userdebug
31. cf_x86_phone-userdebug
32. cf_x86_tablet-userdebug
33. cf_x86_tablet_3g-userdebug
34. cf_x86_tv-userdebug
35. cf_x86_wear-userdebug
36. cf_x86_64_auto-userdebug
37. cf_x86_64_phone-userdebug
38. cf_x86_64_tablet-userdebug
39. cf_x86_64_tablet_3g-userdebug
40. cf_x86_64_tv-userdebug
41. cf_x86_64_wear-userdebug
42. aosp_marlin-userdebug
43. aosp_marlin_svelte-userdebug
44. aosp_sailfish-userdebug
45. aosp_walleye-userdebug
46. aosp_walleye_test-userdebug
47. aosp_taimen-userdebug
48. hikey-userdebug
49. hikey64_only-userdebug
50. hikey960-userdebug
Which would you like? [aosp_arm-eng]
编译目标的格式组成为BUILD-BUILDTYPE,比如aosp_arm-eng的BUILD为aosp_arm,BUILDTYPE为eng。BUILDTYPE 指的是编译类型,有以下三种:
user:用来正式发布到市场的版本,权限受限,如没有 root 权限,不能 dedug,adb默认处于停用状态。
userdebug:在user版本的基础上开放了 root 权限和 debug 权限,adb默认处于启用状态。一般用于调试真机。
eng:开发工程师的版本,拥有最大的权限(root等),具有额外调试工具的开发配置。一般用于模拟器。
通过make指令进行代码编译,通过-j参数设置参与编译的线程数量来提高编译速度:
make -j8
编译后最终会在 out/target/product/generic_x86/目录生成了三个重要的镜像文件: system.img、userdata.img、ramdisk.img。
system.img:系统镜像,里面包含了Android系统主要的目录和文件,通过init.c进行解析并mount挂载到/system目录下。
userdata.img:用户镜像,是Android系统中存放用户数据的,通过init.c进行解析并mount挂载到/data目录下。
ramdisk.img:根文件系统镜像,包含一些启动Android系统的重要文件,比如init.rc。
至此,Android11编译完成,如果在模拟器上运行该系统需要在桌面命令行中运行emulator命令即可运行
模块编译
Android编译有一套自己的规则,主要利用mk文件,主要包含三个命令用于编译:make、mmm、mm。
make:不带任何参数,用于编译整个系统,编译时间较长。也可以带参数来编译单个模块,比如make MediaProvider,由于会编译该模块的依赖模块,所以比较耗时。
mmm packages/providers/MediaProvider:用于编译指定目录下的模板模块,不会编译该模块的依赖模块。
mm:编译当前目录下的模块,只编译当前模块,需要通过cd切换到当前目录下。
一般编译方式都使用增量编译,只编译发生变化的模板文件,如果想编译所有模板文件则使用-B选项参数即可。
下面是一些常用模块的编译命令列表:
目标模块 | make命令 | mmm命令 |
---|---|---|
init | make init | mmm system/core/init |
zygote | make app_process | mmm frameworks/base/cmds/app_process |
system_server | make services | mmm frameworks/base/services/java |
RefBase | make libutils | mmm frameworks/base/libs/utils |
Looper | make framework | mmm frameworks/base |
AudioTrack | make libmedia | mmm frameworks/base/media/libmedia |
AudioFliger | make libaudioflinger | mmm frameworks/base/libs/audioflinger |
AudioPolicyService | make libaudiopolicy | mmm hardware/msm7k/libaudio-qsd8k |
SurfaceFlinger | make libsurfaceflinger | mmm frameworks/base/libs/surfaceflinger |
Vold | make void | mmm system/vold/ |
Rild | make rild | mmm hardware/ril/rild/ |
Phone | make Phone | mmm packages/apps/Phone/ |
make命令编译framework-res.apk和framework.jar两个模块,它们编译的结果在out/target/product/generic/system/framework下。
利用adb命令将这两个文件push到手机的system/framework目录下即可替换旧的文件。(测试新模块前,需要杀掉所有使用该模块的进程)