如何在Ubuntu 16.04上构建Android ROM

Android是当今世界上最流行的操作系统。数百个不同的原始设备制造商或OEM选择将其安装在他们的设备上,因为它是免费的,开放源代码的,并且拥有大量的应用程序和服务生态系统。

介绍

Android是当今世界上最流行的操作系统。 数百个不同的原始设备制造商或OEM选择将其安装在他们的设备上,因为它是免费的,开放源代码的,并且具有围绕其构建的大量应用程序和服务的生态系统。 不幸的是,许多原始设备制造商不会定期推送Android的空中(OTA)更新。 而其他OEM只能在设备启动后的一段时间内提供更新。 此外,原始设备制造商倾向于广泛定制Android,以确保其设备具有独特的外观和风格。 他们的定制包括可选的发射器,主题系统用户界面和预安装的应用程序。

如果您想删除所有这些自定义设置,或者想要在设备上运行最新版本的纯Android,则可以自行为其构建新的固件。 在Android modding社区中,这样的固件通常被称为只读存储器的简称ROM。

在本教程中,您将构建一个基于Android开放源代码项目 (简称AOSP)的Android Oreo ROM。 为了保持这个教程独立于设备和通用,我们将只针对AOSP仿真器,但是您可以将相同的技术应用于实际设备。

先决条件

为了能够跟随,你需要:

第1步 - 开始一个屏幕会话

您将在本教程中执行的一些命令可能会运行几个小时。 如果您的PC与您的服务器之间的SSH连接在命令运行时被中断,则它们将突然终止。 为了避免出现这种情况,请使用screen实用程序,它允许您在单个终端中运行多个控制台会话。 使用屏幕,您可以从正在运行的会话中进行分解并稍后重新附加。 如果您是“屏幕”的新手,请在本教程中了解有关在Ubuntu上使用屏幕的更多信息

开始一个新的screen会话。

screen

当您第一次运行屏幕时,您将获得许可协议。 Enter接受许可证。

从这一点来看,如果你的SSH连接失败,你的长时间运行的命令将继续在后台运行。 一旦重新建立SSH连接,您将能够通过运行screen -r恢复会话。

接下来,让我们安装我们需要编译Android的组件。

第2步 - 安装依赖关系

AOSP源代码分布在几个不同的Git仓库中。 为了方便用户下载所有的存储库,AOSP社区创建了一个名为repo的命令行工具。

我们将使用wget下载最新版本的工具,并将其存储在~/bin目录中。 首先,创建~/bin目录:

mkdir -p ~/bin

然后下载repo脚本:

wget 'https://storage.googleapis.com/git-repo-downloads/repo' -P ~/bin

注意 :如果您担心从其他站点下载的计算机上运行脚本的安全性,请检查脚本的内容:

less ~/bin/repo

一旦您对脚本的内容感到满意,请继续阅读本教程。

使用chmod来授予您当前用户运行repo的权限。

chmod +x ~/bin/repo

repo工具在内部使用Git,并要求您创建一个指定您的用户名和电子邮件地址的Git配置。 执行这些命令来做到这一点:

git config --global user.name "your name"
git config --global user.email "your_email@your_domain.com"

Android的源代码主要由Java,C ++和XML文件组成。 要编译源代码,您需要安装OpenJDK 8,GNU C和C ++编译器,XML解析库,ImageMagick和其他几个相关的软件包。 幸运的是,你可以使用apt来安装它们。 在此之前,请确保更新服务器的软件包列表。

sudo apt-get update

一旦列表更新,安装依赖关系:

sudo apt-get install openjdk-8-jdk android-tools-adb bc bison build-essential curl flex g++-multilib gcc-multilib gnupg gperf imagemagick lib32ncurses5-dev lib32readline-dev lib32z1-dev libesd0-dev liblz4-tool libncurses5-dev libsdl1.2-dev libssl-dev libwxgtk3.0-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc yasm zip zlib1g-dev

一旦依赖关系下载,我们可以使用repo脚本来获取Android源代码。

第3步 - 下载源代码

我们将使用repo脚本来完成一些任务来准备我们的工作空间。 创建一个新的目录来存储您要下载的Android源代码:

mkdir -p ~/aosp/oreo

在本教程的其余部分中,您将在这个目录中工作,现在切换到它:

cd ~/aosp/oreo

该目录必须使用AOSP 清单存储库进行初始化,该存储库是一个特殊的Git存储库,其中包含名为default.xml的XML文件,该文件指定了所有其他Git存储库的路径,这些存储库一起构成AOSP代码库。

使用整个AOSP代码树可能会非常麻烦。 因此,您必须另外指定您感兴趣的特定版本或分支的名称。在本教程中,因为我们正在构建一个Oreo ROM,所以我们将使用android-8.0.0_r33分支,其构建ID为OPD1.170816.025 您可以从AOSP的官方代号,标签和内部编号页面获取所有可用的构建ID和分支名称的列表。

此外,本教程不需要代码树的完整提交历史记录。 您可以通过截取历史记录深度为1来节省时间和存储空间。

因此,使用repo init命令来初始化目录并指定这些选项:

repo init -u https://android.googlesource.com/platform/manifest -b android-8.0.0_r33 --depth=1

当提示启用彩色显示时,按Y ,然后按Enter

最后,通过运行repo sync命令从各个存储库下载实际的AOSP文件:

repo sync

以上命令下载了超过30 GB的数据,所以在完成时要耐心等待。 一旦完成,我们将设置一个缓存来加速编译。

第4步 - 准备编译器缓存

要加快构建,可以使用编译器缓存。 顾名思义,编译器缓存可以帮助您避免重新编译已编译的ROM部分。

要启用编译器缓存,请设置一个名为USE_CCACHE的环境变量。

export USE_CCACHE=1

除非有足够的可用磁盘空间,否则不会让缓存变得太大,所以可以限制其大小。 如果您正在为单个设备构建ROM,则可以将其限制为15 GB。 为此,请使用ccache命令。

prebuilts/misc/linux-x86/ccache/ccache -M 15G

您将看到确认您进行了此更改的输出:

Set cache size limit to 15.0 Gbytes

在我们编译之前,还需要做一个更多的优化。 我们接下来做。

第5步 - 配置插孔

Jack服务器负责构建大部分ROM的基于Java的部分,需要大量的内存。 为避免内存分配错误,您可以使用名为ANDROID_JACK_VM_ARGS的环境变量来指定允许使用多少内存插口。 通常,分配大约50%的服务器RAM就足够了。 这个环境变量也指定了其他的编译设置。

执行以下命令将8 GB的RAM分配给Jack服务器并保留Jack所需的默认编译选项:

export ANDROID_JACK_VM_ARGS="-Xmx8g -Dfile.encoding=UTF-8 -XX:+TieredCompilation"

现在你已经准备好建立你的Android ROM。

第6步 - 开始构建

AOSP代码树包含一个名为envsetup.sh的脚本,它具有多个与构建相关的帮助函数。 虽然许多辅助函数(例如mmmmammm )作为make命令的快捷方式,但其他方面(例如lunch设置了重要的环境变量,其中包括决定ROM的CPU体系结构,以及构建。

来源脚本访问辅助功能。

source build/envsetup.sh
including device/asus/fugu/vendorsetup.sh
including device/generic/car/car-arm64/vendorsetup.sh
including device/generic/car/car-armv7-a-neon/vendorsetup.sh
including device/generic/car/car-x86_64/vendorsetup.sh
including device/generic/car/car-x86/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-mips64/vendorsetup.sh
including device/generic/mini-emulator-mips/vendorsetup.sh
including device/generic/mini-emulator-x86_64/vendorsetup.sh
including device/generic/mini-emulator-x86/vendorsetup.sh
including device/google/dragon/vendorsetup.sh
including device/google/marlin/vendorsetup.sh
including device/google/muskie/vendorsetup.sh
including device/google/taimen/vendorsetup.sh
including device/huawei/angler/vendorsetup.sh
including device/lge/bullhead/vendorsetup.sh
including device/linaro/hikey/vendorsetup.sh
including sdk/bash_completion/adb.bash

接下来,运行lunch并将设备的代号传递给它,Postfix为构建类型,可以是enguserdebuguser 虽然enguserdebug构建类型导致最适合测试目的的ROM,但建议将user构建类型用于生产用途。

要构建可以在AOSP ARM仿真器上运行的测试ROM, aosp_arm-eng传递给lunch命令:

lunch aosp_arm-eng

你会看到这个输出,显示环境设置:

============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=8.0.0
TARGET_PRODUCT=aosp_arm
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_PLATFORM_VERSION=OPD1
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a
TARGET_CPU_VARIANT=generic
TARGET_2ND_ARCH=
TARGET_2ND_ARCH_VARIANT=
TARGET_2ND_CPU_VARIANT=
HOST_ARCH=x86_64
HOST_2ND_ARCH=x86
HOST_OS=linux
HOST_OS_EXTRA=Linux-4.4.0-104-generic-x86_64-with-Ubuntu-16.04-xenial
HOST_CROSS_OS=windows
HOST_CROSS_ARCH=x86
HOST_CROSS_2ND_ARCH=x86_64
HOST_BUILD_TYPE=release
BUILD_ID=OPD1.170816.025
OUT_DIR=out
AUX_OS_VARIANT_LIST=
============================================

最后,运行make开始构建。 make支持并行作业,因此可以使用-j选项将并行作业的数量设置为等于服务器中可用的CPU数量,从而大大加快构建的速度。

使用nproc命令查看您有多少个CPU:

nproc

该命令返回CPUS的数量:

8

然后你可以用这个数字来指定并行执行:

make -j8

即使有8个CPU,只要在服务器上没有其他CPU密集型进程处于活动状态,就必须等待一个多小时才能完成构建。 构建的持续时间与RAM的数量和CPU的数量成正比。 如果您想要更快的构建,请考虑使用专门的高CPUDroplet ,它最多支持32个CPU和48 GB内存。

注意:您将在构建过程中看到许多警告消息。 你可以放心地忽略它们。

一旦ROM准备就绪,您应该看到一条消息,说明构建已成功完成。 您也将能够看到构建的确切持续时间。

...
Creating filesystem with parameters:
    Size: 2147483648
    Block size: 4096
    Blocks per group: 32768
    Inodes per group: 8192
    Inode size: 256
    Journal blocks: 8192
    Label: system
    Blocks: 524288
    Block groups: 16
    Reserved block group size: 127
Created filesystem with 2266/131072 inodes and 178244/524288 blocks
[100% 63193/63193] Install system fs i... out/target/product/generic/system.img
out/target/product/generic/system.img+ maxsize=2192446080 blocksize=2112 total=2147483648 reserve=22146432

#### make completed successfully (01:05:44 (hh:mm:ss)) ####

让我们来验证正确的东西。

第7步 - 验证构建

构建过程的输出由多个文件系统映像组成,这些映像一起构成ROM。 你会在out/target/product/generic/目录下找到它们。

ls -l out/target/product/generic/*.img
-rw-r--r-- 1 sammy sammy   69206016 Jan  5 18:51 out/target/product/generic/cache.img
-rw-rw-r-- 1 sammy sammy    1699731 Jan  5 19:09 out/target/product/generic/ramdisk.img
-rw-r--r-- 1 sammy sammy 2147483648 Jan  5 19:10 out/target/product/generic/system.img
-rw-r--r-- 1 sammy sammy  576716800 Jan  5 19:09 out/target/product/generic/userdata.img

要测试ROM,您可以尝试通过运行emulator命令来启动一个仿真emulator 如果您处于非GUI环境中,请确保将-no-window-noaudio标志传递给它。

emulator -no-window -noaudio > /dev/null 2>&1 &

要检查仿真器是否能够成功启动,请等待一会儿,然后使用Android调试桥工具adb在仿真器上打开一个shell。

adb shell

如果ROM没有问题,您将看到模拟器上运行的shell提示。

* daemon not running; starting now at tcp:5037
* daemon started successfully
generic:/ #

输入exit并按ENTER ,或者按CTRL+D退出该shell。

注意:如果您尝试在模拟器启动之前打开shell,您将看到一条错误消息,通知您模拟器处于脱机状态。 等一会儿再试一次。

故障排除

如果构建失败,最可能的原因是内存不足。 要修复它,首先运行以下命令来终止Jack服务器:

jack-admin kill-server

然后再次开始构建,但允许使用更少的并行作业。 例如,下面是如何将并行作业的数量减少到2:

make -j2

如果您的构建由于磁盘空间不足而失败,那么您可能会尝试构建多次而不清除以前的构建的结果。 要放弃以前的版本的结果,可以运行以下命令:

make clobber

或者,您可以使用DigitalOcean的块存储将更多的磁盘空间添加到您的Droplet。

结论

在本教程中,您成功地为Android Oreo构建了基于AOSP的ROM。 您今天学到的技术也适用于AOSP的所有分支,例如Lineage OSResurrection Remix OS 如果您有开发Android应用程序的经验,您可能有兴趣修改AOSP代码库的一小部分,以使您的ROM具有个人风格。

要了解有关构建AOSP源代码的更多信息,请浏览Google网上论坛上的Android Building论坛


分享按钮