Android FrameWork 之源码编译

3,612 阅读6分钟

一、配置 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 要求:

根据需要选择不同的 JDK,这里编译的是 Android 7.1.1,所以需要 jdk 8u45 或更高版本,安装过程略。

2.2 安装所需的应用程序

编译 Android 7.1.1 源码需要 Mac OS v10.10 (Yosemite) 或更高版本,需要的应用程序有:

  1. 安装 Xcode 命令行工具

使用以下命令安装 Xcode 命令行工具:

xcode-select --install
  1. 安装 MacPorts

macports.org 下载安装 MacPorts。

然后在 ~/.bash_profile(如果是 zsh 则在 ~/.zshrc)文件中添加:

export PATH=/opt/local/bin:$PATH
  1. 使用 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。更多信息请参阅开发部分。

  1. 在主目录下创建 bin/ 目录,并添加到 PATH 中:
mkdir ~/bin
PATH=~/bin:$PATH

注:Repo 命令是一段可执行的 Python 脚本,您可以将其放在路径中的任何位置。

  1. 下载 Repo 工具
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
  1. 确保 Repo 可执行
chmod a+x ~/bin/repo

2. 初始化 Repo 客户端

  1. 创建目录

在之前创建的区分大小写的分区中创建目录,来存放 Android 源码,名字自定:

mkdir WORKING_DIRECTORY
cd WORKING_DIRECTORY

如果是使用上面的 mountAndroid 命令来挂载分区的话,则可以使用 /Volumes/android/ 目录

  1. 初始化

使用 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

3. 其他警告信息如果没有终止编译可以忽略