macOS 下载编译 aosp 源码

2022-03-17 08:28:20 浏览数 (1)

最近在读《Android 进阶指北》,开篇就是介绍如何在安装到 VirtualBox 的 Ubuntu 上进行下载和编译 aosp(Android Open Source Project)。由于我的电脑是 macOS,所以首先尝试了在 macOS 上进行下载和编译 aosp,其中碰到了很多问题,所以整理此文出来,给后来人借鉴。

下载编译环境: 系统:macOS Catalina 10.15.6 aosp 目标编译平台:android-9.0.0_r1

1. 配置 macOS 环境

由于 Git 对区分大小写比较敏感,而下载和管理 aosp 源码用到了 Git。所以首先要划分一块区分大小写的磁盘出来。

创建区分大小写的磁盘

使用一下命令即可创建一块区分大小写、日志式的磁盘。

代码语言:javascript复制
hdiutil create -type SPARSE -fs ‘Case-sensitive Journaled HFS ’ -size 200g ~/android.dmg

其中 size 根据需要调整,如果只是下载源码,100g 差不多够用。如果要编译就要 200g 及以上。假如后续磁盘空间不够,可以使用以下命令调整已创建的磁盘大小:

注:这里需要注意的是,根据系统不同,创建出的磁盘文件后缀不同,分别可能是 android.dmg.sparseimageandroid.dmg。所以以下命令执行的对应文件名不一致。

代码语言:javascript复制
hdiutil resize -size g ~/android.dmg.sparseimage

可以在 ~/.bash_profile 中添加以下两个方法来方便的挂载、卸载磁盘,执行方法前可能需要执行一下 source ~/.bash_profile 导入方法:

代码语言:javascript复制
# mount the android file image
function mountAndroid { hdiutil attach ~/android.dmg.sparseimage -mountpoint /Volumes/android; }

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

挂载之后可以在 Finder 或者 磁盘工具 中看到该磁盘,其格式为 MacOS 扩展、区分大小写、日志式磁盘。如下图所示:

另外,在 macOS 中默认同时打开文件数量上限较低,当我们并行编译 aosp 时,可能会超出此上限。所以如果计划并行编译源码(最好是这样,因为代码量实在太多了),就需要设置文件描述符上限,将以下内容添加到 ~/.bash_profile 即可,同样的可能需要执行 source ~/.bash_profile 来使配置生效:

代码语言:javascript复制
# set the number of open files to be 1024
ulimit -S -n 1024

至此,关于磁盘文件相关的内容就设置好了。下面来看一下如何安装下载时会用到的软件。

安装所需软件

安装 Xcode

执行以下命令即可:

代码语言:javascript复制
xcode-select --install
使用 homebrew 安装 Git

执行以下命令安装 homebrew:点击跳转 Homebrew 官网

代码语言:javascript复制
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

执行以下命令安装、配置 Git:

代码语言:javascript复制
# install git by homebrew
brew install git

# config git user info
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
检查是否已安装 python2.7

aosp 要求 python2.7 版本,python3 则不行。macOS 自带了 python2.7 版本,可以使用以下命令进行检查:

代码语言:javascript复制
python --version

有以下输出即可:

代码语言:javascript复制
Python 2.7.16
安装 jdk8

点击下载 jdk 8,选择 macOS 版本进行下载安装。安装完成之后,运行以下命令进行验证:

代码语言:javascript复制
java -version
下载 repo 工具

aosp 源码是通过 Git 进行管理的,但是由于代码量巨大,单纯使用 Git 已经无法满足日常便捷操作的目标。所以 Google 以 Git 为基础,使用 Python 编写了 repo 这款工具,让开发者可以更方便轻松的管理源码,点击查看 repo 使用详情。

首先,创建 repo 工具存放文件夹。

代码语言:javascript复制
mkdir ~/bin

然后,下载 repo,并赋予 repo 可执行权限。

代码语言:javascript复制
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo

chmod a x ~/bin/repo

最后,将 repo 工具添加到 PATH 路径,这样我们可以在之后在终端直接进行访问,无需关心 repo 所在路径。在 ~/.bash_profile 添加以下内容即可:

代码语言:javascript复制
export PATH=~/bin:$PATH

至此,相关软件安装完毕。接下来开始下载源码。

2. 使用 repo 下载源码

创建文件夹

首先,进入我们之前创建、并挂载的磁盘,创建并进入 aosp 源码下载文件夹。

代码语言:javascript复制
cd /Volumns/android
mkdir aosp
cd aosp

初始化版本库

然后,初始化一个指定版本的 aosp 源码库。如果命令后跟上 -b 参数,则代表初始化指定版本的源码库,否则为默认的 master 分支。分支列表可以参考 aosp 代号、标记和细分版本号。初始化代码如下:

代码语言:javascript复制
# default is master
repo init -u https://android.googlesource.com/platform/manifest

# define 9.0.0_r1 branch
repo init -u https://android.googlesource.com/platform/manifest -b android-9.0.0_r1

如果存在网络问题,可以使用清华镜像源,具体可以参考 AOSP 清华大学开源软件镜像站。这里要注意的是,如果单纯阅读代码使用,使用清华源即可。如果计划编译代码,建议能够使用 Google 官方源就用官方源,因为清华源存在没有同步的问题,可能会造成一些不必要的麻烦。

tips: 使用清华源尽量在夜间进行,白天清华源请求量大,下载源码十分容易中断。晚上则比较顺畅。

如有下图输出即为初始化成功:

initSuccess

下载源码

在已经初始化好的 aosp 源码目录下执行以下命令即可开始下载源码。

代码语言:javascript复制
repo sync

如下图输出即为下载成功:

downloadSuccess

3. 构建源码

aosp 构建系统简介

aosp 原本是使用 make 进行构建源码。但是由于在 Android 上 make 十分缓慢,易出错等等原因,Google 转而使用由 Go 语言编写的 Soong 构建系统。Soong 是 make 构建系统的替代品,make 构建系统使用 .mk 文件进行书写编译规则,Soong 则是使用 Blueprint 的 .bp 文件书写。.bp 文件是一种类似 JSON 的语法结构,更加简单明了。Soong 最终将 .bp 文件编译成 ninja 文件,进而由 ninjia 进行编译。ninjia 是一种追求编译速度的小型构建系统,其设计目标是嵌入到一个高级构建系统中,追求尽可能快的编译速度。其构建文件可以读懂但是并不适合手动编写——类似于汇编语言,一般是通过将其他高级构建系统的构建文件编译为 ninjia 文件后作为输入。

此时读者可能产生疑问,Google 由 make 转 Soong 不可能是一夜之间发生的,那如何兼容两者呢?答案是,针对原有的 .mk 文件,Google 开发了 kati 系统,将其也编译为 ninjia 文件,再交给 ninjia 进行编译。

总的来说,Soong 是通过解析 .bp 文件为 ninjia 文件,将 .mk 文件通过 kati 编译为 ninjia 文件,最后进行构建的。

如果你想了解更多,以下资源可以参考:

  • Android Make Build System
  • kati
  • Soong
  • Ninja, a small build system with a focus on speed

初始化构建环境

执行 envsetup.sh 脚本来初始化环境,envsetup.sh 会添加一系列命令可供编译使用。

注:编译相关命令需要在 bash shell 下执行,如果你使用了 zsh 等其他 shell,需要执行 bash 进入 bash shell 后再运行构建命令。

代码语言:javascript复制
source build/envsetup.sh

选择编译的目标系统

代码语言:javascript复制
lunch

此时输出如下:

代码语言:javascript复制
/Volumes/Windows/aosp » 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. aosp_car_arm-userdebug
     8. aosp_car_arm64-userdebug
     9. aosp_car_x86-userdebug
     10. aosp_car_x86_64-userdebug
......
Which would you like? [aosp_arm-eng]

输入英文或者序号都可以,因为我的电脑 CPU 是 x86 架构,所以这里选择 aosp_x86-eng 进行编译,这样运行 Android 虚拟机时,速度会比较快。

开始编译

执行 make 命令即可开始编译,如果需要并行构建的话,需要添加 -j 参数,示例命令如下:

代码语言:javascript复制
make

# simplify
m

# multi task
m -j16

在编译的时候会碰到很多问题,其解决方法见下一节一一道来。编译成功最后会打印 build completed successfully

运行模拟器

如果刚刚编译完,直接执行 emulator 即可。否则需要重新执行 source build/envsetup.sh; lunch aosp_x86-eng; 导入 emulator 命令。

代码语言:javascript复制
emulator

最后成功运行起来了自己构建出来的 Android 虚拟机了!

emualtor

4. 可能碰到的问题及其解决

问题一:Could not find a supported mac sdk

问题详情输出如下:

代码语言:javascript复制
internal error: Could not find a supported mac sdk: [“10.10” “10.11” “10.12” “10.13”]
ninja: build stopped: subcommand failed.

执行 ls /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs 发现,MacOSX.sdk 之外,还有一个与其对应的 MacOSX10.15.sdk 软链接。说明本机的 mac sdk 为 10.15 版本。

解决方法:

修改 build/soong/cc/config/x86_darwin_host.go 文件,在 darwinSupportedSdkVersions 下添加 “10.15”,(记得带英文逗号)。

问题二:执行上述操作后,重试编译报错

报错详情如下:

代码语言:javascript复制
ld: symbol(s) not found for architecture i386

其原因是,aosp 并没有支持所有的 mac sdk 版本。比如说我电脑的 mac sdk 版本 10.15,相关配置文件 build/soong/cc/config/x86_darwin_host.go 中的配置如下:

代码语言:javascript复制
darwinSupportedSdkVersions = []string{
        "10.10",
        "10.11",
        "10.12",
        "10.13",

从这里可以看到官方测试通过、支持的 mac sdk 为上述几个版本。而更新的版本是不支持的。

最终在 Unable to make AOSP systemimage on macOS Mojave 找到了解决问题的答案。

解决方法:

去 phracker/MacOSX-SDKs 下载 10.13 版本。解压后放置到 Mac sdk 文件夹 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs 下。

问题三:执行上述操作后,重新编译又回到问题一

其原因应该是 aosp 编译系统查找 mac sdk 的规则问题,使用以下方法可以欺骗一下构建系统。

解决方法:

移除现有的 MacOSX10.15.sdk 软链接,执行以下命令来给之前复制进来的 10.13 sdk 创建一个名为 MacOSX10.15.sdk 的软连接,来冒充 10.15 sdk。最后这个问题终于解决。

代码语言:javascript复制
cd /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs

sudo ln -s MacOSX10.13.sdk MacOSX10.15.sdk

参考资料:android - Running AOSP build on Mac (Yosemite and later) - Stack Overflow。

问题四:sepolicy_tests_intermediates/sepolicy_tests error

问题详情如下:

代码语言:javascript复制
...
[ 89% 64112/71309] build out/target/pr...icy_tests_intermediates/sepolicy_tests
FAILED: out/target/product/generic/obj/ETC/sepolicy_tests_intermediates/sepolicy_tests
...

其原因是 libc _static 库被重复引入了。删除 system/sepolicy/tests/Android.pb 文件中的 libc _static 那一行即可。后来有提交修复了该问题,点击查看该提交的 diff。其改动如下图:

diff

参考资料

  • 《Android 进阶指北》
  • Releases · phracker/MacOSX-SDKs · GitHub
  • AOSP 清华大学开源软件镜像站
  • 在解决问题过程中 Google、StackOverflow 帮助很大,感谢

注:一些资料已在文中列出在此不再累述

版权声明 无需授权即可转载,甚至无需保留以上版权声明; 转载时请务必注明作者。

0 人点赞