动手实现Android源码(AOSP)的下载、编译、运行、导入、调试
这几天为了搞Android源码费了不少功夫,也遇到了不少坑,在此记录作为日后参考。Android源码的编译运行只支持Linux和Mac系统,至于Windows系统只能绕道了,或是在虚拟机上安装Linux系统也是可以的。本人的系统是macOS 10.12.3,Xcode的版本是7.1。
官方教程地址为:https://source.android.com/source/index.html
一、搭建Mac系统编译环境
1、创建大小写敏感的磁盘映像
Linux和friends系统是大小写敏感的,而Windows和Mac系统正好相反,大小写不敏感,也就是说相同目录下不能同时存在aa和AA两个文件。
但是Android是基于Linux的,所以为了能够在Mac上编译运行就必须先创建一个大小敏感的磁盘印象。
下载Android 6.0的源码大约需要50GB,编译后涨到70GB左右。当然,如果磁盘空间紧张,下载源码后,你可以手动将源码根目录下的.repo目录删除,这样大约可以节省35GB的空间。我建议最好80GB空间以上,因为我的磁盘空间比较大,就直接设置为100GB。
- 使用磁盘工具创建
打开应用程序中的磁盘工具—>文件—>新建映像—>空白映像—>设置名称、大小、格式则必须选择Mac OS扩展(区分大小写,日志式),储存后,双击储存位置的磁盘名.dmg即可挂载该硬盘。
- 使用命令行创建
创建磁盘空间:
hdiutil create -type SPARSE -fs 'Case-sensitive Journaled HFS+' -size 100g ~/android.dmg
在当前的目录下会生成android.dmg.sparseimage文件,一旦挂载上,就是一个Android开发所需要的文件系统格式的磁盘。当然你也可调整磁盘空间的大小,可以使用下面的命令:
hdiutil resize -size <new-size-you-want>g ~/android.dmg.sparseimage
挂载磁盘映像:
当磁盘空间创建后,需要挂载才能使用,可以通过如下的命令进行挂载:
# mount the android file image
function mountAndroid { hdiutil attach ~/android.dmg.sparseimage -mountpoint /Volumes/android; }
取消挂载命令:
# unmount the android file image
function umountAndroid() { hdiutil detach /Volumes/android; }
你可以把上面的两个命令添加到~/.bash_profile文件中,就可以直接通过mountAndroid和umountAndroid命令进行挂载和卸载。
一旦挂载后,你就可以看见在/Volumes/中挂载了一个叫android的磁盘。
2、安装JDK和Xcode
编译不同版本的Android源码所需要的软件支持也不一样:
GNU/Linux系统
- Android 6.0 (Marshmallow) - AOSP master: Ubuntu 14.04 (Trusty)
- Android 2.3.x (Gingerbread) - Android 5.x (Lollipop): Ubuntu 12.04 (Precise)
- Android 1.5 (Cupcake) - Android 2.2.x (Froyo): Ubuntu 10.04 (Lucid)
Mac OS (Intel/x86)系统
- Android 6.0 (Marshmallow) - AOSP master: Mac OS v10.10 (Yosemite) or later with Xcode 4.5.2 and Command Line Tools
- Android 5.x (Lollipop): Mac OS v10.8 (Mountain Lion) with Xcode 4.5.2 and Command Line Tools
- Android 4.1.x-4.3.x (Jelly Bean) - Android 4.4.x (KitKat): Mac OS v10.6 (Snow Leopard) or Mac OS X v10.7 (Lion) and Xcode 4.2 (Apple’s Developer Tools)
- Android 1.5 (Cupcake) - Android 4.0.x (Ice Cream Sandwich): Mac OS v10.5 (Leopard) or Mac OS X v10.6 (Snow Leopard) and the Mac OS X v10.5 SDK
Java Development Kit (JDK)
- The master branch of Android in AOSP: Ubuntu - OpenJDK 8, Mac OS - jdk 8u45 or newer
- Android 5.x (Lollipop) - Android 6.0 (Marshmallow): Ubuntu - OpenJDK 7, Mac OS - jdk-7u71-macosx-x64.dmg
- Android 2.3.x (Gingerbread) - Android 4.4.x (KitKat): Ubuntu - Java JDK 6, Mac OS - Java JDK 6
Android 1.5 (Cupcake) - Android 2.2.x (Froyo): Ubuntu - Java JDK 5
具体可以参考官网文档:https://source.android.com/source/requirements.html,因为本人编译的是Android 6.0而且是MacOS 10.12系统,所以安装了JDK7和Xcode7.1。至于如何安装,网上教程很多这里就不再叙述。
3、安装MacPort
MacPort一款方便在Shell模式下进行下载、安装、编译、更新的软件,下载地址。安装完成后,请确保环境变量中/opt/local/bin是否在/usr/bin之前,如果没有请在~/.bash_profile文件中进行设置:
export PATH=/opt/local/bin:$PATH
4、设置文件同时打开数量
在Mac中,默认的文件同时打开数实在太低,一个高速并行的编译进程运行时可能会遇到瓶颈。为了增加最大文件打开数量,在~/.bash_profile中添加如下:
# set the number of open files to be 1024
ulimit -S -n 1024
二、下载Android源码
由于墙的原因,直接去google官方下载会很慢,这里推荐用中科大镜像。
1、下载repo工具
# 在用户目录创建一个bin文件夹
mkdir ~/bin
# 将该目录临时添加进环境变量
PATH=~/bin:$PATH
# 从镜像下载repo工具
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
# 给repo添加执行权限
chmod a+x ~/bin/repo
为了~/bin下面的命令以后可以直接访问,我把~/bin这个目录配置一下环境变量,在.bash_profile文件中添加如下,放在刚刚配置的MacPort之后:
export PATH="/opt/local/bin:/opt/local/sbin:~/bin:$PATH"
修改完毕后,为了让配置立即生效,输入:
source .bash_profile
2、初始化仓库
在之前所创建的大小写敏感磁盘中创建存储源码的目录:
mkdir aosp
cd aosp
进入该目录,然后执行下面的命名进行仓库的初始化:
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'
默认是master分支,如果需要某个特定的 Android 版本,请用如下的命令,-b 表示分支的切换:(Android版本列表,需翻墙)
repo init -u git://mirrors.ustc.edu.cn/aosp/platform/manifest -b android-6.0.1_r30
因为本人要编译的是Android 6.0系统,所以这里选择的是android-6.0.1_r30分支。注意,列表中每个分支后都有所支持的设备类型,如果要烧录到真机时,就要特别注意。
3、下载源码
同步源码树(以后只需执行这条命令来同步):
repo sync
注意,由于硬盘 I/O 资源有限,Git 服务器每 IP 限制 5 个并发连接。repo sync 命令默认使用 4 个并发连接,请勿使用 -j 参数增加并发连接数。
输入上面的命令后就开始真正的下载源码了,Android 6.0下载后的大小大概50GB左右。如果为了节约空间的话,那么可以删除下载好的源代码目录下的.repo文件夹,但是这样就失去了同步的能力。
三、编译Android源码
源码下载后,我们就可以进行Android源码的编译了。
1、准备编译环境
用envsetup.sh(它在源代码根目录/build下面)脚本初始化环境,注意后面的lunch命令等都跟这一步有没有执行有关。如果没有执行后面会提示找不到lunch命令:
source build/envsetup.sh
在编译新版本之前请清理之前编译过的文件,因为之前编译过的文件有可能对要编译的版本造成不可预知的影响,所以先执行下面的命令进行清理:
make clobber
2、选择编译目标
用lunch命令选择编译目标,后面跟上目标参数,比如我编译的是适用于模拟器的完整可调试版本:
lunch aosp_arm-eng
后面所携带的参数可以分为两部分:BUILD-BUILDTYPE。
- BUILD也就是aosp_arm,代表一个特定的功能组合代号,一般是来表示版本所适配的硬件的,比如模拟器的是aosp-arm,烧录到Nexus6上的是aosp_shamu,更多关于真机代号和刷入,可以参考 Running Builds。
- BUILDTYPE也就是eng是构建类型的意思,主要是决定了你编译出的系统的权限,有以下三种:
BUILDTYPE | 作用 |
---|---|
user | 有限的访问权限,适合生产环境 |
userdebug | 和user类似,但是具有root和debug权限,适合调试 |
eng | 有一些额外的调试和debug工具 |
3、开始编译
最后我们执行下面的命令就可以开始编译了:
make -j4
数字4表示并行地处理数,它一般设置为CPU线程数的1~2倍进行编译,大家可以根据自己机器性能进行调整。例如一个dual-E5520机器上(2个CPU,每个CPU 4核,每个核2线程),那最快的编译速度就在make -j16到make -j32之间。因为本人机子CPU的内核是8核的,所以开16个线程加快编译。
开始编译时,会先输出该编译版本的信息列表:
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=6.0.1
TARGET_PRODUCT=aosp_arm
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a
TARGET_CPU_VARIANT=generic
TARGET_2ND_ARCH=
TARGET_2ND_ARCH_VARIANT=
TARGET_2ND_CPU_VARIANT=
HOST_ARCH=x86_64
HOST_OS=darwin
HOST_OS_EXTRA=Darwin-16.4.0-x86_64-i386-64bit
HOST_BUILD_TYPE=release
BUILD_ID=MOB30D
OUT_DIR=out
============================================
通过列表可以确认我们要编译的版本号和编译目标。
在开始编译后,会遇到各种异常而中止编译。编译错误后再次输入make -j4后可以重新编译,前面编译过的模块不会重复进行编译,正因为这个原因,当我们希望从零开始进行编译的话,要先执行make clobber命令来清除临时文件。不过我建议每当编译错误解决后,最好都从头开始进行编译,以免不可预知的错误发生。
编译的速度跟机子的性能有关,本人的机子整个编译过程持续了将近1个小时,如果编译成功会有类似如下的信息输出:
\e[0;32m#### make completed successfully (52:51 (mm:ss)) ####\e[00m
所有编译的文件都会在out目录下生成,整个out文件占据了20GB左右,加上源码的50GB,现在整个磁盘占了70GB左右大小的容量。这里就知道了为啥我刚开始建议设置80GB以上磁盘的原因了吧。
4、运行源码
编译成功了,我们就可以让源码在模拟器或设备上运行了。请注意之前用lunch设置的特定设备,已编译的设备版本只能在该设备上运行。
模拟器:
如果在选择编译目标那一步选择的是lunch aosp_arm-eng.那么这时候就可以直接输入emulator命令来运行模拟器了(emulator命令在编译过程中会自动添加到Path路径下)
Shell emulator
刷机
因为本人刷的是模拟器,想了解刷入真机这块的可以参考Flashing a device(翻墙)
展示一下成功在模拟器上运行的截图:
5、编译问题总汇
在Mac上编译Android源码遇到了一些坑,这些问题。
问题一
Xcode版本的问题,你会收到如下错误提示:
Can not find SDK 10.6 at /Developer/SDKs/MacOSX10.6.sdk
具体错误的原因是,在编译脚本中会检查当前的Xcode sdk的版本是否是兼容的,这可能是因为你mac上的Xcode版本比较新。打开/Volumes/android/asop/build/core/combo/mac_version.mk
文件,可以查看源码所以支持的mac sdk版本:
mac_sdk_versions_supported := 10.6 10.7 10.8 10.9
在应用程序里打开XCode.app的包内容,进入/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs
。在该目录下,我这里只有MacOSX10.11.sdk目录,也就说当前Xcode的sdk版本是10.11,很明显都不在上述支持的列表中。怎么办? 直接在末尾加上当前的sdk版本呗:
mac_sdk_versions_supported := 10.6 10.7 10.8 10.9 10.11
OK,添加后果然再重新编译,就没有上面的问题发生了。
问题二
解决上面的问题后,果然一直欢快的编译下去了。可是为啥编译那么久,为什么最终花了2个小时,而且最后还编译失败了? 为毛跟别人的博客不一样。最终发现我指定的并发进程数太高了:
make -j32
指定默认值、8、或16都能编译得过,但是唯独32不行。参数的值和机子性能有关,机子性能差的还是乖乖使用默认值吧。
本人在编译和运行过程只发现这两个问题,不像别人的博客中那么多的问题,可能跟编译的版本高有关吧。
四、导入Android Studio
请确保源码已经被编译生成了out相关目录文件,并成功的在运行起来。接下来就可以把源码导入到as中了。
1、编译idegen
cd aosp 进入源码根目录,我们通过如下命令编译idegen模块:
source build/envsetup.sh // 将执行文件设置为临时变量
mmm development/tools/idegen/ //生成idegen.jar文件
这行命令的意思是编译idegen这个模块项目,然后生成idegen.jar文件,该文件的路径一般在/Volumes/android/asop/out/host/darwin-x86/framework/idegen.jar
果看到如下信息则说明编译OK:
#### make completed successfully (4 seconds) ####
接着执行如下脚本,生成IDE项目文件:
development/tools/idegen/idegen.sh
执行成功后在asop的根目录下生成android.ipr,android.iws和android.iml三个文件:
- android.iws 包含工作区的个人设置,比如打开过的文件,版本控制工具的配置,本地修改历史,运行和debug的配置等。
- android.ipr 一般保存了工程相关的设置,比如modules和modules libraries的路径,编译器配置,入口点等。
- android.iml 用来描述modules。它包括modules路径、 依赖关系,顺序设置等。一个项目可以包含多个 *.iml 文件。
通过如上操作我们就完成了基本的源码配置工作。
2、优化AS内存
因为源码非常多,所以导入时IDEA/AS会需要大量内存。所以我们需要编辑IDE的VM选项,通过Help-Edit Custom VM Options即可直接编辑。请根据自己机子的实际情况进行设置,因为本人内存比较大,所以直接上4GB:
-Xms2048m
-Xmx4096m
-XX:MaxPermSize=2048m
-XX:ReservedCodeCacheSize=1024m
-XX:+UseCompressedOops
3、导入AS
很多博客说可以修改iml来减少导入库的量,可以加速导入速度,但是我不知道哪个库有用哪个没用,而且本人的机子性能贼好,所以就没有进行修改android.iml文件的操作了。
接下来直接双击android.ipr或通过AS的Open an existing Android Studio project选项选择android.ipr 就可以直接打开源码了。
整个源码的导入花了差不多10分钟左右,主要跟机子性能有关,导入后工程目录样式切换为Project,到目前为止我们就可以方便的使用Android Studio查看源码:
4、配置AS的JDK、SDK
为当前工程设置正确的SDK和JDK,工程右键-Open Module Settings—SDKs,比如我编译的是6.0源码,所示设置的SKD是23,JDK为8。不过这里JDK设置方式与以往的不一样,因为下载的aosp源码中已经包含了用到的所有jdk文件,所以不需要依赖我们安装的JDK:
左上角“+”号新建JDK — 取个名字叫1.8(No Libraries):
设置sdk依赖新建的” 1.8(No Libraries)”
删除1.8(No Libraries)的Classpath和Sourcepath下的所有东西(右边“-”号删除)
之后在Project标签中的Project SDK中选择对应的Android API版本:
设置后,在源码中跳转的JDK版本不再是系统自带的JKD版本了,而是源码中的JDK了。
5、解决源码中跳转错误问题
解决代码调试时跳转到.class文件而非源码中的.java文件:这时候你打开一个Handler.java类,你会发现它跳转的是你的默认SDK中的jar内部的class文件。既然要修改查看整套源码,这么跳转得多蛋疼啊,所以我们需要配置让其能跳转到源码中的java文件:
打开Project Structure—Modules—Dependencies,让所有的jar包置于这两个下面:
大部分博客都说删除其他的依赖,只剩下上图中的前两个,但是我这么做后,源码文件打开会看到一片红,R文件找不到等等,所以我的做法是不删除任何jar包,直接把和API Platform移动到其他jar包之前,让studio先从源码文件夹找.java文件。
这时候我们再试试跳转就可以直接跳转到源码中的Handler.java文件了,可是这时你会发现Handler类下发出了如下的警告:
原来编译后的out文件下也会生成Handler.java文件,那么我们直接把out/target/common/obj目录,右键Mark Directory as->Excluded,把out下编译后生成的文件排除在工程外就可以了。
6、R文件无法跳转
虽然经过前边的设置,我们解决了代码跳转的问题(不再跳转至反编译的代码文件了),但是你会在代码窗口的右边栏发现红色的错误提示 - R文件无法找到。比如Activity中的com.android.internal.R.attr.state_focused
。
aosp默认生成的android.ipr文件并没有将R文件导入到项目中,所以才会出现这个问题。我们可以手动地将R文件添加到项目的依赖库中:
打开项目的Dependencies,将目录aosp/out/target/common/R以JARs or dictionaries的方式添加进去,默认会起名为Empty library。
还有一种解决R文件无法跳转的方法,请详见这里。
设定好之后,你会发现R文件仍然无法被识别,这时你打开com.android.internal.R文件,看到编译器发出了如下的警告:
IDEA(Android Studio是基于IDEA开发的)默认限制了打开文件的最大尺寸为2500K,我们可以将其改大一点,以满足实际的需求。
配置文件的地址为AndroidStudio-root/bin/idea.properties,将下面的这一行
idea.max.intellisense.filesize=2500
替换为
idea.max.intellisense.filesize=5000
具体的数字根据你自己的需要来定,我这里设定为5000,即5000K。
7、版本控制
如果你想知道每段代码提交的意义的话,我们可以把源码添加到版本控制中:Preferences–Version Control->全选并点击+添加:
五、调试源码
要让Android源码可以调试,那就必须让Android studio把当前工程看成Android工程:
然后在代码中加断点,然后直接点击下图所示的图标
注意,添加为Android工程后,工具栏中才会有上面的图标出现。在弹出的选择进程(Choose Process)对话框中,勾选显示所有进程,选择要DEBUG的代码所在的进程,点击OK即可(可同时debug多个进程)。
参考:
MacOS X 下载编译Android 4.4.4源码(上)
MacOS X 下载编译Android 4.4.4源码(下)
陈哈哈-Mac下设置Android源代码编译环境
陈哈哈-国内不翻墙下载Android 源代码
陈哈哈-编译Android AOSP代码
陈哈哈-Android编译过程中的碎碎念
Mac 10.10 编译android 4.4.4 for nexus
在macOS 10.12 上编译 Android 5.1
Android Studio系列(二)使用AS开发/调试整个android系统源代码(不定时更新)
如何使用Android Studio开发/调试Android源码
下载AOSP android源码(最小最快下载方式,跳过编译直接导入Android Studio) Ubuntu 16.04
使用Android Studio导入源码
Android源代码(AOSP)调试 - Java部分
更多推荐
所有评论(0)