MacOS X 编译Android源码

  • 本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布

由于在工作中遇到了很多关于android内部实现的问题,虽然后面都解决了,有些是看了源码实现,有些源码看不了只能去google,百度。这就导致了对于很多的问题其实是知其然不知其所以然,所以从现在开始我下定决心开始学习Android的源码。那说到源码就必须提到编译源码这件事情。
最开始是在我的MBP上面安装了linux的双系统准备在ubuntu上面来安装编译源码,不过这个方法有个弊端就是查看源码的过程真是爽翻天啊,所以开始捣鼓再mac上面编译源码

在google了一些方法之后发现比较混乱以至于难以完成,所以这次使用官方的方法来完成源码的编译。

那么现在开始了:


1. 系统要求

Mac OS (Intel/x86)

  • Android 6.0 (Marshmallow) - AOSP master:Mac OS v10.10 (Yosemite) 或更高版本,具有 Xcode 4.5.2 和命令行工具
  • Android 5.x (Lollipop):Mac OS v10.8 (Mountain Lion),具有 Xcode 4.5.2 和命令行工具
  • Android 4.1.x-4.3.x (Jelly Bean) - Android 4.4.x (KitKat):Mac OS v10.6 (Snow Leopard) 或 Mac OS X v10.7 (Lion),以及 Xcode 4.2(Apple 的开发者工具)
  • Android 1.5 (Cupcake) - Android 4.0.x (Ice Cream Sandwich):Mac OS v10.5 (Leopard) 或 Mac OS X v10.6 (Snow Leopard),以及 Mac OS X v10.5 SDK

2. JDK

这里会需要注册一个 甲骨文的账号

  • AOSP 中 Android 的 master 分支:Mac OS - jdk 8u45 或更高版本
  • Android 5.x (Lollipop) - Android 6.0 (Marshmallow):Mac OS - jdk-7u71-macosx-x64.dmg
  • Android 2.3.x (Gingerbread) - Android 4.4.x (KitKat):Mac OS - Java JDK 6

3. 主要程序包

  • python
  • gmake
  • git

gmake 后面会下载的,你只需要安装好python2.7 然而一般python是安装好的


4. 搭建编译环境

4.1. 创建区分大小写的磁盘映像

您可以使用磁盘映像在现有的 Mac OS 环境中创建区分大小写的文件系统。要创建磁盘映像,请启动磁盘工具,然后选择“新建映像”。完成编译至少需要 25GB 空间;更大的空间能够更好地满足未来的需求。使用稀疏映像有助于节省空间,而且以后可以随着需求的增加进行扩展。请务必选择“Case sensitive, Journaled”存储卷格式。

我推荐使用这种方式来建立磁盘映像

您也可以通过 shell 使用以下命令创建磁盘映像:
# hdiutil create -type SPARSE -fs 'Case-sensitive Journaled HFS+' -size 40g ~/android.dmg 这将创建一个 .dmg(也可能是 .dmg.sparseimage)文件,该文件在装载后可用作具有 Android 开发所需格式的存储卷。
如果您以后需要更大的存储卷,还可以使用以下命令来调整稀疏映像的大小:
# hdiutil resize -size <new-size-you-want>g ~/android.dmg.sparseimage 对于存储在主目录下的名为 android.dmg 的磁盘映像,您可以向 ~/.bash_profile 中添加辅助函数:
要在执行 mountAndroid 时装载磁盘映像,请运行以下命令:
# mount the android file image function mountAndroid { hdiutil attach ~/android.dmg -mountpoint /Volumes/android; } 注意:如果系统创建的是 .dmg.sparseimage 文件,请将 ~/android.dmg 替换成 ~/android.dmg.sparseimage。
要在执行 umountAndroid 时卸载磁盘映像,请运行以下命令:
# unmount the android file imagefunction umountAndroid() { hdiutil detach /Volumes/android; } 装载 android 存储卷后,您将在其中开展所有工作。您可以像对待外接式存储盘一样将其弹出(卸载)。


4.2. 安装Xcode

你只需要在AppStore 里面安装Xcode就可以了。
之后需要运行一下命令

$ xcode-select --install

或者你也可以选择直接运行命令,不过我不推荐,下个xcode有好处的哦


4.3. 安装MacPorts

下载链接 根据自己的系统来选择

  • 编辑.bash_profile,如果没有就新建(不用特意操作,vi可以自动生成的)

vi ~/.bash_profile

vi的小提示,按i切换到insert模式就是编辑模式,按esc退出编辑模式,按:wq 保存退出
复制 export PATH=/opt/local/bin:$PATH 到文件中。

输入source ~/.bash_profile 使命令生效


4.4. 通过 MacPorts 获取 Make、Git 和 GPG 程序包

POSIXLY_CORRECT=1 sudo port install gmake libsdl git gnupg

如果您使用 Mac OS X v10.4,还需要安装 bison:POSIXLY_CORRECT=1 sudo port install bison


在 Mac OS 中,可同时打开的文件描述符的默认数量上限太低,在高度并行的编译流程中,可能会超出此上限。要提高此上限,请将下列行添加到 ~/.bash_profile 中:
ulimit -S -n 1024

4.5. 设置ccache

  • 在源代码的根目录下执行以下命令

export USE_CCACHE=1export CCACHE_DIR=/<path_of_your_choice>/.ccache


5. 下载源代码

5.1. 安装repo

  • 确保主目录下有一个 bin/ 目录,并且该目录包含在路径中

mkdir ~/binPATH=~/bin:$PATH

(要在~/.bash_profile中添加;输入source ~/.bash_profile 使命令生效)

  • 下载 Repo 工具,并确保它可执行

curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repochmod a+x ~/bin/repo

5.2. 初始化repo客户端

必须使用之前创建的区分大小写的文件系统,一般挂载的新的盘是在/Volumes/ 路径下的
我分出来的区分大小写的文件系统名字是Android 所以我cd进去就ok了

  • 创建一个目录 mkdir XXX (XXX 是你自己取得名字)
  • cd XXX

如果遇到repo: command not found 问题 请在初始工作目录输入
echo 'export PATH=$PATH:$HOME/bin' >> ~/.bashrc export PATH=$PATH:$HOME/bin

5.3. 配置git信息

git config --global user.name "Your Name"git config --global user.email "you@example.com"

5.4. 初始化repo

repo init -u https://android.googlesource.com/platform/manifest

  • P.S. 此时需要科学上网,如果不能科学上网没有关系,我们可以通过其他的镜像来完成这一步操作

5.5. 清华镜像下载

清华镜像 首先我们可以看到

2016-06-24 : 关闭 git:// 协议,仅支持 HTTPS

所以我们是无法使用repo来同步代码的,所以我们要这么做:

  • 下载https://mirrors.tuna.tsinghua.edu.cn/aosp-monthly/aosp-latest.tar
  • 然后~~等(这个包有31个G,我用迅雷慢慢下载中)
  • 将下载完的包放在之前建立的工作目录上

tar xf aosp-latest.tar 解压的目录

cd aosp

repo sync

此后,每次只需运行 repo sync 即可保持同步。 我们强烈建议您保持每天同步,并尽量选择凌晨等低峰时间

5.6.科大镜像下载

科大镜像

科大镜像没有去掉git协议,所以我们可以顺畅的完成下载按照页面提示的操作即可


6. 编译准备工作

  • 点击https://source.android.com/source/requirements.html#binaries进行文件下载

对于运行带标记的 AOSP 版本分支的受支持设备,您可以从 Google 的 Nexus 驱动程序页面下载相关的官方二进制文件。有了这些二进制文件,您将有权使用采用非开放源代码的其他硬件功能。要编译 AOSP 的 master 分支,请使用 Nexus 设备的二进制文件预览。在针对某种设备编译 master 分支时,请使用适用于最新编号版本的二进制文件或具有最新日期的二进制文件。

  • 解压缩下载的文件将会得到一个sh的文件通过终端sh xxx.sh运行

此处需要agree用户协议,你只需要按住向下键,就可以划到最后输入 I ACCEPT 就可以了。

  • sh运行完成之后会得到一个vendor文件夹,将其复制到源代码的根目录下
  • 清理
    为了确保新安装的二进制文件在解压后会被适当考虑在内,请使用以下命令删除所有以前编译操作的已有输出: make clobber

6.1. 设置环境

  • 使用 envsetup.sh 脚本初始化环境

source build/envsetup.sh

6.2. 选择目标

  • 使用 lunch 选择要编译的目标。

lunch 然后会出现对应的列表选择其中某个数字即可

该命令表示针对模拟器进行完整编译,并且所有调试功能均处于启用状态。
如果您没有提供任何参数就运行命令,lunch 将提示您从菜单中选择一个目标。
所有编译目标都采用 BUILD-BUILDTYPE 形式,其中 BUILD 是表示特定功能组合的代号。
BUILDTYPE 是以下类型之一

编译类型

使用情况

user

权限受限;适用于生产环境

userdebug

与“user”类似,但具有 root 权限和可调试性;是进行调试时的首选编译类型

eng

具有额外调试工具的开发配置

  • 由于本人有一个nexus 5x 的手机 ,所以准备在nexus5x 的手机上运行自己编译的代码,所以我选择的编译命令为aosp_bullhead-userdebug

如果想要针对真机调试,请参阅运行版本进行命令选择。我在这里不建议初次接触源码编译的人进行真机调试,刷砖了就gg了。

6.3. 编译代码

您可以使用 make 编译任何代码。GNU Make 可以借助 -jN 参数处理并行任务,通常使用的任务数 N 介于编译时所用计算机上硬件线程数的 1-2 倍之间。例如,在一台双核 E5520 计算机(2 个 CPU,每个 CPU 4 个内核,每个内核 2 个线程)上,要实现最快的编译速度,可以使用介于 make -j16 到 make -j32 之间的命令。

make -j4

  • 请注意,本部分只是一个摘要,用于确保设置已完成。如需关于编译 Android 的详细说明,请参阅运行编译系统。

编译过程中遇到的问题

  • xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance
    Answer:

sudo xcode-select -s /Applications/Xcode.app/Contents/Developer


  • build/core/combo/mac_version.mk:26: none of the installed SDKs (wifi-serviceac_sdk_versions_installed) match supported versions (10.8 10.9 10.10 10.11), trying 10.8
    原因boxen的版本太低了需要更新

https://github.com/boxen/our-boxen 根据此处进行更新

  • no SDK 10.8 at /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk, trying legacy dir
    build/core/combo/mac_version.mk:40: *****************************************************
    build/core/combo/mac_version.mk:41: * Can not find SDK 10.8 at /Developer/SDKs/MacOSX10.8.sdk
    build/core/combo/mac_version.mk:42: *****************************************************

通过查看build/core/combo/mac_version.mk文件我们可以看到
mac_sdk_versions_supported := 10.8 10.9 10.10 10.11 而我电脑是10.12版本的所以我加了个10.12在这句话之后 就可以了 我们需要下载一个MacOSX10.11.sdk放到这个目录中。 ReleasePage因为10.12这个版本的sdk中syscall这个方法被弃用了,所以我们需要换回11这个版本的sdk

  • could not find jdk tools.jar at /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/../lib/tools.jar, please check if your JDK was installed correctly. Stop. 在~/.bash_profile 中添加 export ANDROID_JAVA_HOME=$JAVA_HOME
  • 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]

我们需要下载一个MacOSX10.11.sdk解压后放到这个目录中Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/

  • external/doclava/src/com/google/doclava/Converter.java:407: 错误: 找不到符号
    m.isAbstract(), m.isSynchronized(), m.isNative(), m.isDefault(), true,
    ^
    符号: 方法 isDefault()
    位置: 类型为AnnotationTypeElementDoc的变量 m

应该是jdk版本不对 你需要查看你在安装过程中哪里使用了1.7版本的jdk 可以通过查看java -versionjavac -version 来查看

  • Communication error with Jack server (52). Try 'jack-diagnose'

export JACK_SERVER_VM_ARGUMENTS="-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4g"./prebuilts/sdk/tools/jack-admin kill-server./prebuilts/sdk/tools/jack-admin start-server

  • Out of memory error (version 1.2-rc4 'Carnac' (298900 f95d7bdecfceb327f9d201a1348397ed8a843843 by android-jack-team@googl

修改文件 prebuilts/sdk/tools/jack-admin 修改这个语句加上-Xmx4096m ----> JACK_SERVER_COMMAND="java -XX:MaxJavaStackTraceDepth=-1 -Djava.io.tmpdir=$TMPDIR $JACK_SERVER_VM_ARGUMENTS -Xmx4096m -cp $LAUNCHER_JAR $LAUNCHER_NAME"

  • frameworks/base/tools/aidl/aidl_language_l.l:55: warning, rule cannot be matched


  • abuild/core/base_rules.mk:238: error: external/googletest/googletest: MODULE.TARGET.STATIC_LIBRARIES.libgtest already defined by external/googletest/googletest.

unset NDK_ROOT


7.0 刷机

终于build完成了 真是历经千幸万苦啊。

首先第一步 在源代码的更目录下输入

sudo adb reboot bootloader

(如果发现没有成功请重新输入6.1和6.2的步骤)
然后你就会到达这个界面

fastboot oem unlock输入这个命令 然后通过音量键选择yes 通过待机键确认

再然后输入

fastboot flashall -w

  • 出现错误error: could not load android-info.txt: No such file or directory

export ANDROID_PRODUCT_OUT=/Volumes/android/android-7.1.1_r24/out/target/product/generic (请替换你自己的目录)

  • 出现错误error: could not load boot.img

你会发现没有boot.img 这个文件 这时候你只需要 make bootimage 就会生成对应的文件