在Android Studio代码调试一文中,简单的介绍了Android Studio代码调试的一些技巧.现在呢,我们来谈谈android源码编译的一些事.(俺认为,作为android developer人人都应该有一份自己Android源码,这样我们就可以随时对自己有疑惑的地方通过亲手调试来加强理解). 本文使用最新的Ubuntu 16.04,在开始之前,请首先确保自己已经安装了Git.没安装的同学可以通过以下命令进行安装: sudo apt-get install git
git config –global user.email “test@test.com”
git config –global user.name “test” 其中test@test.com为你自己的邮箱. 在步入正题之前,我们先来说一下android源码编译的四个流程:1.源码下载;2.构建编译环境;3.编译源码;4运行.下文也将按照该过程进行讲述. 源码下载由于某墙的原因,这里我们采用国内的镜像源进行下载.目前,可用的镜像源一般是科大和清华的,具体使用差不多,这里我选择清华大学镜像进行说明.参考:(科大源,清华源) repo工具下载及安装通过执行以下命令实现repo工具的下载和安装 mkdir ~/bin
PATH=~/bin:$PATH
curl https://storage./git-repo-downloads/repo > ~/bin/repo
chmod a x ~/bin/repo 这里,我来简单的介绍下repo工具,我们知道AOSP项目由不同的子项目组成,为了方便进行管理,Google采用Git对AOSP项目进行多仓库管理.在聊repo工具之前,我先带你来聊聊多仓库项目:
AOSP项目结构和我上文的描述非常类似.repo工具对应RepoUtil,mainfest对应sub_projects. 建立源码文件夹熟悉Git的同学都应该知道,我们需要为项目在本地创建对应的仓库.同样,这里为了方便对代码进行管理,我们为其创建一个文件夹.这里我在当前用户目录下创建了source文件夹,后面所有的下载的源码和编译出的产物也都放在这里,命令如下: mkdir source
cd source 初始化仓库我们将上面的source文件夹作为仓库,现在需要来初始化这个仓库了.通过执行初始化仓库命令可以获取AOSP项目master上最新的代码并初始化该仓库,命令如下: repo init -u https://aosp.tuna./platform/manifest 或者使用: repo init -u git://aosp.tuna./aosp/platform/manifest 两者实现的效果一致,仅仅只是协议不同. REPO_URL = 'https://gerrit-google.tuna./git-repo' 然后重新执行上述命令即可. 不带参数的manifest命令用于获取master上最新的代码,有时候,我们想要指定的某个版本的源码,此时可以通过-b参数指定获取某个特定的android版本,比如我们想要获取android-4.0.1_r1分支,那么命令如下: repo init -u https://aosp.tuna./platform/manifest -b android-4.0.1_r1 (这里AOSP项目当前所有的分支列表可以在官网查看:分支列表) 同步源码到本地初始化仓库之后,就可以开始正式同步代码到本地了,命令如下: repo sync 以后如果需要同步远程代码到本地,也只需要执行该命令即可.在同步过程中,如果因为网络原因中断,使用该命令继续同步即可.不出意外,5个小时便可以将全部源码同步到本地.所以呢,这个过程可以放在晚上睡觉期间完成. (提示:一定要确定代码完全同步了,不然在下面编译过程出现的错误会让你痛不欲生,不确定的童鞋可以多用repo sync同步几次) 构建编译环境源码下载完成后,就可以构建编译环境了.在开始之前,我们先来看看一些编译要求: 1. 硬件要求: 2. 软件要求:
2. JDK版本要求
更具体的可以参看:Google源码编译要求 我现在在Ubuntu 16.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. 其他要求 Google官方构建编译环境指南中已经说明了Ubuntu14.04,Ubuntu 12.04,Ubuntu 10.04需要添加的依赖,这里我们就不做介绍了.我原先以为,Ubuntu16.04的设置和Ubuntu14.04的依赖设置应该差不多,但是只能说too young too simple. 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指令设置要要编译的具体版本.比如,在这里我们要编译aosp_arm64-eng,因此执行指令: lunch aosp_arm64-eng 如果你不知道自己要编译什么版本,那么只需要执行不带参数的lunch指令.之后,控制台会列出当前源码支持的所有设备型号及编译类型: 这里写图片描述
开始编译通过make指令进行代码编译,该指令可以指定 make -j8 需要注意的是,参与编译的线程并不是越多越好,通常是根据你机器cup的核心来确定:core*2,即当前cpu的核心的2倍.比如,我现在的笔记本是双核四线程的,因此根据公式,最快速的编译可以make -j8. 如果一切顺利的化,在几个小时之后,便可以编译完成.看到 运行模拟器在编译完成之后,就可以通过以下命令运行Android虚拟机了,命令如下: source build/envsetup.sh
lunch(选择刚才你设置的目标版本,比如这里了我选择的是2)
emulator 如你是在编译完后立刻运行虚拟机,由于我们之前已经执行过source及lunch命令了,因此现在你只需要执行命令就可以运行虚拟机: emulator 不出意外,在等待一会之后,你会看到运行界面: 这里写图片描述
既然谈到了模拟器运行,这里我们顺便介绍模拟器运行所需要四个文件:
上面我在使用lunch命令时选择的是aosp_arm64-eng,因此linux默认使用的 模块编译通过make命令编译可以整个android源码,这种需求相对较少.更多的情况是,我们修改或者新增一些模块,那么如何编译单独的模块呢? Google也为开发者提供了相应的命令来支持单独的模块的编译.上面我们提到envsetup.sh为我们提供了一些命令,除了我们上边用到的lunch之外,还有这些: - croot: Changes directory to the top of the tree.
- m: Makes from the top of the tree.
- mm: Builds all of the modules in the current directory.
- mmm: Builds all of the modules in the supplied directories.
- cgrep: Greps on all local C/C files.
- jgrep: Greps on all local Java files.
- resgrep: Greps on all local res/*.xml files.
- godir: Go to the directory containing a file. 这里我最为常用的就是mmm,也就是用来编译指定目录.通常来说,每个目录只包含一个模块.比如这里我们编译Launcher2模块: mmm packages/apps/Launcher2/ 稍等一会之后,如果提示 编译好指定模块后,如果我们想要将该模块对应的apk集成到系统镜像中,需要借助 我们在不断的修改某些模块,总不能每次重新编译完成后都要重新打包system.img,然后重启手机吧.有没有什么简单的方法呢?
SDK编译如果你需要自己编译SDK使用,很简单,只需要执行命令 错误集合在编译过程中,基本上会遇到各种各样的错误,大部分错误我们都可以在google搜到响应的解决方案.这里只简单的列举我遇到的几个错误: 这里写图片描述
错误二: Out of memory error.具体错误如下: 这里写图片描述
方法二: export JACK_SERVER_VM_ARGUMENTS='-Dfile.encoding=UTF-8 -XX: TieredCompilation -Xmx4096m'
out/host/linux-x86/bin/jack-admin kill-server
out/host/linux-x86/bin/jack-admin start-server 如图: 这里写图片描述
错误三:使用emulator时,虚拟机停在黑屏界面,点击无任何响应.此时,可能是kiner内核问题,解决方法如下: ./out/host/linux-x86/bin/emulator -partition-size 1024 -kernel ./prebuilts/qemu-kernel/arm/kernel-qemu-armv7 通过使用kernel-qemu-armv7内核 解决模拟器等待黑屏问题.而-partition-size 1024 则是解决警告: system partion siez adjusted to match image file (163 MB >66 MB)问题. 如果你一开始编译的版本是aosp_arm-eng,使用上述命令仍然不能解决等待黑屏问题时,不妨编译aosp_arm64-eng试试. 到现在为止,我们已经说明了整个android编译的流程,除此之外,也简单的android源码的多仓库管理机制.下面,你需要的就是,自动动手,为自己编译一份源码.后面,我会继续在此基础上增加一些原理的说明,并结合Android Studio进行源码调试. 著作权归作者所有 |
|
来自: 昵称32649950 > 《文学》