一、编译源码的背景环境
Android源码编译有什么困难
- AOSP 非常庞大,需要下载,但是他是Google家的,和大陆开发者之间隔着一个GFW
- 官方文档 推荐使用Ubuntu 14.04进行编译。我用的是MacOS,官网也给了Mac下的编译方式,不过看起来还是挺麻烦的。而且我怕搞乱我的电脑。
针对上面的两点,以前有这么两种解决方式,以前有这么几种解决方式
- 至于下载慢,可以使用国内镜像清华镜像 和 科大镜像,好像现在google的开发者网站部分不用梯子就可以访问了[当前时间2017-04]
- 有人使用虚拟机,然后安装Ubuntu,然后编译源码。这方式也可以,但是Mac下三种虚拟机,免费的那个还不好用。而且编译本身就比较消耗资源,再装个虚拟机就更麻烦了
后来有人提出用Docker
而且这个人搞了一份Docker镜像出来 kylemanna/docker-aosp,后来有人针对Docker以及天朝的网络环境做了一部分修改,fork了一份国产的 tiann/docker-aosp。主要是修改了shell脚本中的下载源。但是这个东西在MAC OS上有bugissues 19所以我就没用成功。
有一点题外话需要说一下,这个Docker安装后会开机默认启动,默认启动倒是也没问题,有问题的是他不可以和Android虚拟机同时运行,就是AndroidStudio自带的那个虚拟机。
二、搭建Mac编译环境
修改文件描述符限制
在~/.bash_profile
中添加以下内容
#set the number of open files to be 1024
ulimit -S -n 1024
开发环境要求
1、 Mac OS v10.10 (Yosemite) 或以上,安装了 Xcode 4.5.2或以上,安装了Command Line Tools。
2、安装JDK 7。
3、安装了python 2.7
4、GNU Make 3.81或3.82
5、Git
我本机环境
- Mac OS v10.12.4
- xcode v8.0
- git version 2.8.4 (Apple Git-73)
- GNU Make 3.81
- 为了编译不同版本的Android源码,同时安装了JDK7 & JDK8,通过配置
.bash_profile
来切换 - Python 2.7.11
- 之前我电脑还安装了homebrew
磁盘分区
为什么在Mac上编译会很麻烦呢,因为Mac的文件系统默认不区分大小写,但是Android源码编译系统的要求区分大小写,这时候我们可以创建个区分大小写的磁盘空间(磁盘映像)。方法如下:
- 打开
磁盘工具
(在Launchpad中直接搜索就行) - 如下图操作(磁盘映像命名为AOSP,磁盘映像大小为100G,磁盘格式一定要选择区分大小写) 首先选中
Macintosh HD
然后Comand + N
(或者 菜单栏选择 --> 文件-->新建映像-->空白映像)
注意:这个磁盘映像的名字后面要用到,磁盘大小好像官网推荐70G,以防不够还是大点吧,格式一定要选
区分大小写
。对应磁盘的映像使用,有人为了节省Mac上的硬盘,也为了防止搞坏系统,用了外接硬盘的方式然后操作这个外接硬盘的分区。如果是使用移动硬盘可以直接把硬盘格式化成 Mac OS 扩展(区分大小写,日志式)
下载Android源码
下面是科大的源也可以用清华的参考文献,我下载的是Android6.0的源码,最终编译的时候选择的是x86_64
- 下载 repo 工具:
mkdir ~/bin
PATH=~/bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
- 建立工作目录:
cd /Volumes/AOSP/
mkdir WORKING_DIRECTORY
cd WORKING_DIRECTORY
- 初始化仓库
repo init -u git://mirrors.ustc.edu.cn/aosp/platform/manifest
## 如果提示无法连接到 gerrit.googlesource.com,可以编辑 ~/bin/repo,把 REPO_URL 一行替换成下面的:
## REPO_URL = 'https://gerrit-googlesource.proxy.ustclug.org/git-repo'
如果需要某个特定的 Android 版本(Android 版本列表),可以通过下面的方式指定版本号,如果不指定则代码下载当前最新的代码。
repo init -u git://mirrors.ustc.edu.cn/aosp/platform/manifest -b android-6.0.1_r46
注:在mac上运行这行可能会报错,GnuPG 这玩意不可用,解决方式看最后错解决
- 同步源码树(以后只需执行这条命令来同步)如果中途出现网络错误,可以停止后在执行下面的命令:
repo sync
注意:科大的镜像服务器限制了并发数,“由于硬盘 I/O 资源有限,Git 服务器每 IP 限制 5 个并发连接。repo sync 命令默认使用 4 个并发连接,请勿使用 -j 参数增加并发连接数。”
然后就等着吧0_0
编译源码
如果想把编译后的img刷入真机的话,需要下载驱动,下载对应版本的驱动文件,依次解压,将其置于源码根目录中,再依次执行这些脚本,执行操作前,它会让你阅读相关协议,协议比较多有8项,最后输入 I ACCEPT 即可。执行完成以后会在源码的主目录生成一个vendor目录。注意执行shell的顺序。
- 清空缓存
$ make clobber
注:如果运行这行命令出错看文章最后错误处理
- 配置编译环境
$ source build/envsetup.sh
- 选择编译目标
$ lunch
这时候会列出一系列的选项然后选择一个如下:
You're building on Darwin
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. full_fugu-userdebug
8. aosp_fugu-userdebug
9. mini_emulator_arm64-userdebug
10. m_e_arm-userdebug
11. m_e_mips-userdebug
12. m_e_mips64-eng
13. mini_emulator_x86-userdebug
14. mini_emulator_x86_64-userdebug
15. aosp_dragon-userdebug
16. aosp_dragon-eng
17. aosp_marlin-userdebug
18. aosp_sailfish-userdebug
19. aosp_flounder-userdebug
20. aosp_angler-userdebug
21. aosp_bullhead-userdebug
22. hikey-userdebug
23. hikey960-userdebug
24. aosp_shamu-userdebug
Which would you like? [aosp_arm-eng]
然后直接输入上面选项的序号就好了这里,我选择第一个,至于上面那些名字的含义是啥看下面解释:
官网说根据上面名字的后缀可以判断要编译那种类型的:
- user: limited access; suited for production(有限的访问权限,一般用于发布版)
- userdebug: 这个和user类似,但是可以获取root权限,并且能够调试
- eng: 具有开发配置,并且有额外的调试工具(注:工程师模式engineer)
lunch
命令也可以直接这么用 $ lunch aosp_arm-eng
- 开始编译
make -j16
这里指定的开启几个并行task
来进行编译,官网建议j后面的数字根据你电脑的线程数量的1~2倍来设置,比如电脑是双核CPU,每个CPU为双核心四线程,那么就有8个线程。所以我配置的数量为16。
然后就是漫长的等待ing...
启动模拟器
$ source build/envsetup.sh
-
$ lunch
(选择刚才你设置的目标版本,我编译的是x86_64-eng的那个) -
$ emulator
模拟器启动,这个命令有很多复杂用法,具体可参考官网。
烧录镜像到机器中
这个烧录过程我没有测试,官网是这么写的。
- 进入fastboot模式
$ adb reboot bootloader
- 把img文件刷进去
$ fastboot flashall -w
这个-w
是为了wipes the /data partition
擦除/data
分区
如果编译前没有下载驱动,即使刷入,还是无法进入系统,此时,只需要重新下载驱动,再次执行编译命令。
AndroidStudio中查看源码
在android源码中有这么一个目录development/tools/idegen。
顾名思义,是生成ide的project文件,主要是生成intellij的project文件,可用于AndroidStudio。
- 在整个Android源码全编成功之后,然后编译idegen模块,用以生成Android studio的工程配置文件,编译成功之后就生成了idegen.jar(out/host/darwin-x86/framework/idegen.jar),运行如下命令:
$ mmm development/tools/idegen/
注:如果刚才编译AOSP的那个命令行窗口关闭了,必须要在执行
source build/envsetup.sh
一次,用了初始化编译环境。
- 在源码根目录生成对应的android.ipr、android.iml IEDA工程配置文件。以便于AndroidStudio可以打开项目
$ . development/tools/idegen/idegen.sh
- 打开Android studio,点击File --> Open,选择刚刚生成的android.ipr就好了。
三、错误处理
执行repo init
的错误
错误1描述
warning: gpg (GnuPG) is not available.
warning: Installing it is strongly encouraged.
解决方法:
原因是GnuPG for osx没有安装,去https://www.gnupg.org/download/下载安装即可。
我用homebrew安装的brew install gnupg
执行make clobber
的错误
错误1描述:
build/core/config.mk:660: error: Error: could not find jdk tools.jar at /System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/../lib/tools.jar, please check if your JDK was installed correctly.
17:29:26 ckati failed with: exit status 1
解决方式:
在~/.bash_profile
添加如下代码
export JAVA_8_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home
export JAVA_HOME=$JAVA_8_HOME
##上面是jdk的配置,主要是添加下面这一行
export ANDROID_JAVA_HOME=$JAVA_HOME
错误2描述
build/core/combo/mac_version.mk:38: *****************************************************
build/core/combo/mac_version.mk:39: * Can not find SDK 10.6 at /Developer/SDKs/MacOSX10.6.sdk
build/core/combo/mac_version.mk:40: *****************************************************
build/core/combo/mac_version.mk:41: *** Stop.. Stop.
解决方法:
出现这个错误是因为xcode的版本不对,首先查看本机安装xcode的版本,
$ cd /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/
然后修改build/core/combo/mac_version.mk
这个文件中的下面这行,把本机的版本号添加到下面,我的是10.12 添加后如下:
mac_sdk_versions_supported := 10.6 10.7 10.8 10.9 10.12
错误3描述:
system/core/libcutils/threads.c:38:10: error: 'syscall' is deprecated: first deprecated in OS X 10.12 - syscall(2) is unsupported; please switch to a supported interface. For SYS_kdebug_trace use kdebug_signpost(). [-Werror,-Wdeprecated-declarations]
return syscall(SYS_thread_selfid);
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include/unistd.h:733:6: note: 'syscall' has been explicitly marked deprecated here
int syscall(int, ...);
^
1 error generated.
解决方式:
这个错误3归根到底是因为错误2引起的,再归根下是xcode版本引起的,(为啥说在mac上编译麻烦,这个xcode版本会出这么多破事),没办法这个我们上面用的mac sdk 10.12 版本太高了,这个版本废弃了某些方法导致编译不可用,那就去下个低版本的吧传送门,压缩包在这然后下载那个10.11。理论上来说,下载后把目录放到这个路径下/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/
和这个MacOSX10.12.sdk
目录平级就行了,然后把错误2中添加到build/core/combo/mac_version.mk
中的那个10.12改成10.11就好了。但是这个东西貌似在下次xcode升级的时候会被删掉。
a oh so? 弄个软连接:
$ mkdir ~/lib
然后把下载的压缩包解压到~/lib
下
$ sudo ln -s ~/lib/MacOSX10.11.sdk /Applications/XCode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk