阅读android源码,应该是每个android 开发者提升 技术最快的途径,如果感兴趣可以自己尝试编译一下android系统,本文编译环境是ubuntu16.04 ,编译的android版本是6.0 由于虚拟机配置比较低,编译器也比较慢,折腾了好几天。估计我的硬盘比我更辛苦,好了进入正题。

1.源码下载

Google采用Git对AOSP项目进行多仓库管理,所以需要先安装git,git的使用之前有记录过

1
2
3
sudo apt-get install git
git config --global user.email “test@qq.com”
git config --global user.name “tom”

安装git

参考科大源

按照 Google 官方教程 https://source.android.com/source/downloading.html

https://android.googlesource.com/platform/manifest 替换为 git://mirrors.ustc.edu.cn/aosp/platform/manifest。

具体做法摘录如下(以防墙抽风):

首先下载 repo 工具

1
2
3
4
5
6
7
mkdir ~/bin
PATH=~/bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
## 如果上述 URL 不可访问,可以用下面的:
## curl https://storage-googleapis.proxy.ustclug.org/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo

然后建立一个工作目录(名字任意)

1
2
mkdir WORKING_DIRECTORY
cd WORKING_DIRECTORY

初始化仓库:

1
2
3
repo init -u git://mirrors.ustc.edu.cn/aosp/platform/manifest -b android-6.0.1_r62
## 如果提示无法连接到 gerrit.googlesource.com,可以编辑 ~/bin/repo,把 REPO_URL 一行替换成下面的:
## REPO_URL = 'https://gerrit-googlesource.proxy.ustclug.org/git-repo'

有些时候 更换REPO_URL 依然连接失败,没关系 多试几次
如果需要某个特定的 Android 版本(Android 版本列表):

同步源码树(以后只需执行这条命令来同步):

1
repo sync

接下来就是等了,这个过程比较慢 我大概用了一晚上 才下完源码。
注:
在下载过程中会出现很多问题,所以创建一个自动下载脚本,确保出错后自动执行repo sync,要不睡一觉起来发下代码下载失败那多恼火。
先在 WORKING_DIRECTORY下创建一个脚本down.sh,代码如下:

1
2
3
4
5
6
7
#!/bin/bash
repo sync -j16
while [ $? = 1 ]; do
echo “======sync failed, re-sync again======”
sleep 3
repo sync -j16
done

执行命令

1
2
chmod a+x down.sh
./down.sh

这样明天早上起来一看 代码就下完了。大概50多G,所以如果用虚拟机编译的化,建议设置100G以上内存。
源码的文件夹中只有一个.repo文件夹,这是正常的,等到所有源码下载完毕,其余文件夹就会出现,不要着急

删除.repo

下载完源码后,会发现代码有50多G 其中有个隐藏文件夹.repo 他自己就有40多G ,这个文件夹只跟代码同步有关,并不影响编译,果断删除,删除后源码只有7G ,可以备份下源码

2.配置编译环境

更换软件源为阿里云

为了更快的安装软件,我们需要更换软件源为国内的软件源,这里推荐使用Ubuntu官方指定的国内软件源阿里云

1
sudo gedit /etc/apt/sources.list

在文件最前面加入下面代码:

1
2
3
4
5
6
7
8
9
10
deb http://mirrors.aliyun.com/ubuntu/ quantal main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ quantal-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ quantal-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ quantal-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ quantal-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ quantal main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ quantal-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ quantal-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ quantal-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ quantal-backports main restricted universe multiverse

1
sudo apt-get update

安装依赖

1
2
3
4
5
6
7
8
9
10
11
sudo apt-get install -y git flex bison gperf build-essential libncurses5-dev:i386
sudo apt-get install libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-dev g++-multilib
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 lib32z-dev ccache
sudo apt-get install libgl1-mesa-dev libxml2-utils xsltproc unzip m4
sudo apt-get install 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

Ubuntu 16.04请务必使用上面的依赖,Ubuntu 16.04需要的依赖和Ubuntu 14.04所需要的依赖是不同的,博主照着Ubuntu 14.04的依赖结果掉进大坑,详见后面的编译过程记录.

安装JDK

编译android源码 对应android版本对 ubuntu版本有要求

Android版本 编译要求的Ubuntu最低版本
Android 6.0至AOSP master Ubuntu 14.04
Android 2.3.x至Android 5.x Ubuntu 12.04
Android 1.5至Android 2.2.x Ubuntu 10.04
Android版本 编译要求的Ubuntu最低版本
AOSP的Android主线 OpenJDK 8
Android 5.x至android 6.0 OpenJDK 7
Android 2.3.x至Android 4.4.x Oracle JDK 6

更具体的可以参看:Google源码编译要求

这里我编译的是android6.0 用的是openjdk7
Ubuntu 15.04及之后的版本的在线安装库中只支持openjdk8和openjdk9的安装.因此,如果你想要安装openjdk 7需要首先设置ppa:

1
2
sudo add-apt-repository ppa:openjdk-r/ppa
sudo apt-get update

然后再执行安装命令:

1
sudo apt-get install openjdk-7-jdk

配置环境变量
打开/etc/profile文件:

1
sudo gedit /etc/profile

在末尾追加下面代码:

1
2
3
4
export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH

修改了/etc/profile文件需要重启才能生效,但使用下面命令可以在不重启的情况下在当前bash环境生效:

1
source /etc/profile

有时候,我们需要编译不同版本的android系统,就可能使用不同的jdk版本.关于jdk版本切换,可以使用如下命令:

1
2
3
sudo update-alternatives --config java
sudo update-alternatives --config javac
sudo update-alternatives --config javap

查询下JDK版本

1
java -version

修改源码

找到 WORKING_DIRECTORY/art/build/Android.common_build.mk 文件

1
ifneq ($(WITHOUT_HOST_CLANG),true)

改为

1
ifneq ($(WITHOUT_HOST_CLANG),false)

如果不修改这里,会遇到一个比较棘手的编译错误,

1
make:***[out/host/lnux-x86/obj/lib/libartd.so] Error 1

修改的目的是把CLANG这个编译选项关掉,详见后面的编译记录,百度搜狗都无解,这个错误只会在Ubuntu16.04上遇到,Ubuntu14.04则不存在这个问题,这里卡了好几天

编译

初始化编译环境

确保上述过程完成后,接下来我们需要初始化编译环境,命令如下:

1
source build/envsetup.sh

lunch
控制台上会显示 选择 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/ou're building on Linux
Lunch menu…pick a combo:
1. aosp_arm-eng
2. aosp_arm64-eng
3. aosp_mlps-eng
4. aosp_mlps64-eng
5. aosp_x86-eng
6. aosp_x86_64-eng
7. aosp_deb-userdebug
8. aosp_flo-userdebug
9. full_fugu-userdebug
10. aosp_fugu-userdebug
11. mlnl_emulator_arm64-userdebug
12. n_e_arm-userdebug
13. mlnl_emulator_mlps-userdebug
14. mlnl_emulator_x86_64-userdebug
15. mlnl_emulator_x86-userdebug
16. aosp_flounder-userdebug
17. aosp_hammerhead-userdebug
18. aosp_hammerhead_fp-userdebug
19. aosp_shanu-userdebug
rJhlch would you like? [aosp_arm-eng] |

这里说一下user userdebug eng

版本 描述
user 用于正式产品
userdebug 和user类似,但是有root权限,并且可以调试,主要用于调试
eng 开发用的选项,配有额外的调试工具

如果编译后只在模拟器上运行,则lunch时选择:1

如果你想更深一步了解lunch该选哪一个,请参考下面的链接,根据第三列选择编译选项
https://source.android.com/source/running.html

开始编译

通过make指令进行代码编译,该指令通过-j参数来设置参与编译的线程数量,以提高编译速度.比如这里我们设置8个线程同时编译: 一般google推荐这个数字为2倍的cpu个数再加上2,比如4核,就是10

1
make -j8

关于cpu个数,可以用下面命令查看:

1
cat /proc/cpuinfo

如果顺利,2个小时左右 就可以看到编译成功了,不过 应该是不可能的

还有其他常用命令 你肯定能遇到 make clean,make update-api

运行

编译的文件会在 out目录下 编译成功里面会包含 system.img userdate.img ramdisk.img

1
emulator

不出意外,你将运行起来一个 黏糊糊 热乎乎的 android6.0 没错 你看 他真的很丑。

总结

编译源码 前前后后一共用了一个 多星期,其中不少坑 ,文章里写的也只是 在编译后能记录下来,还有些坑想想都丢人 一般人也不会犯。