Ubuntu16.04 LTS环境下编译Android6.0源码

前言

十月国庆放假在家的时候,自己已经将用来下载android源码的初始化包下载完成,却一直没有时间下载源码。上周开发中研究监听软件盘弹出的时候,突然心血来潮要编译Android源码,说干就干,经过周末两天的不断尝试,终于编译成功。

博主使用清华大学开源软件镜像站的镜像下载源码,第一天下载源码的时候没有指定下载的版本,所以下载的是最新的8.1版本,编译过程中出现各种error,参考许多博客,最终有一些问题没有解决掉,决定放弃。第二天又重新下载了一次源码,指定下载的版本为6.0,然后参考博客Android 编译(一)] Ubuntu 16.04 LTS 成功编译 Android 6.0 源码教程编译成功。

编译环境

  • 硬件:联想R720( i7处理器 16G内存 250G固态 1T硬盘)
  • 系统:ubuntu16.04 LTS
  • Android 6.0_r1
  • Open JDK7(注意是openJdk,不是Sun公司的Jdk)
    自己电脑配置还算不错,编译过程耗费了三小时,如果电脑配置低的话可能耗时更长,加上各种报错,如果是第一次编译android源码,不要指望一天就可以编译成功,一定要做好打持久战的准备,

下载Android源码

参考博客:
Android Studio中调试Android源码
清华大学TUNA镜像源

注意: 因为无法访问google的官网,博主使用国内镜像(清华开源镜像站)下载源码。一定要指定下载的版本,否则下载的最新版本,编译的过程中遇到很多问题网上都搜不到解决答案。

1.首先要下载Repo(一个下载脚本)
具体的配置可以看参考博客使用Ubuntu16下载编译Android6.0源码

执行下边命令下载repo脚本

1
2
3
4
mkdir ~/bin
PATH=~/bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo //修改repo的权限为可执行

自己用浏览器可以科学上网,因为电脑没有配置全局代理,所以执行第三条命令时却无法下载该脚本。这时将网址复制到浏览器中下载,然后移动到~/bin中,效果是一样的。

2.下载月初始化包(32.8G),可以使用参考博客中的命令下载,也可以使用浏览器下载

1
wget -c https://mirrors.tuna.tsinghua.edu.cn/aosp-monthly/aosp-latest.tar

初始化包下载完成后:使用命令或者右键解压都行,解压完成后会生成一个名字为aosp文件夹,里边为空的,执行解压命令:

1
tar xf aosp-latest.tar

进入asop文件夹,使用ctrl + H 或者命令 ls -a 可以看到一个.repo隐藏文件夹,大小为32.8G

3.检出源码
指定源码的版本,进入asop目录,执行命令

1
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-6.0.0_r4  //指定下载的版本为6.0

如果提示无法连接到 gerrit.googlesource.com,可以编辑 ~/bin/repo,把 REPO_URL 一行替换成:

1
REPO_URL = 'https://mirrors.tuna.tsinghua.edu.cn/git/git-repo'

4.执行同步的命令

1
repo sync

源码所在的路径一律不能出现中文,否则会报类似错误UnicodeDecodeError: 'ascii' codec can't decode byte 0x

5.检出源码完成

asop中的文件有13G
.repo隐藏文件夹由原来的38.2G变为62G

6.查看下载源码的版本号:
进入/aosp/build/core目录中,打开version_defaults.mk文件,可以看到如下代码:(说明当前版本是6.0)

1
2
3
4
5
6
7
ifeq "" "$(PLATFORM_VERSION)"
# This is the canonical definition of the platform version,
# which is the version that we reveal to the end user.
# Update this value when the platform version changes (rather
# than overriding it somewhere else). Can be an arbitrary string.
PLATFORM_VERSION := 6.0
endif

配置JDK

编译不同版本的源码,需要不同版本的jdk,那么如何查看编译当前源码所需的JDK版本号呢?
打开aosp/build/core/main.mk文件,可以看到下边代码:

说明默认的版本为jdk7(最好是OpenJdkk),如果JDK的版本不正确的话,编译过程中,也会提示如下图的错误:

如果之前自己电脑是没有jdk,直接安装openJdk。
安装openJdk7只需要执行下边命令:

1
2
3
sudo add-apt-repository ppa:openjdk-r/ppa  
sudo apt-get update
sudo apt-get install openjdk-7-jdk

如果之前安装有jdk(如自己之前安装了jdk1.8),那么就需要进行jdk版本切换
切换方法参考博客Android实战技巧之八:Ubuntu下切换JDK版本
如果实在不会切换直接将系统环境变量设置为openJdk7
下边是博主的JDK环境变量配置信息:

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

然后执行source /etc/profile 使环境变量立即生效(也可一重启电脑)

输入java -version 命令检查jdk的版本是否设置成功

安装依赖环境,并修改源码

1.按照前言中的参考博客Android 编译(一)] Ubuntu 16.04 LTS 成功编译 Android 6.0 源码教程,添加编译需要的一些依赖,

1
2
3
4
5
6
7
8
9
10
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

2.修改源码
将aosp/art/build/Android.common_build.mk 文件中的代码:

1
ifneq ($(WITHOUT_HOST_CLANG),true)

修改为:

1
ifeq ($(WITHOUT_HOST_CLANG),false)

注意:看清楚,不仅仅是将true修改为false,而且要将ifneq修改为ifeq,自己就是粗心没有修改ifneq耽误了好长时间

执行编译

1.设置缓存
在当前用户的根目录下,按下ctrl + H,显示出隐藏文件,在.bashrc文件的最后一行添加:

1
export USE_CCACHE = 1

然后进入源码目录aosp中,执行下边命令设置缓存:

1
2
echo export USE_CCACHE=1 >> ~/.bashrc
prebuilts/misc/linux-x86/ccache/ccache -M 50G

2.接着导入编译Android源码所需的环境变量和其它参数:
下边没有特殊说明,命令都是在aosp目录(也就是存放源码的目录)中执行

1
source build/envsetup.sh

3.运行lunch命令选择编译目标:

1
lunch

出现下图

选择1:

4.执行编译(8表示 开8个线程编译)

1
make -j8

自己编译成功的图片:

5.运行模拟器
编译成功后,直接输入下方命令启动虚拟机:

1
emulator

但是自己的不行,提示找不到emulator命令的错误,
参考博客自己动手编译Android源码(超详细)在源码目录aosp中输入以下命令启动虚拟机:

1
2
3
source build/envsetup.sh
lunch(选择刚才你设置的目标版本,比如这里了我选择的是1)
emulator

耐心等待一会,就会出现以下界面:

错误记录

1.刚开始运行,就报出如下错误

自己一开始没有按照上边的步骤设置jdk的版本,所以 报出上图错误,将编译版本设置为openJdk7就可以解决上图中的错误

2.clang错误,如下图

自己一开始按照前言中的参考博客,在“对源码修改一步”中由于粗心,没有将ifneq修改为ifeq,所以仍然报出此错误。后来,将ifneq修改为ifeq就可以成功编译了

整个编译过程与前一天编译8.1版本相比还算顺利,只出现了以上两个错误。

编译总结

总结自己编译的步骤,共分以下几步:
1.下载源码(使用国内镜像下载)

  • 下载repo脚本
  • 下载初始化包aosp-latest.tar(32.8G)
  • 指定下载的版本
  • 检出源码(repo sync)

2.配置编译的环境
本篇博客使用的是系统是ubuntu16.04,所以和ubuntu14.04编译环境不一样

  • 设置jdk的版本:openJdk7(一定要注意JDK的版本)
  • 安装编译过程需要的依赖包,并修改源码(修改源码这一步一定要看仔细喽)
  • 设置编译所需要的缓存

3.执行编译

下一篇博客将学习如何使用Android-studio调试android源码
非常感谢blog.csdn.net/fuchaosz/article/details/51487585博主的教程。