一、配置 Mac OS 编译环境
1. 创建区分大小写的磁盘镜像
Mac OS 的文件系统,默认情况下保留大小写但不区分大小写。Git 不支持这样的文件系统。所以在 Mac OS 中编译 Android 源码,需要创建一块区分大小写的磁盘镜像。
可以通过命令直接创建区分大小写的磁盘镜像:
hdiutil create -type SPARSE -fs 'Case-sensitive Journaled HFS+' -size 100g ~/android.dmg
复制代码
执行上述命令将会创建一个 android.dmg 或 android.dmg.sparseimage 文件,挂载改文件后,可以作为一个区分大小写的镜像分区。
-size 用于设置分区的大小,完成 Android 源码编译至少需要 25GB。如果之后需要调整镜像分区的空间大小,可以使用如下命令:
hdiutil resize -size <new-size-you-want>g ~/android.dmg.sparseimage
复制代码
可以在 ~/.bash_profile(如果是 zsh 则在 ~/.zshrc)文件中添加辅助函数来执行挂载和取消挂载:
# mount the android file image
function mountAndroid { hdiutil attach ~/android.dmg -mountpoint /Volumes/android; }
# unmount the android file image
function umountAndroid() { hdiutil detach /Volumes/android; }
复制代码
注:如果创建磁盘镜像时生成的是 .dmg.sparseimage 文件,将上述方法中的 ~/android.dmg 换成 ~/android.dmg.sparseimage。
之后我们可以使用 mountAndroid 命令来执行挂载镜像,使用 umountAndroid 命令来执行取消挂载镜像。
2. 安装相关工具
2.1 安装 JDK
不同 Android 系统版本的 JDK 要求:
- AOSP 中 Android 的 master 分支:jdk 8u45 或更高版本
- Android 5.x (Lollipop) - Android 6.0 (Marshmallow):jdk-7u71-macosx-x64.dmg
- Android 2.3.x (Gingerbread) - Android 4.4.x (KitKat):Java JDK 6
根据需要选择不同的 JDK,这里编译的是 Android 7.1.1,所以需要 jdk 8u45 或更高版本,安装过程略。
2.2 安装所需的应用程序
编译 Android 7.1.1 源码需要 Mac OS v10.10 (Yosemite) 或更高版本,需要的应用程序有:
- Xcode 4.5.2 和命令行工具
- Python 2.6 - 2.7
- GNU Make 3.81 - 3.82(对于 Android 3.2.x (Honeycomb) 及更低版本,则需要将 make 3.82 还原到较低版本,以避免出现编译错误)
- Git 1.7 或更高版本
- 安装 Xcode 命令行工具
使用以下命令安装 Xcode 命令行工具:
xcode-select --install
复制代码
- 安装 MacPorts
在 macports.org 下载安装 MacPorts。
然后在 ~/.bash_profile(如果是 zsh 则在 ~/.zshrc)文件中添加:
export PATH=/opt/local/bin:$PATH
复制代码
- 使用 MacPorts 安装 Make、Git 和 GPG
执行如下命令完成安装:
POSIXLY_CORRECT=1 sudo port install gmake libsdl git gnupg
复制代码
3. 设置文件描述符上限
在 Mac OS 中,可同时打开的文件描述符的默认数量上限太低,在高度并行的编译流程中,可能会超出此上限。
所以要提高此上限,在 ~/.bash_profile 文件中添加如下内容:
# set the number of open files to be 1024
ulimit -S -n 1024
复制代码
注:这里建议在 ~/.bash_profile 文件中添加,因为编译 Android 源码只支持 bash,使用 zsh 或其它的 shell 可能会出现错误。
二、下载源码
1. 安装 Repo
要处理 Android 代码,需要同时使用 Git 和 Repo,使用 Repo 执行基本的跨网络操作可简化工作。
Repo 是以 Git 为基础的代码库管理工具。Repo 可以在必要时整合多个 Git 代码库,将相关内容上传到我们的修订版本控制系统,并自动执行 Android 开发工作流程的部分环节。Repo 并非用来取代 Git,只是为了让您在 Android 环境中更轻松地使用 Git。更多信息请参阅开发部分。
- 在主目录下创建 bin/ 目录,并添加到 PATH 中:
mkdir ~/bin
PATH=~/bin:$PATH
复制代码
注:Repo 命令是一段可执行的 Python 脚本,您可以将其放在路径中的任何位置。
- 下载 Repo 工具
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
复制代码
- 确保 Repo 可执行
chmod a+x ~/bin/repo
复制代码
2. 初始化 Repo 客户端
- 创建目录
在之前创建的区分大小写的分区中创建目录,来存放 Android 源码,名字自定:
mkdir WORKING_DIRECTORY
cd WORKING_DIRECTORY
复制代码
如果是使用上面的 mountAndroid 命令来挂载分区的话,则可以使用 /Volumes/android/ 目录
- 初始化
使用 repo init 获取最新版本的 Repo 以及补丁,-u 用于指定 Android 源代码中包含的各个代码库将位于工作目录中的什么位置的网址,-b 用于指定相应的系统版本分支。要查看分支列表,请参阅源代码标记和版本。
获取 Android 7.1.1 的版本分支:
repo init -u https://android.googlesource.com/platform/manifest -b android-7.1.1_r26
复制代码
初始化成功后,会产生一个 .repo 目录,清单等文件将保存在该目录下。
3. 下载 Android 源码
运行以下命令下载 Android 源码:
repo sync
复制代码
注:建议翻墙下载或者使用镜像,如清华的镜像:
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-7.1.1_r26 复制代码
三、编译源码
切换 shell
编译 Android 源码只支持 bash,如果使用的是其它的 shell 需要先切换到 bash。
切换方法有两种:
- 临时切换:
终端重启后失效,切换方法为直接在终端输入 shell 的名称:
/bin/bash
复制代码
- 修改默认 shell:
终端重启后生效,切换方法如下:
chsh -s /bin/bash
复制代码
可以使用以下命令查看当前 shell:
echo $0
复制代码
1. 设置环境
通过源码 build 目录中的 envsetup.sh 脚本文件初始化我们的编译环境。
执行如下命令:
source build/envsetup.sh
复制代码
或
. build/envsetup.sh
复制代码
执行结果:
including device/asus/fugu/vendorsetup.sh
including device/generic/mini-emulator-arm64/vendorsetup.sh
including device/generic/mini-emulator-armv7-a-neon/vendorsetup.sh
including device/generic/mini-emulator-mips/vendorsetup.sh
including device/generic/mini-emulator-mips64/vendorsetup.sh
including device/generic/mini-emulator-x86/vendorsetup.sh
including device/generic/mini-emulator-x86_64/vendorsetup.sh
including device/google/dragon/vendorsetup.sh
including device/google/marlin/vendorsetup.sh
including device/htc/flounder/vendorsetup.sh
including device/huawei/angler/vendorsetup.sh
including device/lge/bullhead/vendorsetup.sh
including device/linaro/hikey/vendorsetup.sh
including device/moto/shamu/vendorsetup.sh
including sdk/bash_completion/adb.bash
复制代码
2. 选择目标
使用 lunch 选择要编译的目标。
执行 lunch 命令会显示可选的编译目标类型:
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. aosp_shamu-userdebug
Which would you like? [aosp_arm-eng]
复制代码
编译目标都采用 BUILD-BUILDTYPE 形式,其中 BUILD 是表示特定功能组合的代号。
BUILDTYPE 是以下类型之一:
编译类型 | 使用情况 |
user | 权限受限;适用于生成环境 |
userdebug | 与“user”类似,但具有 root 权限和可调试性;是进行调试时的首选编译类型 |
eng | 具有额外调试工具的开发配置 |
开发使用的话,一般选择 -eng。
因为这里是准备使用模拟器运行编译的源码,并且电脑的 CPU 是 x86 的,所以选择 5. aosp_x86-eng 或 6. aosp_x86_64-eng。
运行如下命令:
lunch aosp_x86-eng
复制代码
执行结果:
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=7.1.1
TARGET_PRODUCT=aosp_x86
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=x86
TARGET_ARCH_VARIANT=x86
TARGET_CPU_VARIANT=
TARGET_2ND_ARCH=
TARGET_2ND_ARCH_VARIANT=
TARGET_2ND_CPU_VARIANT=
HOST_ARCH=x86_64
HOST_2ND_ARCH=x86
HOST_OS=darwin
HOST_OS_EXTRA=Darwin-16.6.0-x86_64-i386-64bit
HOST_CROSS_OS=
HOST_CROSS_ARCH=
HOST_CROSS_2ND_ARCH=
HOST_BUILD_TYPE=release
BUILD_ID=NOF27C
OUT_DIR=out
============================================
复制代码
3. 编译源码
在源码路径下使用 make 命令编译源码,可以使用 -jN 参数设置并行任务,N 为并行的任务数,一般为 CPU 线程数的 1-2 倍之间。
这里是用以下命令:
make -j4
复制代码
成功编译完成后会有以下显示:
#### make completed successfully (02:51:05 (hh:mm:ss)) ####
复制代码
4. 运行模拟器
编译完成后,执行 emulator 命令可以运行模拟器:
emulator
复制代码
第一次启动时间会比较长。
四、编译中遇到的问题
1. Can not find SDK 10.8 at /Developer/SDKs/MacOSX10.8.sdk
查看 build/core/combo/mac_version.mk 文件,可以看到里面有如下设置:
mac_sdk_versions_supported := 10.8 10.9 10.10 10.11
复制代码
由此可知,支持的 Mac SDK 版本。
因为电脑的系统版本是 MacOS Sierra 10.12,在 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs 目录下只有 MacOSX10.12.sdk,所以会有报错。
解决办法:
网上的一些解决办法是修改 mac_version.mk 文件中的配置,使支持 10.12 版本:
mac_sdk_versions_supported := 10.8 10.9 10.10 10.11 10.12
复制代码
如果按照如上修改方法,在编译源码时会出现 error: 'syscall' is deprecated 的问题,这是因为在 10.12 版本中弃用了 syscall。
所以不能修改 mac_version.mk 文件中的配置,那么就需要在 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs 目录下添加 MacOSX10.11.sdk。
在 github.com/phracker/Ma… 下载 MacOSX10.11.sdk。并拷贝到 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs 目录下,即可解决。
2. OOM
执行如下命令修改内存大小:
export JACK_SERVER_VM_ARGUMENTS="-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4g"
复制代码
然后重启 jack 服务:
./prebuilts/sdk/tools/jack-admin kill-server
./prebuilts/sdk/tools/jack-admin start-server
复制代码