ubuntu 20.04编译Android 11源代码&模拟器

Android 11 系统映像可直接将 ARM 指令转换成 x86 指令,因此以前很多需要真机测试的情况,现在只需要模拟器就可以进行操作了。

不过,根据官方博客 Run ARM apps on the Android Emulator 尾部的一段注意事项:

Note that the ARM to x86 translation technology enables the execution of intellectual property owned by Arm Limited. It will only be available on Google APIs and Play Store system images, and can only be used for application development and debug purposes on x86 desktop, laptop, customer on-premises servers, and customer-procured cloud-based environments. The technology should not be used in the provision of commercial hosted services.

这段事项说明,自己编译的镜像是没办法用上这个功能的,必须是Google编译好的镜像。

由于众所周知的原因,我们是没办法正常下载Android的源代码的,因此只能使用国内的镜像来操作了。

1.安装repo工具以及依赖

$ sudo apt-get install gcc make perl

$ sudo apt-get install ccache

$ sudo apt-get install curl

$ sudo apt-get install python

# 安装repo的时候需要指定 --devmode ,否则同步的时候,会报告如下错误信息:
#repo sync -j4 --fail-fast
#/snap/git-repo/18/usr/bin/python: can't open file '~/aosp/.repo/repo/main.py': [Errno 13] Permission denied
# 不要使用 snap 安装的repo, 目前存在很多异常问题, 
# ubuntu 20.04缺少repo 原因是 repo 废弃 python2 的进度慢了一些,
# 导致没办法集成到这个版本的系统里面
# sudo snap install git-repo --devmode

# 手工下载 repo 
$ mkdir -p ~/.bin

$ PATH="${HOME}/.bin:${PATH}"

$ curl https://storage.googleapis.com/git-repo-downloads/repo > ~/.bin/repo

$ chmod a+rx ~/.bin/repo

$ echo "PATH=${HOME}/.bin:${PATH}" >> ~/.bashrc

$ sudo apt-get install aria2

$ sudo apt-get install git

$ sudo apt install -y libssl-dev

# 解决 
# prebuilts/clang/host/linux-x86/clang-3289846/bin/clang.real: error while loadin
g shared libraries: libncurses.so.5: cannot open shared object file: No such fi
le or directory

$ sudo apt install libncurses5


# 安装VSCode,方便后续查看代码
$ sudo snap install code --classic

$ git config --global user.email "user@email.com"

$ git config --global user.name "user"

2.在需要存储代码的地方创建文件夹

$ mkdir ~/AndSrc

$ cd ~/AndSrc

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

清华大学的镜像

# 建议直接下载压缩包,使用repo更新基本上都会失败,即使用国内镜像也是一样(目前大约96GB)

$ aria2 -c https://mirrors.ustc.edu.cn/aosp-monthly/aosp-latest.tar

$ tar xvf aosp-latest.tar

$ cd aosp

# 解决 fatal: Cannot get https://gerrit.googlesource.com/git-repo/clone.bundle

$ git clone https://gerrit-googlesource.lug.ustc.edu.cn/git-repo

4.Android 模拟器编译(可选)

# 配置默认的 python为python3,否则会在运行时报错  SyntaxError: invalid syntax to repo init in the AOSP code

$ sudo mv /usr/bin/python /usr/bin/python.bak

$ sudo ln -s /usr/bin/python3 /usr/bin/python

# Android 11模拟器对应分支 emu-30-release 

$ repo init -b emu-30-release 

# 可能会失败多次,不断尝试,直到完全成功
$ repo sync -j4 --fail-fast

$ cd external/qemu/android/

$ ./rebuild.sh --no-tests

编译完成之后,产生的模拟器可执行文件及库文件都位于`external/qemu/objs/android`目录下:

~/AndSrc/aosp/external/qemu/android/objs$ ls
android_emu64_unittests           emulator64-mips
android_emu_metrics64_unittests   emulator64_simg2img
bin64                             emulator64_test_crasher
build                             emulator64-x86
emugl64_common_host_unittests     emulator-check
emulator                          lib
emulator64-arm                    lib64
emulator64_crashreport_unittests  lib64GLcommon_unittests
emulator64-crash-service          lib64OpenglRender_unittests
emulator64_img2simg               qemu
emulator64_libui_unittests        resources
emulator64_make_ext4fs

后面就可以像执行 SDK 中的模拟器那样,执行我们编译的模拟器了:

# 下面是个例子,只有设备上已经通过Android SDK 创建过 Nexus_5_API_30_x86,才可以成功执行

~/AndSrc/aosp/external/qemu/android/objs$ ./emulator -avd Nexus_5_API_30_x86

5.列出android-11全部分支

$ cd .repo/manifests && git branch -a | cut -d / -f 3 | grep android-11

6.编译Android 11系统镜像

$ cd ~/AndSrc/aosp

# 前面的编译可能会产生部分垃圾文件,需要清理一下,清理之前,编译好的文件提前备份一下

$ rm -rf *

# 解决 fatal: Cannot get https://gerrit.googlesource.com/git-repo/clone.bundle

$ git clone https://gerrit-googlesource.lug.ustc.edu.cn/git-repo

# 配置默认的 python为python3,否则会在运行时报错  SyntaxError: invalid syntax to repo init in the AOSP code

$ sudo mv /usr/bin/python /usr/bin/python.bak
 
$ sudo ln -s /usr/bin/python3 /usr/bin/python

$ repo init -b android-11.0.0_r48

# 可能会失败多次,不断尝试,直到完全成功
$ repo sync -j4 --fail-fast

# 如果上面的命令失败,可以尝试调整为单线程,目前测试发现单线程虽然慢点,但是基本不会失败,多线程经常失败 
# repo sync -j1 --fail-fast

7.引入编译环境变量

$ source build/envsetup.sh

8.设置编译目标,此处我们指定编译x86_64下的完整调试版本

# eng:代表 engineer,开发工程师的版本,拥有最大的权限(root等),具有额外调试工具的开发配置。
# 执行 lunch 命令可以输出全部的编译目标列表
# 更多的编译选项可以从 build/make/target/product/ 下看到
# lunch aosp_x86_arm-eng 编译后的镜像可以安装 arm 应用, 不过在不进行任何代码调整的情况下,应用启动会崩溃

# 不能安装 arm 应用
$ lunch aosp_x86_64-eng

9.如果需要跟踪调试代码,建议编译为调试类型

$ export TARGET_BUILD_TYPE=debug

10.编译

$ export USE_CCACHE=1  

# 清理代码,为编译准备干净的环境

$ make clobber

$ make -j8

注意此处如果发生编译失败,原因基本上是编译顺序导致的引用出错,也就是某些模块还没有编译完成,其他模块已经开始尝试链接,导致依赖错误,此时只要把多线程并发编译修改成单线程编译即可,即直接执行

$ make

如果由于内存不足导致的编译失败,可以增加物理内存。但是如果内存无法增加的话,那么适当增加交换分区/交换文件的大小(建议配置16GB以上的交换分区)可以解决此问题,只是编译速度会下降。

运行镜像

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

$ cd ~/AndSrc/aosp

$ export ANDROID_BUILD_TOP=~/AndSrc/aosp

$ export PATH=$PATH:$ANDROID_BUILD_TOP/out/host/linux-x86/bin

$ export ANDROID_SWT=$ANDROID_BUILD_TOP/out/host/linux-x86/framework

$ export ANDROID_PRODUCT_OUT=$ANDROID_BUILD_TOP/out/target/product/generic_x86_64

$ ./prebuilts/android-emulator/linux-x86_64/emulator -system ./out/target/product/generic_x86_64/system-qemu.img -data ./out/target/product/generic_x86_64/data.img -ramdisk ./out/target/product/generic_x86_64/ramdisk-qemu.img -vendor ./out/target/product/generic_x86_64/vendor-qemu.img -verbose -show-kernel

上面运行起来的镜像是从`~/AndSrc/aosp/out/debug/target/product/generic/hardware-qemu.ini`即可读取配置信息的,但是这个文件直接修改无效,我们如果需要修改参数,只能从启动参数中设置。
比如我们如果需要增大内存,开启`GPU`的支持,则执行如下命令:

$ ./prebuilts/android-emulator/linux-x86_64/emulator -system ./out/target/product/generic_x86_64/system-qemu.img -data ./out/target/product/generic_x86_64/data.img -ramdisk ./out/target/product/generic_x86_64/ramdisk-qemu.img -vendor ./out/target/product/generic_x86_64/vendor-qemu.img -gpu on -memory 4096 -verbose -show-kernel
编译支持ARM应用的镜像

尽管根据

Note that the ARM to x86 translation technology enables the execution of intellectual property owned by Arm Limited. It will only be available on Google APIs and Play Store system images, and can only be used for application development and debug purposes on x86 desktop, laptop, customer on-premises servers, and customer-procured cloud-based environments. The technology should not be used in the provision of commercial hosted services.

我们自己编译的镜像是没办法直接从源代码编译支持安装运行 ARM 应用的。

但是有两个变通方案:

  1. Google官方的 Android 11 镜像中提取需要的文件塞到我们自己编译的镜像里,参考方案: Adding ARM native bridge to the AOSP11 x86 emulatorandroid_vendor_google_emu-x86
  2. 使用 Intel Houdini 实现支持,参考方案:Include Intel Houdini in Android-x86

首先,我们尝试从Google官方的 Android 11 镜像中提取需要的文件,执行如下脚本:

# 安装镜像文件提取依赖库
$ sudo apt install curl rsync zip unzip binwalk

# git clone https://gitlab.com/android-generic/android_vendor_google_emu-x86 vendor/google/emu-x86

$ git clone https://gitlab.com/LongSky/android_vendor_google_emu-x86.git vendor/google/emu-x86

$ . vendor/google/emu-x86/update.sh x86_64

$ sed -i '$a\\n-include vendor/google/emu-x86/board/native_bridge_arm_on_x86.mk' build/make/target/board/generic_x86_64/BoardConfig.mk

$ sed -i '$a\\n$(call inherit-product-if-exists, vendor/google/emu-x86/target/native_bridge_arm_on_x86.mk)' build/make/target/board/generic_x86_64/device.mk

$ sed -i '$a\\n$(call inherit-product-if-exists, vendor/google/emu-x86/target/libndk_translation.mk)' build/make/target/board/generic_x86_64/device.mk

执行编译:

# 禁用系统文件目录文件拷贝检查
$ export DISABLE_ARTIFACT_PATH_REQUIREMENTS="true"

$ lunch aosp_x86_64-eng

$ make

参考链接


发布者

《ubuntu 20.04编译Android 11源代码&模拟器》上有2条评论

  1. 请教下,emulator能否脱离sdk或者aosp独立运行呢?比如使用qemu运行,我编译了emulator源码,但按照帮助命令并不能启动模拟器:
    See -help-build-images for more details.

    If you're neither using the SDK or the Android build system, you
    can still run the emulator by explicitely providing the paths to
    *all* required disk images through a combination of the following
    options: -sysdir, -datadir, -kernel, -ramdisk, -system, -data, -cache
    -sdcard and -snapstorage.

    1. 这个报错说明模拟器是可以的,只是给模拟器的参数有问题,可以试着指定 -sysdir, -datadir, -kernel, -ramdisk, -system, -data, -cache
      -sdcard and -snapstorage 这些参数的位置试试

回复 默默 取消回复

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