转身搁浅昨天

不忘初心,方得始终

Endevour To Be A Humanistic Programmer


macOS Sierra 编译Android源代码

​这两天捣鼓了一下Android 6.0.1源码的下载与编译,碰到了不少坑,但最后还是成功地编译出了一份源码,在这里记录一下自己的操作过程,第一次写博客,还希望大家体谅我的渣渣水平。

搭建环境

先交代一下自己的硬件情况:

  • 操作系统:macOS Sierra

  • CPU:双核四线程(后头有用)

创建一个大小写敏感的磁盘镜像

因为我下载的是6.0 .1的源码,源码下载和编译完后需占用70多G的空间,电脑的存储空间不足,所以用的外接硬盘下载和编译源码。可通过磁盘工具将外接硬盘格式化为“Mac OS扩展(区分大小写,日志式)”的格式,请务必保证你的外接硬盘的分区的容量有80G的空间。

若是电脑存储充足,可通过以下命令创建磁盘镜像:

1
# hdiutil create -type SPARSE -fs 'Case-sensitive Journaled HFS+' -size 80g ~/android.dmg

此时会在当前目录下创建一个后缀是.dmg或者.dmg.sparseimage的磁盘镜像,在macOS上是后者,如果之后需要扩展空间,可以通过以下命令:

1
# hdiutil resize -size <new-size-you-want>g ~/android.dmg.sparseimage

可以通过向~/.bash_profile文件中添加工具方法进行镜像的挂载与卸载

  • 挂载可通过在终端中执行mountAndroid,需在.bash_profile中添加以下内容:

    1
    2
    # mount the android file image
    function mountAndroid { hdiutil attach ~/android.dmg -mountpoint /Volumes/android; }

注意:如果系统创建的镜像的后缀为.dmg.sparseimage,需要将上面函数中的~/android.dmg替换为 ~/android.dmg.sparseimage

  • 卸载镜像可通过执行umountAndroid,添加内容如下:

    1
    2
    # unmount the android file image
    function umountAndroid() { hdiutil detach /Volumes/android; }

    需注意的地方与上头相同

安装JDK

可查看要求来查询不同版本的Android源码所需的Java版本,Android 6.0需安装Java 7,如果你的电脑中已经安装了其它版本的java,记得在你的~/.bash_profile中将JAVA_HOME设置为java 7,同时还需作以下操作:

  • 安装必须的软件包:

    • Xcode,可从App Store安装最新的Xcode
    • MacPorts,可从macports.org安装MacPorts

    注意:确保/opt/local/bin在PATH环境变量中出现在/usr/bin之前,可在~/.bash_profile中添加如下内容:

    1
    export PATH=/opt/local/bin:$PATH

在安装完必须的软件包后,通过MacPorts获取make,git和GPG等软件包,命令如下:

1
$ POSIXLY_CORRECT=1 sudo port install gmake libsdl git gnupg

如果电脑系统版本是OS X v10.4,还需安装bison,命令如下:

1
$ POSIXLY_CORRECT=1 sudo port install bison

​如果需下载Android 4.0.x以及更早的源码,gmake 3.82中存在bug,需要另作处理,具体查看这里

  • 设置最大打开文件数

    在Mac OS中,默认的最大文件打开数很低,高度的并行构建进程可能会超过这个限制,所以需要对其进行设置,可在~/.bash_profile中添加如下内容:

    1
    2
    # set the number of open files to be 1024
    ulimit -S -n 1024

下载源码

安装Repo

  • 确保在用户目录下有bin目录,并且在PATH环境变量中,执行以下命令:

    1
    2
    $ mkdir ~/bin
    $ PATH=~/bin:$PATH
  • 下载Repo工具并确保其可执行,执行命令如下:

    1
    2
    $ curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
    $ chmod a+x ~/bin/repo

初始化Repo仓库

在安装好Repo后,进入硬盘下或你创建的磁盘镜像挂在的目录下,然后创建一个工作目录用于存放下载的Android源码和编译后的产物:

1
2
$ mkdir Android
$ cd Android

可在初始化Repo仓库前通过git config命令配置你的真实姓名和邮件地址,这将可用于你之后代码的提交,配置命令如下:

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

通过repo init命令可以初始化仓库:

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

上头不带参数的命令用于初始化master的仓库,可通过-b参数获取某一分支,这里我获取的是Android 6.0.1_r17分支,命令如下:

1
$ repo init -u https://android.googlesource.com/platform/manifest -b android-6.0.1_r17

同步源码

接着即可开始同步源码,命令如下:

$ repo sync

同步源码会占用一个小时甚至更多的时间去完成,同步过程中可能会出现错误,如果是出现无法连接到gerrit.googlesource.com,则可修改~/bin/repo文件,找到REPO_URL这一行,修改为:

1
REPO_URL = 'https://gerrit-google.tuna.tsinghua.edu.cn/git-repo'

相应的初始化仓库的命令变为:

1
$ repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest

1
$ repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-6.0.1_r17

然后重新repo sync,如果一开始硬盘容量不够或磁盘镜像分配的容量不足,sync过程中会出现no space left的错误,此时需给你的磁盘镜像调整容量大小。

由于下载源码的时间太长,中途可能会出现链接断开的情况,repo同步虽然支持断点续传,但是不知道什么时候会断开,所以可以写一个脚本来开启同步,脚本文件名可设为get_android.sh,内容如下:

1
2
3
4
5
6
7
8
9
10
#!/bin/bash
#FileName get_android.sh
PATH=~/bin:$PATH
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-6.0.1_r17
repo sync
while [ $? = 1 ]; do
echo "================sync failed, re-sync again ====="
sleep 3
repo sync
done

该脚本来自于该作者

然后可通过以下命令开启同步:

1
$ ./get_android.sh

同步完后可删除该脚本文件

编译源码

初始化编译环境

执行命令如下:

1
$ source build/envsetup.sh

选择编译目标

通过lunch命令设置编译目标,所谓的编译目标就是生成的镜像要运行在什么样的设备上,这里我尝试了几个编译目标编译的时候都出了点儿问题,有MacOSX sdk版本的问题,也有mac_version.mk文件配置的问题,最后我是设置编译目标为aosp_arm64-eng,且修改源码所在目录下的build/core/combo/mac_version文件中的mac_sdk_versions_supported := 10.6 10.7 10.8 10.9为mac_sdk_versions_supported := 10.11,并从这里下载的MacOSX10.11.sdk,然后将其放到/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs下,最后执行命令:

1
$ lunch aosp_arm64-eng

也可通过先执行$ lunch查看可选择的编译目标,然后选择某一编译目标:

lunch_command_display

注意:最新版本的Xcode的sdk版本为10.12,用该版本的sdk编译会出现错误,所以不要将mac_sdk_versions_supported设为10.12,如果需将编译出来的源码用于Nexus设备(包括模拟器),还需要另外处理一下驱动问题,可从这里下载不同Nexus设备在不同Android版本下所需的驱动,下载完后需将解压出来的脚本在源码所在的根目录下执行,执行完成后会在源码目录下生成一个vendor目录。

编译源码

执行$ make -j4启动编译,编译过程需要耗用长达几个小时的时间,这要看机子的配置情况,命令中-j后的数字4是我电脑的所有CPU的线程数的总和,假设你的电脑的所有CPU的线程数的总和为n,那么-j后可跟n或2n来启动编译。

如果顺利编译成功的话,结果如下:

make_success_display

运行模拟器

在编译完成后,即可通过emulator命令打开模拟器

若不是在编译完成后立马运行模拟器,则需通过以下命令打开模拟器:

1
2
3
$ source build/envsetup.sh
$ lunch aosp_arm64-eng
emulator

这里lunch后跟的编译目标需要设为你编译时选择的编译目标,如果编译过程没出现问题,则结果如下:

emulator_display

导入源码到Android Studio

导入前还需先做一些处理,首先需要编译idegen模块,命令如下:

1
$ mmm development/tools/idegen/

命令执行成功后会提示

1
#### make completed successfully (7 seconds) ####

m、mm、mmm命令可以编译单独的模块,但shell必须为bash shell

注意:如果命令执行失败,提示错误信息为-bash: mmm: command not found,那么需要现在源码目录下执行

1
$ source build/envsetup.sh

然后执行一下命令以在源码根目录下生成对应的android.ipr和android.iml IDEA工程配置文件:

1
$ development/tools/idegen/idegen.sh

执行成功后可看到终端提示如下:

1
2
Read excludes: 30ms
Traversed tree: 230917ms

该命令的执行时间视机子配置情况而定

最后使用Android Studio,选择Open an existing Android Studio Project, 然后找到源码所在目录,选中android.ipr,最后就是等待Android Studio索引完成了,打开过程中会提示源码所在目录的文件系统大小写敏感与IDE不匹配,直接忽略提示。

最近的文章

编译Android内核

最近尝试编译了一下Android内核源码,不知道为什么编译出来的内核无法启动之前编译的Android 6.0.1_r17的镜像,搜索了很久,但仍是无解,所以重新选择了编译Android 7.1.1_r13这个源码分支,然后再根据启动的模拟器的内核版本,选择了相应的内核分支进行了编译,最终可以由编译 …

于  AOSP 继续阅读
comments powered by Disqus