Prologue
由于 GFW 的原因,使用国内镜像下载更快,这里以清华镜像为例。
- google 官方教程
- 清华
- 中科大
- Github(只有部分 common repositories)
准备编译环境
在编译之前,需要先做一些 设置编译环境 之类的准备工作;由于当前使用 Mac OS,故需要做以下几步准备:
-
Mac OS 默认的 APFS 卷(Volume)是不区分大小写、不加密的,而编译 AOSP 会对 case-sensitive 进行检查(因为不区分大小写会导致某些 Git 命令行为出现异常),所以编译 AOSP 必须基于区分大小写的卷上操作,否则会报如下错误:
$make -j4 Checking build tools versions... build/core/main.mk:90: ************************************************************ build/core/main.mk:91: You are building on a case-insensitive filesystem. build/core/main.mk:92: Please move your source tree to a case-sensitive filesystem. build/core/main.mk:93: ************************************************************ uild/core/main.mk:94: *** Case-insensitive filesystems not supported. Stop.
有两种方式建立一个区分大小写(case-sensitive)的 APFS 卷:
-
使用
hdiutil
指令的方式,可参考 官方指南 或者 StackOverFlow。 -
macOS High Seirra 及其以上的系统版本可直接使用系统的磁盘工具(Disk Utility),在 container disk 里增加一个区分大小写的 APFS 卷(打开磁盘工具,选择 container disk,点击顶部的
+
)。
推荐使用系统的磁盘工具,使用
hdiutil
指令的方式还需要考虑 convert、mount、unmount 等操作。
case-sensitive 的卷建好后,后续的下载和编译都基于此卷进行操作。如果先下载,后建卷,然后移动下载的源码至新建的卷,会出现部分软链接文件依然指向移动前的源文件,导致无法编译。NOTE
Mac 从终端进入另一个卷的方法:cd /Volumes/{卷名}
所有的卷都存在于系统所在卷的
Volumes
目录下。 -
-
安装 Xcode 和 Command Line Tools
编译过程中需要用到 Xcode 的开发者 SDK,如果没有安装 Xcode 则编译会报错
Could not find a supported mac sdk
:ninja: no work to do. [1/1] out/soong/.bootstrap/bin/soong_build out/soong/build.ninja FAILED: out/soong/build.ninja out/soong/.bootstrap/bin/soong_build -t -l out/.module_paths/Android.bp.list -b out/soong -n out -d out/soong/build.ninja.d -o out/soong/build.ninja Android.bp internal error: Could not find a supported mac sdk: ["10.10" "10.11" "10.12" "10.13"] internal error: xcrun failed with: "exit status 1" internal error: xcrun failed with: "exit status 1" internal error: xcrun failed with: "exit status 1" internal error: xcrun failed with: "exit status 1" ninja: build stopped: subcommand failed. 10:41:26 soong bootstrap failed with: exit status 1 #### failed to build some targets (14 seconds) ####
当然,没有安装 Xcode 只是的错误原因之一,出现这种错误也可能是 Xcode 对应的开发者 SDK 目录下没有编译支持的 SDK 版本。
# 查看 Xcode 开发者 SDK 版本 ls /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/
对于这种情况,有两种解决方案:
-
下载 AOSP 编译支持的 Xcode 开发者 SDK,解压到 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ 目录。
-
把 Xcode 当前的开发者 SDK 版本加入到 AOSP 编译支持的版本配置里:
vim build/soong/cc/config/x86_darwin_host.go
80 darwinSupportedSdkVersions = []string{ 81 "10.10", 82 "10.11", 83 "10.12", 84 "10.13", 85 "10.14", // 支持列表添加 Xcode 开发者 SDK 10.14 86 }
NOTE
从 App Store 上下载 Xcode 后,默认是不会安装 Command Line Tools 的,在 Xcode 缺少 Command Line Tools 的情况下编译 AOSP 同样会报Could not find a supported mac sdk
错误。可在终端输入以下命令:xcode-select --install
进行安装,安装完成后再次执行该指令可检测是否安装成功,安装成功会显示command line tools are already installed
。 -
-
设置文件描述符数量上限
在 Mac OS 中,可同时打开的文件描述符的默认数量上限太低(可使用ulimit -n
查看,一般默认是256),在高度并行的编译流程中,可能会超出此上限。要提高此上限,请将下列行添加到 ~/.bash_profile 中:# set the number of open files to be 1024 ulimit -S -n 1024
修改完后不要忘记刷新生效:
source .bash_profile
或者. .bash_profile
。
下载 AOSP
-
安装 git 和 repo
// https://source.android.com/source/downloading.html#installing-repo curl https://storage.googleapis.com/git-repo-downloads/repo > /usr/local/bin/repo chmod a+x /usr/local/bin/repo
-
创建 AOSP 源码存放文件夹(Mac OS 必须位于 case-sensitive 的卷上)
mkdir AndroidPlatform cd AndroidPlatform
-
初始化 repo
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest
-
切换分支:
自行选择 manifests 列出来的分支,这里的 android-9.0.0_r35 是当前最新分支(根据分支命名规则),pull
操作可省略(刚创建的 manifests 所有分支代码都是最新的)。cd .repo/manifests git branch -a | cut -d / -f 3 git checkout -b android-9.0.0_r35 origin/android-9.0.0_r35 git pull --rebase cd ../..
NOTE
如果能事先确定 manifests 存在自己需要的分支,则可以合并第 3、4 步,直接使用如下命令(这里仍然以 origin/android-9.0.0_r35 分支为例):repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-9.0.0_r35
-
这种初始化方式的不同之处在于,manifests 里是 default 分支指向 origin/android-9.0.0_r35,而 3、4 步骤的 default 分支指向默认的 master 分支,新建的 android-9.0.0_r35 才指向 origin/android-9.0.0_r35 分支(可以使用
git branch -vv
查看分支指向情况)。 -
查看可用的 manifests 分支列表,列表更新不是那么及时,实际 manifests 里可能会存在表里没有列出的新分支。
-
-
同步代码(清华的镜像服务器不要超过4线程)
repo sync -j4
-
漫长的等待,几个小时(视网速而定),如果 sync 失败,再次执行步骤 5,继续 sync 会接着之前的进度。sync 成功后会有提示:
Syncing work tree: 100% (xxx/xxx), done.
-
检查大小,同步完成后目前大概在 73G 左右,可以作为同步是否成功的一个大概判断。
.
表示当前路径,可省略(无路径参数时默认为当前路径)。du -sh .
NOTE
由于 AOSP 工程过大,可以使用一些小技巧减少同步时间和空间:-
repo init
使用--depth=1
参数,省去同步历史记录。 -
repo sync
使用-c
或者--current-branch
参数,指定只抓取特定分支代码。
加上优化参数后同步,空间占 50G 左右,减少了大约 23G;由于是下班后丢在公司下载的,没有统计时间,但是节省的时间百分比应该和空间大致差不多。
-
make m mm mmm 的区别
-
make
GNU 的 make 构建工具,用于解释 Makefile 规则。 -
m mm mmm
这三个指令其实是build/envsetup.sh
脚本里定义的几个函数,只有执行过该 shell 脚本后才能生效:. build/envsetup.sh
这三者的简单解释可以通过同样定义在该 shell 脚本里的函数 hmm 进行查看(详细解释还是得看三个函数对应实现的源码):
hmm
-
m
其实质就是 make 指令,只不过封装成从工程根部开始编译。更多用法可以查看帮助信息:m help
。 -
mm
编译当前路径下的所有模块。 -
mmm
编译指定路径下的所有模块
-
编译
-
全编译
. build/envsetup.sh lunch make -j8
-
首次编译 idegen
. build/envsetup.sh make idegen
-
增量编译 idegen
. build/envsetup.sh mmm development/tools/idegen/
NOTE
-
idegen 是用来生成针对 Eclipse 和 IntelliJ IDEA 的 Android 系统源代码工程配置文件的一个工具,它位于 Android 系统源代码工程目录的下列位置:
development/tools/idegen/
,更多详细信息可以参考该目录下的 README。
对于 Android Studio 加载 AOSP 源码,只需要编译 idegen 即可,并不需要编译整个工程。 -
初次接触 AOSP,编译很难一次顺畅通过,过程中可能会多次遇上错误而中断,耐心搜索解决相应错误即可。
-
Android Studio 加载 AOSP
-
编译 idegen 成功后,运行 idegen.sh 便可生成 Android Studio 能够打开的工程文件 android.ipr 以及工程配置文件 android.iml:
. development/tools/idegen/idegen.sh
必须在 AOSP 源码根目录执行该指令,否则会报错,最后生成的两个文件也处于源码根目录下。
-
双击文件 android.ipr 便可自动关联打开 Android Studio 进行加载。
android.ipr 包含了基本上 Android 源码里的所有模块,直接打开 android.ipr,会等待相当长时间的 scanning index。如果只是想调试 framework,没有必要加载其他模块。 android.iml 文件的excludeFolder
就是用于配置不需要加载的模块,打开该文件 替换默认生成的 excludeFolder 配置为如下项(只保留了 framework 模块):<excludeFolder url="file://$MODULE_DIR$/./external"/> <excludeFolder url="file://$MODULE_DIR$/.repo"/> <excludeFolder url="file://$MODULE_DIR$/art"/> <excludeFolder url="file://$MODULE_DIR$/bionic"/> <excludeFolder url="file://$MODULE_DIR$/bootable"/> <excludeFolder url="file://$MODULE_DIR$/build"/> <excludeFolder url="file://$MODULE_DIR$/compatibility"/> <excludeFolder url="file://$MODULE_DIR$/cts"/> <excludeFolder url="file://$MODULE_DIR$/dalvik"/> <excludeFolder url="file://$MODULE_DIR$/developers"/> <excludeFolder url="file://$MODULE_DIR$/development"/> <excludeFolder url="file://$MODULE_DIR$/device"/> <excludeFolder url="file://$MODULE_DIR$/external"/> <excludeFolder url="file://$MODULE_DIR$/hardware"/> <excludeFolder url="file://$MODULE_DIR$/kernel"/> <excludeFolder url="file://$MODULE_DIR$/libcore"/> <excludeFolder url="file://$MODULE_DIR$/libnativehelper"/> <excludeFolder url="file://$MODULE_DIR$/out"/> <excludeFolder url="file://$MODULE_DIR$/packages"/> <excludeFolder url="file://$MODULE_DIR$/pdk"/> <excludeFolder url="file://$MODULE_DIR$/platform_testing"/> <excludeFolder url="file://$MODULE_DIR$/prebuilts"/> <excludeFolder url="file://$MODULE_DIR$/sdk"/> <excludeFolder url="file://$MODULE_DIR$/system"/> <excludeFolder url="file://$MODULE_DIR$/test"/> <excludeFolder url="file://$MODULE_DIR$/toolchain"/> <excludeFolder url="file://$MODULE_DIR$/tools"/>
Android Studio 加载成功后,依然会显示 exclude 的模块,这是因为 IDE 默认勾选开启了
Show Excluded Files
,在 show option menu 里取消勾选就可以隐藏掉。
Android Studio 调试 framework
Todo