macOS Sonoma(14.2.1)通过UTM虚拟机编译Android 12.1源码过程总结(MacBook Pro 2023-Apple M2 Pro)

前置条件


根据 Google 官方文档,2021年6月22日之后的Android系统版本不支持在macOS系统上构建,我们在 Applic SiliconmacOS 系统是不能直接成功构建后续版本的,但是之前的版本可以在修改编译配置后成功编译,只是是否能正常运行存疑

尝试过使用 Podman Desktop / Docker 方式进行编译、也尝试过借助 OrbStackLima 这些纯虚拟机通过安装 ubuntu 22.04 系统镜像的方式进行编译,结果都在执行 lunch 命令的时候长时间卡住,观察系统进程发现名为 nsjail 进程的 CPU 占用持续卡住在 100% 上无法继续编译,并且由于 Docker 或者虚拟机文件系统是 Linux 文件系统,而宿主机的文件系统是 AppleFS 文件系统,导致需要进行文件转换,中间的转换性能代价非常高,性能很差。

相反,目前测试来看,直接在 UTM 虚拟机里执行编译的性能反倒更好一些。

目前测试发现存在严重的文件系统缺陷,编译/大量文件复制过程中,经常出现文件系统损坏,导致编译失败。

原因参考:

https://github.com/utmapp/UTM/pull/5869
https://github.com/utmapp/UTM/pull/5919

需要等待 UTM 合并到主分支。

另外,我们需要安装 Rosetta 2 支持运行部分 x86_64 应用。注意  Rosetta 2 只支持 64 位应用,不支持 32 位应用。 参考 Does Rosetta 2 support 32-bit Intel apps?

Important: Platform development on MacOS isn't supported as of June 22, 2021.

准备环境


安装依赖

安装虚拟机应用

UTM 官网,安装最新版本的 UTM 安装包。

安装ARM版本操作系统

Ubuntu Server for ARM 官网,下载 Ubuntu 22.04.3 LTS ARM 系统镜像。

创建虚拟机

虚拟化引擎选择部分,务必勾选 Apple Virtualization 。如果不勾选此项,那么后续的 Rosetta 是没办法选择的,并且性能是不足以进行系统编译的。

如下图:

内存,CPU 部分,建议尽量多给一些,这样编译速度更快,但是不一太多,太多会导致宿主机卡顿,这个需要均衡考虑,尤其是宿主机还需要同步执行其他事情的时候。

如下图:

磁盘部分,建议至少 400GB 以上,如下图:

共享目录部分,如果是编译代码,不建议使用,性能不够,如果是常规的文件共享,问题不大。

如下图:

最终的配置如下:

操作系统安装

键盘点击确认(回车),默认下一步

键盘点击确认(回车),默认下一步

键盘点击确认(回车),默认下一步

键盘点击确认(回车),默认下一步

键盘点击确认(回车),默认下一步

键盘点击确认(回车),默认下一步

等待镜像服务器测试完成之后,键盘点击确认(回车),默认下一步

接下来, 注意:务必取消掉 “Set up this disk as an LVM group”选项,否则不管你给出磁盘有多大,都是默认分配 100GB 的磁盘,其余磁盘空间需要手工分区。 

移动上下键,到指定位置,点击键盘上的空格,取消选中,如下图:

移动上下键,到 Done ,键盘点击确认(回车),默认下一步

键盘点击确认(回车),默认下一步

移动上下键,到 Continue ,确认使用上述的分区配置,键盘点击确认(回车),执行下一步

用户名,密码,机器名等配置(此处,我们默认都输入 ubuntu),输入完成后,移动上下键,键盘点击确认(回车),执行下一步

键盘点击确认(回车),默认下一步

配合上下键,空格,选中 "Install OpenSSH server", 键盘点击确认(回车),默认下一步

此处,没有我们需要的服务器配置,键盘上下键调整到 “Done” 高亮 ,点击确认(回车),默认下一步

等待安装完成,直到底部出现 “Reboot Now”,键盘上下键调整到 “Reboot Now” 高亮 ,点击确认(回车)系统重启,安装完成。

重启之后,会再次回到安装界面,如下图:

原因是我们没有弹出安装镜像导致的,我们需要手工弹出安装光盘,直接关闭虚拟机,然后如下操作

设置 Rosetta 启用对于 x86_64 架构应用的支持

登录到刚刚创建的虚拟机(建议通过 SSH 登录进去,直接通过虚拟机提供的屏幕操作,不方便复制粘贴),然后执行如下命令:

添加到系统文件加载项,要求系统启动的时候自动加载 rosetta 。

在文件尾部新增一行:

修改后的配置文件类似如下:

执行 df 命令,应该可以看到 rosetta 已经被正常加载,如下:

配置完成之后,务必重启一次虚拟机,否则大概率虚拟机系统会在运行过程中崩溃。

启用多处理器架构应用安装

此时注意,默认情况下 ARM 安装包的 APT 服务器是跟 x86 安装包的服务器是不同的,如果执行上述命令后,更新安装源,会报错找不到文件,我们需要手工指定不同架构的安装包搜索服务器。可以参照下面的方式修改 /etc/apt/sources.list 显式声明各个架构的服务器地址,如下:

更新源

至此,我们已经可以在 ARM64 环境下,正常安装并运行 x86_64 的应用,只是安装应用的时候,需要明确指定安装包的处理器架构。

安装编译依赖

代码拉取&构建

1. 使用镜像下载Android源代码

清华大学的镜像

2.检出需要编译的分支

3.准备编译环境

4.编译

注意,如果执行 

的时候长时间卡住,Ctrl + C 停止之后报错:

则观察当前执行的进程,会发现名为 nsjail 的进程长时间卡住,并且 100% CPU 占用,如下:

nsjailAndroid 用于建立隔离环境,防止进程之间相互干扰的一个沙箱工具,功能类似 Docker

应用位于源代码的位置: prebuilts/build-tools/linux-x86/bin/nsjail

Rosetta 转译造成应用运行异常,最简单的方案,就是直接重命名或者删除 prebuilts/build-tools/linux-x86/bin/nsjail,让编译工具找不到 nsjail, 不使用沙箱进行编译即可。

如下:

针对警告 “Build sandboxing disabled due to nsjail error.” 可以直接无视。

如果报错:

则说明当前的 repo 版本太低,需要更新到最新版本。

执行如下命令:

如果报错:

这个问题解决比较简单,直接在编译命令里面禁止 DEXPREOPT 即可,参考 Compiling a deodexed AOSP?

如下:

其他错误

如果是编译 Android 12.0 以下的源代码,则可能会长时间卡住在 link 命令,结束不了,如下:

观察构建日志,会发现在如下命令卡住:

我们手工执行这些卡住的命令,也是照样卡住,如下:

于是执行观察进程信息:

可以看到相当多的进程卡住了。

随便选择一个进程,查看进程当前卡住的地方

可以发现都是卡住在相同的地方。

比如,如下命令:

去掉其中的

就可以正常编译通过了。

如下的命令:

同理,去掉全部的静态库链接如下:

也可以编译通过,经过不断排查,发现这个是由于 llvm-toolchins 的 BUG 导致的,Android 11 默认使用 llvm-toochains 11.0.5 版本构建。

构建工具版本可以通过如下命令查看:

llvm-toochains 11.0.5 版本存在卡住的问题,具体原因暂时没有找到相关的修改记录。

一个可能的解释来自 chromium 的构建脚本 build.py,关键部分的解释截图如下:

当版本升级到 llvm-toochains 12.0 以上版本之后,此问题可以解决。

因此编译低版本的代码的时候,可能需要手工升级构建工具版本,部分编译报错需要自行调整。

如何进行相关的调整,可以参考如下的官方文档

运行镜像

选择 system-qemu.imgvendor-qemu.img,这两个镜像是专门为 qemu 运行制作的,如果选择 system.img vendor.img,则 avd 运行失败。

上面运行起来的镜像是从 ~/aosp/out/target/product/emulator_arm64/hardware-qemu.ini 读取配置信息的,但是这个文件直接修改无效。我们如果需要修改参数,只能从启动参数中设置。

比如我们如果需要增大内存,开启 GPU 的支持,则执行如下命令:

参考链接


发布者

《macOS Sonoma(14.2.1)通过UTM虚拟机编译Android 12.1源码过程总结(MacBook Pro 2023-Apple M2 Pro)》上有2条评论

  1. 使用utm ubuntu arm64的虚拟机按照步骤编译碰到下面的问题了,大佬有碰到吗

    # A fatal error has been detected by the Java Runtime Environment:
    #
    # SIGSEGV (0xb) at pc=0x00007fffff0423b9, pid=1499792, tid=1499795
    #
    # JRE version: OpenJDK Runtime Environment (11.0.4) (build 11.0.4+0-6508549)
    # Java VM: OpenJDK 64-Bit Server VM (11.0.4+0-6508549, mixed mode, tiered, compressed oops, g1 gc, linux-amd64)
    # Problematic frame:
    # V [libjvm.so+0xa423b9] MethodMatcher::matches(methodHandle const&) const+0x39
    #
    # Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E" (or dumping to /home/king/mikrom12_gitlab/core.1499792)
    #
    # An error report file with more information is saved as:
    # /home/king/mikrom12_gitlab/hs_err_pid1499792.log
    #
    # If you would like to submit a bug report, please visit:
    # http://bugreport.java.com/bugreport/crash.jsp
    #
    #
    # -XX:OnError="cat hs_err_pid%p.log"
    # Executing /bin/sh -c "cat hs_err_pid1499792.log" ...
    #
    # A fatal error has been detected by the Java Runtime Environment:
    #
    # SIGSEGV (0xb) at pc=0x00007fffff0423b9, pid=1499792, tid=1499795
    #
    # JRE version: OpenJDK Runtime Environment (11.0.4) (build 11.0.4+0-6508549)
    # Java VM: OpenJDK 64-Bit Server VM (11.0.4+0-6508549, mixed mode, tiered, compressed oops, g1 gc, linux-amd64)
    # Problematic frame:
    # V [libjvm.so+0xa423b9] MethodMatcher::matches(methodHandle const&) const+0x39

    1. 看看系统是不是低于 macOS Sonoma 14.3.1 ? 低版本的 macOS 虚拟化存在缺陷,部分Java指令集翻译错误,这个Apple在后续版本修复了,可以看到Docker之类的都有这个修改记录的。目前已知的解决方案就是升级系统到最新版本。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注