⾃⼰动⼿编译Android源码(超详细)
在⼀⽂中,简单的介绍了代码调试的⼀些技巧.现在我们来谈谈android源码编译的⼀些事.(俺认为,作为android developer⼈⼈都应该有⼀份⾃⼰Android源码,这样我们就可以随时对⾃⼰有疑惑的地⽅通过亲⼿调试来加强理解).
本⽂使⽤最新的Ubuntu 16.04,请⾸先确保⾃⼰已经安装了Git.没安装的同学可以通过以下命令进⾏安装:
sudo apt-get install git
curl是什么命令git config –ail “test@test”
git config –global user.name “test”
其中test@test为你⾃⼰的邮箱.
简要说明
android源码编译的四个流程:1.源码下载;2.构建编译环境;3.编译源码;4运⾏.下⽂也将按照该流程讲述.
源码下载
由于某墙的原因,这⾥我们采⽤国内的镜像源进⾏下载.
⽬前,可⽤的镜像源⼀般是科⼤和清华的,具体使⽤差不多,这⾥我选择清华⼤学镜像进⾏说明.(参考:,)
repo⼯具下载及安装
通过执⾏以下命令实现repo⼯具的下载和安装
mkdir ~/bin
PATH=~/bin:$PATH
curl leapis/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
补充说明
这⾥,我来简单的介绍下repo⼯具,我们知道AOSP项⽬由不同的⼦项⽬组成,为了⽅便进⾏管理,Google采⽤Git对AOSP项⽬进⾏多仓库管理.在聊repo⼯具之前,我先带你来聊聊多仓库项⽬:
我们有个⾮常庞⼤的项⽬Pre,该项⽬由很多个⼦项⽬R1,R2,…Rn等组成,为了⽅便管理和协同开发,我们为每个⼦项⽬创⽴⾃⼰的仓库,整个项⽬的结构如下:
这⾥写图⽚描述
将⼀个项⽬Pre进⾏分库后会遇到这么⼀个问题:如果我们想要创建Pre分⽀来做feature开发,这就意味着,我们需要到每个⼦项⽬中分别创建对应的分⽀,这个过程如果纯粹靠⼿⼯做,那简直是个灾难,利索当然我们会想写个⾃动化处理程序(我们假设这个⼯具叫做RepoUtil)来帮助我们解决这个问题.这个RepoUtil也会有版本管理之类的需求,因此我们也⽤Git对其管理,并为其创建对应的仓库.此时整个项⽬的结构如下:
这⾥写图⽚描述
这⾥RepoUtil知道整个项⽬Pre下的每个⼦项⽬(即维护⼦项⽬的列表),同时需要提供对这些⼦项⽬的管理功能,⽐如统⼀创建分⽀等.但是从”单⼀职责”⾓度来看,RepoUitl这个⼯具的功能过于复杂,我们完全可以将维护⼦项⽬列表这个功能抽取出来作为⼀个新项⽬sub_projects,因为⼦项⽬也会变化,因此,为其创建对应的仓库,并⽤Git管理,这样的化,RepoUtil只需要通过简单的对ub_projects进⾏依赖即可,此时整个项⽬的结构如下:
这⾥写图⽚描述
AOSP项⽬结构和我上⽂的描述⾮常类似.repo⼯具对应RepoUtil,mainfest对应sub_projects.
总结⼀下:repo就是这么⼀种⼯具,由⼀系列python脚本组成,通过调⽤Git命令实现对AOSP项⽬的管理.
建⽴源码⽂件夹
熟悉Git的同学都应该知道,我们需要为项⽬在本地创建对应的仓库.同样,这⾥为了⽅便对代码进⾏管理,我们为其创建⼀个⽂件夹.这⾥我在当前⽤户⽬录下创建了source⽂件夹,后⾯所有的下载的源码和编译出的产物也都放在这⾥,命令如下:
mkdir source
cd source
初始化仓库
我们将上⾯的source⽂件夹作为仓库,现在需要来初始化这个仓库了.通过执⾏初始化仓库命令可以获取AOSP项⽬master上最新的代码并初始化该仓库,命令如下:
repo init -u aosp.tuna.tsinghua.edu/platform/manifest
或者使⽤:
repo init -u git://aosp.tuna.tsinghua.edu/aosp/platform/manifest
两者实现的效果⼀致,仅仅只是协议不同.
如果执⾏该命令的过程中,如果提⽰⽆法连接到 lesource,那么我们只需要编辑 ~/bin/repo⽂件,到REPO_URL这⼀⾏,然后将其内容修改为:
REPO_URL = 'gerrit-google.tuna.tsinghua.edu/git-repo'
然后重新执⾏上述命令即可.
补充说明
不带参数的manifest命令⽤于获取master上最新的代码,但是可以通过-b参数指定获取某个特定的android版本,⽐如我们想要获取android-4.0.1_r1分⽀,那么命令如下:
repo init -u aosp.tuna.tsinghua.edu/platform/manifest -b android-4.0.1_r1
(AOSP项⽬当前所有的分⽀列表参看:)
同步源码到本地
初始化仓库之后,就可以开始正式同步代码到本地了,命令如下:
repo sync
以后如果需要同步最新的远程代码到本地,也只需要执⾏该命令即可.在同步过程中,如果因为⽹络原因中断,使⽤该命令继续同步即可.不出意外,5个⼩时便可以将全部源码同步到本地.所以呢,这个过程可以放在晚上睡觉期间完成.
(提⽰:⼀定要确定代码完全同步了,不然在下⾯编译过程出现的错误会让你痛不欲⽣,不确定的童鞋可以多⽤repo sync同步⼏次)
构建编译环境
源码下载完成后,就可以构建编译环境了.在开始之前,我们先来看看⼀些编译要求:
1. 硬件要求:
64位的操作系统只能编译2.3.x以上的版本,如果你想要编译2.3.x以下的,那么需要32位的操作系统.
磁盘空间越多越好,⾄少在100GB以上.意思就是,你可以去买个⼤点的硬盘了啊
如果你想要在是在虚拟机运⾏linux,那么⾄少需要16GB的RAM/swap.
(实际上,我⾮常不推荐在虚拟机中编译2.3.x以上的代码.)
2. 软件要求:
1. 操作系统要求
在中,主分⽀使⽤Ubuntu长期版本开发和测试的,因此也建议你使⽤Ubuntu进⾏编译,下⾯我们列出不同版本的的Ubuntu能够编译那些android版本:
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
2. JDK版本要求
除了操作系统版本这个问题外,我们还需要关注JDK版本问题,为了⽅便,同样我们也列出的不同Android版本的源码需要⽤到的JDK版本:
Android版本编译要求的JDK版本
AOSP的Android主线OpenJDK 8
Android 5.x⾄android 6.0OpenJDK 7
Android 2.3.x⾄Android 4.4.x Oracle JDK 6
Android 1.5⾄Android 2.2.x Oracle JDK 5
更具体的可以参看:
我现在在Ubuntu 16.04下编译AOSP主线代码,因此需要安装OpenJDK 8,执⾏命令如下:
sudo apt-get install openjdk-8-jdk
如果你需要在Ubuntu 14.04下编译AOSP主线代码,同样需要安装OpenJDK 8,此时需要执⾏如下命令:
sudo apt-get update
sudo apt-get install openjdk-8-jdk
如果你要编译的是Android 5.x到android 6.0之间的系统版本,需要采⽤openjdk7.但是在Ubuntu 15.04及之后的版本的在线安装库中只⽀持openjdk8和openjdk9的安装.因此,如果你想要安装openjdk 7需要⾸先设置ppa:
sudo add-apt-repository ppa:openjdk-r/ppa
sudo apt-get update
然后再执⾏安装命令:
sudo apt-get install openjdk-7-jdk
有时候,我们需要编译不同版本的android系统,就可能使⽤不同的jdk版本.关于jdk版本切换,可以使⽤如下命令:
sudo update-alternative --config java
sudo update-alternative --config javac
3. 其他要求
中已经说明了Ubuntu14.04,Ubuntu 12.04,Ubuntu 10.04需要添加的依赖,这⾥我们就不做介绍了.我原先以为,Ubuntu16.04的设置和Ubuntu14.04的依赖设置应该差不多,但是只能说too young too simple.
下⾯是Ubuntu16.04中的依赖设置:
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
(其中⼏个命令中参数是重复的,但不妨碍我们)
初始化编译环境
确保上述过程完成后,接下来我们需要初始化编译环境,命令如下:
source build/envsetup.sh
执⾏该命令结果如下:
这⾥写图⽚描述
不难发现该命令只是引⼊了其他执⾏脚本,⾄于这些脚本做什么,⽬前不在本⽂中细说.
该命令执⾏成功后,我们会得到了⼀些有⽤的命令,⽐如最下⾯要⽤到的lunch命令.
编译源码
初始化编译环境之后,就进⼊源码编译阶段.这个阶段⼜包括两个阶段:选择编译⽬标和执⾏编译.
选择编译⽬标
通过lunch指令设置编译⽬标,所谓的编译⽬标就是⽣成的镜像要运⾏在什么样的设备上.这⾥我们设置的编译⽬标是aosp_arm64-eng,因此执⾏指令:
lunch aosp_arm64-eng
编译⽬标格式说明
编译⽬标的格式:BUILD-BUILDTYPE,⽐如上⾯的aosp_arm-eng的BUILD是aosp_arm,BUILDTYPE是eng.
什么是BUILD
BUILD指的是特定功能的组合的特定名称,即表⽰编译出的镜像可以运⾏在什么环境.其中,aosp(Android Open Source Project)代表Android开源项⽬;arm表⽰系统是运⾏在arm架构的处理器上,arm64则是指64位arm架构;处理器,x86则表⽰x86架构的处理器;此外,还有⼀些单词代表了特定的Nexus设备,下⾯是常⽤的设备代码和编译⽬标,更多参考
|受型号|设备代码|编译⽬标|
|—|—-|—|
|Nexus 6P|angler|aosp_angler-userdebug|
|Nexus 5X|bullhead|aosp_bullhead-userdebug|
|Nexus 6|shamu|aosp_shamu-userdebug|
|Nexus 5|hammerhead|aosp_hammerhead-userdebug|
提⽰:如果你没有Nexus设备,那么通常选择arm或者x86即可
什么是BUILDTYPE
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论