macOS Ventura(13.6)/macOS Sonoma(14.0)编译Android 10.0/Android 11.0源码过程总结(MacBook Pro 2023-Apple M2 Pro)

前置条件


  • macOS Ventura(13.6)/macOS Sonoma(14.0) MacBook Pro 2023-Apple M2 Pro (4能效核、8性能核、32GB内存、2TB磁盘)
  • Homebrew (4.0.28 或更高版本)
  • Xcode Version 15.0 (15A240d)
  • Android Studio Giraffe | 2022.3.1 Patch 1

从Intel版本MacBook Pro迁移到MacBook Pro 2023(Apple M2 Pro)的设备,参考 从Intel版本MacBook Pro 2013迁移到MacBook Pro 2023(Apple M2 Pro)后HomeBrew报错"Error: Cannot install in Homebrew on ARM processor in Intel default prefix (/usr/local)" 重新安装 Homebrew

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

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

通过 UTM 虚拟机,使用 MacOS 提供的虚拟机执行编译的话,性能会更好。但是目前测试发现存在严重的文件系统缺陷,编译/大量文件复制过程中,经常出现文件系统损坏,导致编译失败。

需要在 M2 上使用UTM 虚拟机编译的,可以参考 macOS Sonoma(14.1.1)通过UTM虚拟机编译Android 11.0源码过程总结(MacBook Pro 2023-Apple M2 Pro) 通过 UTM 虚拟机借助 Rosetta 2 的方式进行编译。目前测试来看,性能勉强能用。

另外,我们需要安装 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.

准备环境


创建大小写敏感分区

创建大小写敏感的 APFS 卷宗,相对于文件镜像,性能更好,尤其是针对 TimeMachine 更加友好。参考如下命令:

安装依赖

代码拉取&构建

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

清华大学的镜像

2.Android 模拟器编译(必选)

如果报错:

则说明编译器版本太高,当前的编译配置中缺少指定版本的SDK导致的。

则在源代码代码目录下的 external/qemu/android/scripts/unix/gen-android-sdk-toolchain.sh 文件中找到 prepare_build_for_darwin / prepare_build_for_darwin_aarch64 这两个函数,然后在其中的 OSX_SDK_SUPPORTED 变量列表中增加 14.0 版本,如下:

修改完成后,继续执行上述的编译命令即可。

3.编译源代码

如果报错:

则手工删除 .flake8 这个目录,重新同步。

执行如下命令:

如果报错:

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

执行如下命令:

如果报错:

则需要撤销由于编译模拟器而进行的代码修复,否则无法成功切换代码分支,执行如下命令:

如果报错:

则需要查看自己电脑上安装的 MacOSX.sdk ,执行如下命令:

然后在 build/soong/cc/config/x86_darwin_host.go 文件中找到 "darwinSupportedSdkVersions" 添加 MacOSX.sdk 对应的版本号 14.0 。如下:

如果报错:

问题参考 https://stackoverflow.com/questions/47703239/ld-library-not-found-for-lrt,在旧的 Linux 系统中有 -lrtGNU libc 使用,但是在新的 glibc (after 2.17 from 2013) 之后就没有这个了。解决办法为在 external/v8/Android.bp 找到 -lrt 这一行,把整行全部注释掉。

可以简单的执行如下命令:

如果报错:

则参考 satckoverflow 上的说明,直接在 system/core/base/include/android-base/cmsg.h 中增加 PAGE_SIZE 定义,如下:

修改后的结果大致如下:

如果报错:

则需要在编译配置文件( build/soong/cc/config/x86_darwin_host.go )中的  "darwinCflags" 配置中,增加对 sprintf 不安全的警告的忽略( -Wno-deprecated-declarations ),如下:

如果报错:

则需要在编译配置文件( build/soong/cc/config/x86_darwin_host.go )中的  "darwinCflags" 配置中,增加对指针转换安全的警告的忽略( -Wno-incompatible-pointer-types ),如下:

如果报错:

原因为2021年1月8日 V8 升级导致的,我们直接强制回退 V8 版本到之前的版本,执行如下命令:

如果报错:

我们需要修改 frameworks/base/tools/aapt/Android.bp 移除 -D_DARWIN_UNLIMITED_STREAMS 的定义,可以执行如下命令:

如果报错:

这个问题是由于 macOS 不支持静态链接 libc++ 导致的,需要修改 system/sepolicy/tests/Android.bp ,移除 stl: "libc++_static" 这一行。

可以简单的执行如下命令:

如果报错:

这个原因是由于高版本的 macOS Sonoma(14.0) 已经默认不再内置 Python 2(默认内置的是 Python 3 )导致的,我们需要使用转换成 Python 3 格式的脚本。

转换后可用的脚本内容如下:

额外的模拟器编译配置

通过上面的修改,我们可以成功编译完成,但是编译出的镜像并能在模拟器中正常加载,运行过程中反复重启,观察运行日志,可以看到如下报错:

根据 android-emulator-m1-preview 的说明,这个原因是由于 Applic Silicon 系列芯片的设备只支持 ARM64 的系统镜像,无法运行 ARM32 系列指令集,我们需要修改编译选项,移除对于 ARM32 指令集的支持。

修改 /Volumes/aosp/aosp/build/make/target/board/emulator_arm64/BoardConfig.mk 文件,注释掉 ARM 指令的支持,修改后的代码如下:

继续执行编译,报错如下:

则参照 arpi 11 : framework patch 的说明,删除 platform_testing/build/tasks/tests/native_test_list.mk 中的 resolv_gold_test 这一行, 参考如下:

可以简单的执行如下命令:

继续编译报错:

则参照 Build faild #71 的解决方案:

/Volumes/aosp/aosp/device/generic/goldfish/arm64-vendor.mk

运行镜像

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

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

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

参考链接


发布者

《macOS Ventura(13.6)/macOS Sonoma(14.0)编译Android 10.0/Android 11.0源码过程总结(MacBook Pro 2023-Apple M2 Pro)》上有5条评论

  1. 大佬牛逼,我按照教程,编译完全没有问题。
    但在运行模拟器的时候,分区没有加载出来,模拟器一直黑屏。M1的电脑。
    7] init: starting service 'derive_sdk'...
    [ 5.011416] init: SVC_EXEC service 'derive_sdk' pid 231 (uid 9999 gid 9999+0 context default) started; waiting...
    [ 5.014430] init: Service 'derive_sdk' (pid 231) exited with status 0 waiting took 0.003000 seconds
    [ 5.015364] init: Sending signal 9 to service 'derive_sdk' (pid 231) process group...
    [ 5.016098] libprocessgroup: Successfully killed process cgroup uid 9999 pid 231 in 0ms
    [ 5.017056] init: starting service 'exec 6 (/system/bin/vdc --wait cryptfs init_user0)'...
    [ 5.018007] init: SVC_EXEC service 'exec 6 (/system/bin/vdc --wait cryptfs init_user0)' pid 232 (uid 0 gid 0+0 context default) started; waiting...
    [ 5.027068] chattr (230): highest shadow stack usage: 328 bytes
    [ 5.027940] init: Service 'exec 6 (/system/bin/vdc --wait cryptfs init_user0)' (pid 232) exited with status 0 waiting took 0.009000 seconds
    [ 5.028902] init: Sending signal 9 to service 'exec 6 (/system/bin/vdc --wait cryptfs init_user0)' (pid 232) process group...
    [ 5.029764] libprocessgroup: Successfully killed process cgroup uid 0 pid 232 in 0ms
    [ 5.030396] init: starting service 'apexd-snapshotde'...
    [ 5.031233] init: SVC_EXEC service 'apexd-snapshotde' pid 235 (uid 0 gid 1000+0 context default) started; waiting...
    [ 5.034230] apexd: Snapshot DE subcommand detected
    [ 5.034941] apexd: Failed to stat /metadata/apex/sessions: No such file or directory
    [ 5.035674] apexd: Marking APEXd as ready
    [ 5.036512] init: Service 'apexd-snapshotde' (pid 235) exited with status 0 waiting took 0.005000 seconds
    [ 5.037230] init: Sending signal 9 to service 'apexd-snapshotde' (pid 235) process group...
    [ 5.037867] libprocessgroup: Successfully killed process cgroup uid 0 pid 235 in 0ms
    [ 5.038814] selinux: SELinux: Skipping restorecon on directory(/data)
    [ 5.039328] selinux:
    [ 5.039608] init: starting service 'exec 7 (/system/bin/tzdatacheck /apex/com.android.tzdata/etc/tz /data/misc/zoneinfo)'...
    [ 5.040751] init: SVC_EXEC service 'exec 7 (/system/bin/tzdatacheck /apex/com.android.tzdata/etc/tz /data/misc/zoneinfo)' pid 236 (uid 1000 gid 1000+0 context default) started; waiting...
    [ 5.042994] init: Service 'exec 7 (/system/bin/tzdatacheck /apex/com.android.tzdata/etc/tz /data/misc/zoneinfo)' (pid 236) exited with status 0 waiting took 0.002000 seconds
    [ 5.044311] init: Sending signal 9 to service 'exec 7 (/system/bin/tzdatacheck /apex/com.android.tzdata/etc/tz /data/misc/zoneinfo)' (pid 236) process group...
    [ 5.045372] libprocessgroup: Successfully killed process cgroup uid 1000 pid 236 in 0ms
    [ 5.046195] init: processing action (post-fs-data) from (/system/etc/init/hw/init.usb.rc:6)
    [ 5.046952] init: processing action (post-fs-data) from (/vendor/etc/init/hw/init.ranchu.rc:44)
    [ 5.048320] init: starting service 'ranchu-net'...
    [ 5.049065] init: processing action (post-fs-data) from (/system/etc/init/bootstat.rc:9)
    [ 5.049955] init: processing action (ro.debuggable=1 && post-fs-data) from (/system/etc/init/clean_scratch_files.rc:1)
    [ 5.050963] init: Command 'exec_background - root root -- /system/bin/clean_scratch_files' action=ro.debuggable=1 && post-fs-data (/system/etc/init/clean_scratch_files.rc:2) took 0ms and failed: Could not start exec background service: File /system/bin/clean_scratch_files(labeled "u:object_r:system_file:s0") has incorrect label or no domain transition from u:r:init:s0 to another SELinux domain defined. Have you configured your service correctly? https://source.android.com/security/selinux/device-policy#label_new_services_and_address_denials
    [ 5.054706] init: processing action (post-fs-data) from (/system/etc/init/gsid.rc:14)
    [ 5.055508] init: Not setting encryption policy on: /data/gsi
    [ 5.056233] init: processing action (post-fs-data) from (/system/etc/init/incidentd.rc:21)
    [ 5.056919] init: processing action (post-fs-data) from (/system/etc/init/iorapd.rc:28)
    [ 5.057820] init: processing action (post-fs-data) from (/system/etc/init/logtagd.rc:4)
    [ 5.059114] init: processing action (post-fs-data) from (/system/etc/init/otapreopt.rc:3)
    [ 5.059791] init: starting service 'exec 9 (/system/bin/otapreopt_slot)'...
    [ 5.060654] init: SVC_EXEC service 'exec 9 (/system/bin/otapreopt_slot)' pid 239 (uid 0 gid 0+0 context default) started; waiting...
    [ 5.068567] init: starting service 'dhcpclient_def'...
    [ 5.069555] init: Control message: Processed ctl.start for 'dhcpclient_def' from pid: 242 (setprop ctl.start dhcpclient_def)
    [ 5.070841] init: Service 'exec 9 (/system/bin/otapreopt_slot)' (pid 239) exited with status 1 waiting took 0.010000 seconds
    [ 5.071887] init: Sending signal 9 to service 'exec 9 (/system/bin/otapreopt_slot)' (pid 239) process group...
    [ 5.072858] libprocessgroup: Successfully killed process cgroup uid 0 pid 239 in 0ms
    [ 5.073389] init.ranchu-net (237) used greatest stack depth: 11584 bytes left
    [ 5.073947] init: Service 'ranchu-net' (pid 237) exited with status 0 oneshot service took 0.025000 seconds in background
    [ 5.075086] init: Sending signal 9 to service 'ranchu-net' (pid 237) process group...
    [ 5.075900] libprocessgroup: Successfully killed process cgroup uid 0 pid 237 in 0ms
    [ 5.077087] selinux: SELinux: Skipping restorecon on directory(/data/dalvik-cache/arm)
    [ 5.077672] selinux:
    [ 5.077911] selinux: SELinux: Skipping restorecon on directory(/data/dalvik-cache/arm64)
    [ 5.078505] selinux:
    [ 5.078688] selinux: SELinux: Could not stat /data/dalvik-cache/mips: No such file or directory.
    [ 5.079410] selinux:
    [ 5.079611] selinux: SELinux: Could not stat /data/dalvik-cache/mips64: No such file or directory.
    [ 5.080283] selinux:
    [ 5.080468] selinux: SELinux: Could not stat /data/dalvik-cache/x86: No such file or directory.
    [ 5.081117] selinux:
    [ 5.081296] selinux: SELinux: Could not stat /data/dalvik-cache/x86_64: No such file or directory.
    [ 5.081953] selinux:
    [ 5.082135] init: processing action (post-fs-data) from (/system/etc/init/perfetto.rc:67)
    [ 5.082823] init: Command 'rm /data/misc/perfetto-traces/.guardraildata' action=post-fs-data (/system/etc/init/perfetto.rc:68) took 0ms and failed: unlink() failed: No such file or directory
    [ 5.084367] init: processing action (post-fs-data) from (/system/etc/init/recovery-persist.rc:1)
    [ 5.085207] init: starting service 'exec 10 (/system/bin/recovery-persist)'...
    [ 5.085985] init: processing action (post-fs-data) from (/system/etc/init/tombstoned.rc:10)
    [ 5.086693] init: starting service 'tombstoned'...
    [ 5.087298] init: Created socket '/dev/socket/tombstoned_crash', mode 666, user 1000, group 1000
    [ 5.088007] init: Created socket '/dev/socket/tombstoned_intercept', mode 666, user 1000, group 1000
    [ 5.088746] init: Created socket '/dev/socket/tombstoned_java_trace', mode 666, user 1000, group 1000
    [ 5.089721] init: Service 'exec 10 (/system/bin/recovery-persist)' (pid 246) exited with status 0 oneshot service took 0.003000 seconds in background
    [ 5.090721] init: Sending signal 9 to service 'exec 10 (/system/bin/recovery-persist)' (pid 246) process group...
    [ 5.091504] libprocessgroup: Successfully killed process cgroup uid 1000 pid 246 in 0ms
    [ 5.108408] init: processing action (post-fs-data) from (/system/etc/init/wifi.rc:18)
    [ 5.109322] selinux: SELinux: Skipping restorecon on directory(/data/misc/apexdata/com.android.wifi)
    [ 5.110084] selinux:
    [ 5.110279] init: processing action (post-fs-data) from (/vendor/etc/init/hostapd.android.rc:9)
    [ 5.111630] init: processing action (load_persist_props_action) from (/system/etc/init/hw/init.rc:405)
    [ 5.112509] init: Could not set 'ro.logd.size' to '2M' in /data/local.prop: Read-only property was already set
    [ 5.113549] init: Wait for property 'ro.persistent_properties.ready=true' took 1ms
    [ 5.114187] init: starting service 'logd-reinit'...
    [ 5.114857] init: processing action (load_persist_props_action) from (/system/etc/init/flags_health_check.rc:1)
    [ 5.115724] init: Top-level directory needs encryption action, eg mkdir /data/server_configurable_flags encryption=Require
    [ 5.116301] logd.daemon: reinit
    [ 5.116839] init: starting service 'exec 11 (/system/bin/flags_health_check BOOT_FAILURE)'...
    [ 5.117844] init: SVC_EXEC service 'exec 11 (/system/bin/flags_health_check BOOT_FAILURE)' pid 249 (uid 1000 gid 1000+0 context default) started; waiting...
    [ 5.119077] init: Service 'logd-reinit' (pid 248) exited with status 0 oneshot service took 0.004000 seconds in background
    [ 5.120070] init: Sending signal 9 to service 'logd-reinit' (pid 248) process group...
    [ 5.120764] libprocessgroup: Successfully killed process cgroup uid 1036 pid 248 in 0ms
    [ 5.122780] init: Service 'exec 11 (/system/bin/flags_health_check BOOT_FAILURE)' (pid 249) exited with status 0 waiting took 0.004000 seconds
    [ 5.123814] init: Sending signal 9 to service 'exec 11 (/system/bin/flags_health_check BOOT_FAILURE)' (pid 249) process group...
    [ 5.124667] libprocessgroup: Successfully killed process cgroup uid 1000 pid 249 in 0ms
    [ 5.125279] init: processing action (load_persist_props_action) from (/system/etc/init/logcatd.rc:29)
    [ 5.126067] init: processing action (load_bpf_programs) from (/system/etc/init/bpfloader.rc:20)
    [ 5.126817] init: starting service 'bpfloader'...
    [ 5.127504] init: processing action (persist.sys.fuse=true && zygote-start) from (/system/etc/init/hw/init.rc:797)
    [ 5.128660] init: processing action (ro.crypto.state=unsupported && zygote-start) from (/system/etc/init/hw/init.rc:820)
    [ 5.129630] init: starting service 'update_verifier_nonencrypted'...
    [ 5.135121] init: SVC_EXEC service 'update_verifier_nonencrypted' pid 251 (uid 0 gid 2001+1 context default) started; waiting...
    [ 5.136037] init: Service 'update_verifier_nonencrypted' (pid 251) exited with status 0 waiting took 0.005000 seconds
    [ 5.136994] init: Sending signal 9 to service 'update_verifier_nonencrypted' (pid 251) process group...
    [ 5.137745] libprocessgroup: Successfully killed process cgroup uid 0 pid 251 in 0ms
    [ 5.138821] init: starting service 'statsd'...
    [ 5.139349] init: Created socket '/dev/socket/statsdw', mode 222, user 1066, group 1066
    [ 5.140541] init: starting service 'netd'...
    [ 5.140931] init: Created socket '/dev/socket/dnsproxyd', mode 660, user 0, group 3003
    [ 5.141647] init: Created socket '/dev/socket/mdns', mode 660, user 0, group 1000
    [ 5.142347] init: Created socket '/dev/socket/fwmarkd', mode 660, user 0, group 3003
    [ 5.149034] init: starting service 'zygote'...
    [ 5.149659] init: Created socket '/dev/socket/zygote', mode 660, user 0, group 1000
    [ 5.150550] init: Created socket '/dev/socket/usap_pool_primary', mode 660, user 0, group 1000
    [ 5.152106] init: Service 'bpfloader' (pid 250) exited with status 0 oneshot service took 0.024000 seconds in background
    [ 5.153581] init: Sending signal 9 to service 'bpfloader' (pid 250) process group...
    [ 5.154418] libprocessgroup: Successfully killed process cgroup uid 0 pid 250 in 0ms
    [ 5.155148] init: processing action (zygote-start) from (/vendor/etc/init/hw/init.ranchu.rc:51)
    [ 5.156252] init: processing action (firmware_mounts_complete) from (/system/etc/init/hw/init.rc:411)
    [ 5.157329] init: processing action (early-boot) from (/system/etc/init/installd.rc:5)
    [ 5.159334] libprocessgroup: Failed to open /dev/stune/top-app/tasks: No such file or directory: No such file or directory
    [ 5.159959] init: processing action (boot) from (/system/etc/init/hw/init.rc:836)
    [ 5.160182] libprocessgroup: Failed to apply MaxPerformance task profile: No such file or directory
    [ 5.161392] init: starting service 'hidl_memory'...
    [ 5.162688] init: starting service 'vendor.audio-hal'...
    [ 5.164191] init: starting service 'vendor.authsecret-1-0'...
    [ 5.165360] init: starting service 'vendor.bluetooth-1-1'...
    [ 5.166725] init: starting service 'vendor.camera-provider-2-6-google'...
    [ 5.168580] libprocessgroup: Failed to open /dev/stune/foreground/tasks: No such file or directory: No such file or directory
    [ 5.169746] libprocessgroup: Failed to apply HighPerformance task profile: No such file or directory
    [ 5.171097] init: starting service 'vendor.contexthub-hal-1-1-mock'...
    [ 5.172616] init: failed to write pid to files: couldn't write 262 to /dev/cpuset/camera-daemon/tasks: No such file or directory
    [ 5.174243] init: starting service 'vendor.drm-clearkey-hal-1-3'...

    1. 目前还没找到原因,不仅仅是M1 编译出来的镜像工作不正常,就是 X86编译出来的ARM镜像 也是各种启动问题,倒是编译出的X86镜像都很正常

  2. 大佬牛批,我升级到macos14前编译一切正常。直到某天因为要用一下xcode,然后升级了。升级后就开始各种坑了。折腾好久都编译不成功,试一下大佬的方式。有联系方式吗?可以加个v不

    1. 建议还是UTM虚拟机编译,目前测试来看这个是相对来说比较简单的方案,当然,也只能是相对比较简单,当前Apple虚拟化部分在高负载下,磁盘文件系统的实现部分存在缺陷,会导致虚拟机报告文件系统损坏(不影响真机)。

      一般也是要重试几次即可编译成功,编译出的结果经过验证是可用的。

发表回复

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