Android 自定义系统编译

Android 自定义系统编译

一、编译环境要求

一台x86_64的机器,内存至少为12G(需开swap或zram),峰值内存占用会到30G,请确保有足够的空间以避免崩溃。

CPU越强越好,如果你愿意等的话,奔腾当然也可以。

磁盘空间至少200G,源码大概有80G,如果你不开ccache的话,剩下的空间应该够容纳编译产生的缓存了。

需要特别指出的是,由于编译过程中会产生大量的读写操作,所以对硬盘的IO性能有较高的要求,建议使用SSD来获得更好的体验。当然,HDD也不是不行,就是开始加载时需要等待很久,而且如果你是叠瓦盘,可能有损坏的风险。

系统要求,一个正常的LINUX发行版,谷歌官方使用的是UBUNTU,你也可以选择你自己喜欢的发行版,只要能保证能找到编译时所需的依赖即可。另外,如果你使用的是UBUNTU 22.04,需要注意该发行版有一个OOD的机制,会在高内存负载时干掉你的进程,记得关掉。

最后是需要有一个靠谱的代理,因为代码很多都存储在github上,如果网络不好,大概率会同步失败。

二、同步源码

我这里以crdroid为例,其它的项目过程大差不差:

首先到crdroid项目的github主页https://github.com/crdroidandroid

因为Android本身有着各种各样的组件,他们的源代码也分散在各个仓库中,在同步的时候,总不可能通过人工一个个同步,所以谷歌开发了一个叫repo的python工具,用来自动同步这些仓库里的内容,而android仓库里就是manifests(清单)文件,里面指定的就是各个仓库的远程路径和本地的检出目录。repo在工作时,会根据这些文件里的内容,同步所需要的仓库。

按照主页的文档,你需要先安装这些工具,它们在你同步源码和编译时会用得上。

sudo apt install bc bison build-essential ccache curl flex g++-multilib gcc-multilib git git-lfs gnupg gperf imagemagick lib32ncurses5-dev lib32readline-dev lib32z1-dev liblz4-tool libncurses5 libncurses5-dev libsdl1.2-dev libssl-dev libwxgtk3.0-gtk3-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc zip zlib1g-dev python-is-python3

然后我们需要创建一个目录用来存放同步的代码,以及将其作为编译的工作目录。

mkdir crd && cd crd

然后获取repo管理工具,虽然一些发行版已经在仓库里包含了repo,但是由于版本较旧,建议还是直接下载吧。

创建一个放repo的目录。

mkdir ~/bin

repo在国内有镜像,可以直接去北外或者tuna的源去下载。

curl https://mirrors.bfsu.edu.cn/git/git-repo -o ~/bin/repo

给执行权限并将其添加到你的path环境变量中。

chmod +x ~/bin/repo
PATH=~/bin:$PATH

因为repo在每次启动时,会检查是否有更新,所以把更新的源也添加进你的.bashrc里。

export REPO_URL='https://mirrors.bfsu.edu.cn/git/git-repo'
PATH=~/bin:$PATH

好了,现在准备完成,开始拉取清单文件。

根据你需要的android版本,选择对应的分支,比如crd现在最新的是14.0,

那你同步的命令就是这样:

repo init -u https://github.com/crdroidandroid/android.git -b 14.0 --git-lfs

我这里用13,那分支就应该是

repo init -u https://github.com/crdroidandroid/android.git -b 13.0 --git-lfs

-b后面指定的就是分支名

执行后,你可能会遇到如下提示:

~/crd$ repo init -u https://github.com/crdroidandroid/android.git -b 13.0 --git-lfs
Downloading Repo source from https://mirrors.bfsu.edu.cn/git/git-repo
remote: Enumerating objects: 4972, done.
remote: Counting objects: 100% (4972/4972), done.
remote: Compressing objects: 100% (2444/2444), done.
remote: Total 8646 (delta 4438), reused 2528 (delta 2528), pack-reused 3674
接收对象中: 100% (8646/8646), 4.00 MiB | 9.66 MiB/s, 完成.
处理 delta 中: 100% (5674/5674), 完成.
repo: Updating release signing keys to keyset ver 2.3

Traceback (most recent call last):
、
、
、
、
git_command.GitCommandError: GitCommandError: 'var GIT_COMMITTER_IDENT' on manifests failed
stderr: 提交者身份未知

*** 请告诉我您是谁。

运行

  git config --global user.email "you@example.com"
  git config --global user.name "Your Name"

来设置您账号的缺省身份标识。

那就按提示输入你的用户名和邮箱即可,内容随意

git config --global user.email "you@example.com"
git config --global user.name "Your Name"

然后重新执行

repo init -u https://github.com/crdroidandroid/android.git -b 13.0 --git-lfs

顺利的话,你会看到如下输出:

repo init -u https://github.com/crdroidandroid/android.git -b 13.0 --git-lfs
repo: reusing existing repo client checkout in /home/yourname/crd
warning: Changing --git-lfs settings will only affect new project checkouts.
         Existing projects will require manual updates.


Testing colorized output (for 'repo diff', 'repo status'):
  black    red      green    yellow   blue     magenta   cyan     white 
  bold     dim      ul       reverse 
Enable color display in this user account (y/N)? y

repo has been initialized in /home/yourname/crd

此时,相关的manifest就已经同步到本地了。

实际上,现在就可以使用repo sync命令来同步代码了,但是因为我们是在国内,如果全部选择使用aosp原始的地址来同步,那对代理的流量要求和压力就比较大。

国内有不少高校已经有了aosp的镜像,我们可以直接使用这些镜像,搭配代理工具的分流功能,就可以实现只加速github上的内容,而占大头的aosp本体则直接从国内获取,这样可以有效节省流量。

我们可以修改manifets文件来更改地址:

我们打开刚才创建的目录

可以看到有一个.repo的文件夹,这个目录默认是隐藏的,你可以通过文件管理器的设置来启用隐藏文件。

在manifests这个目录里,你会看到一个default.xml的文件,使用文本编辑器打开它。

注意看选中的那片区域

fetch="https://android.googlesource.com"

修改为

fetch="https://mirrors.bfsu.edu.cn/git/AOSP/"

然后,保存退出即可。

现在,你可以正式同步代码了。

回到你刚才的终端,输入下面的命令,然后就等待同步完成。

repo sync

当顺利同步完成后,你会看到这些内容:

正在更新文件: 100% (16294/16294), 完成.
正在更新文件: 100% (723/723), 完成.
Checking out: 94% (1155/1216) platform/prebuilts/checkcolor正在更新文件:  56% (5Checking out: 95% (1160/1216) crdroidandroid/android_prebuilts_clang_host_linux-Checking out: 95% (1161/1216) LineageOS/android_prebuilts_clang_kernel_linux-x86Checking out: 95% (1165/1216) LineageOS/android_prebuilts_gcc_linux-x86_aarch64_Checking out: 95% (1166/1216) LineageOS/android_prebuilts_gcc_linux-x86_arm_arm-Checking out: 95% (1167/1216) platform/prebuilts/gcc/linux-x86/host/x86_64-linuxChecking out: 96% (1168/1216) platform/prebuilts/gcc/linux-x86/host/x86_64-w64-mChecking out: 96% (1169/1216) LineageOS/android_prebuilts_gcc_linux-x86_x86_x86_Checking out: 97% (1184/1216) platform/prebuilts/module_sdk/AppSearch正在更新文正在更新文件: 100% (9260/9260), 完成.
正在更新文件: 100% (8370/8370), 完成.
正在更新文件: 100% (8703/8703), 完成.
正在更新文件: 100% (1904/1904), 完成.
正在更新文件: 100% (2101/2101), 完成.
正在更新文件: 100% (21272/21272), 完成.
正在更新文件: 100% (18265/18265), 完成.
正在更新文件: 100% (18387/18387), 完成.
Checking out: 97% (1190/1216) platform/prebuilts/module_sdk/OnDevicePersonalizatChecking out: 100% (1216/1216), done in 4m39.170s
repo sync has finished successfully.

三、同步需要设备所需要的设备树和内核等文件

可以开始编译了吗?并不,刚刚同步的只是系统的主代码,这些代码是各种设备能通用的部分,要使这些代码能够在你的机器上运行,我们还需要有设备独有的代码。这些一般是设备树、内核还有vendor blob.

设备树是你设备编译所需要的参数文件,里面指定了你的设备所需要的有关的配置

内核是你设备运作的核心,里面包含有许多驱动你设备运行的程序,比如wifi,触摸屏,蓝牙等各种硬件的驱动程序,厂商愿不愿意开放该设备的内核源码,就决定了这台设备能不能很好的移植这些第三方的系统。

vendor则是各种外围硬件的驱动,里面一般是一堆的so库,一般绝大多数的内容提取自于官方的rom.

了解了上述的概念,现在就可以去拿所需要的东西了。

1、设备树和内核的同步

对于有官方支持的机型

这种情况就很简单,因为官方的仓库有相关的文件,以crdroid为例。

在刚才的目录里输入

. build/envsetup.sh  #初始化编译环境
lunch lineage_devicecodename-buildtype #选择你要编译的设备和构建类型

其中devicecodename是你设备的代号,比如我的设备是MINI 5G,设备代号为TP803,那这里的代号就是TP1803

buildtype则是指构建的类型,可选的有user、userdebugeng三种类型。

user是面向用户的,各种量产的手机,默认的系统就是这种类型。它关闭了很多的调试权限,相对会更安全一些。

userdebug是带一定调试权限的用户类型,默认开启adb调试。

eng则是工程模式,一般只在适配时才用得上。

这里我们以userdebug为例,这也是多数第三方rom的构建类型。

因为Crdroid是直接基于lineage开发的,所以这里的代号就是lineage开头,我的设备代号是TP1803,构建类型为userdebug。因此最终的组合就为

lunch lineage_TP1803-userdebug

执行后,如果你的设备在官方维护名单里,它就会自动同步所需要的设备树和内核代码。

手动同步

就是把需要的东西手动放到指定的位置。如果你要构建的系统没在官方的支持范围内,那就需要你自己去找相关的内容。

设备树和内核可以在github上搜索(如果有的话)。

对于设备树,一般搜索的关键词为device_devicecodename,如device_TP1803 。本地工作目录为device/nubia/TP1803

对于内核,一般是kernel_brand_chipsetcode,如kernel_nubia_sm8150 。本地工作目录为kernel/nubia/sm8150

对于一些设备还需要自己去下载vendor ,本地工作目录为vendor/nubia/TP1803

你也可以创建一个local_manifests ,然后直接通过repo sync和系统的源代码一起同步。这是一个示例:

<?xml version="1.0" encoding="UTF-8"?>
<manifest>
	<remote name="lineage2"
		fetch="https://github.com/LineageOS"
		revision="lineage-21" />

	<!-- Device repos -->
	<project name="android_kernel_nubia_sm8150" path="kernel/nubia/sm8150" remote="lineage2" />
	<project name="android_device_nubia_TP1803" path="device/nubia/TP1803" remote="lineage2" />
	<project name="TheMuppets/proprietary_vendor_nubia_TP1803" path="vendor/nubia/TP1803" revision="lineage-21" />
</manifest>

2、提取blob

如果你已经下载了vendor ,那这一步就可以跳过了。

这个其实很简单:

在你的设备树里有一个proprietary-files.txt 文件,里面记录了rom所需要的库,这些库一般来自官方的系统,被称之为预编译blob。

在提取时,extract-files.sh ,会按照proprietary-files.txt 里的内容把系统里的库文件复制出来,并存放在源码中的指定位置。

由于adb复制系统内的这些文件需要有root权限,且adbd要工作在root模式下才可以,所以一般是没法直接从运行着官方系统的手机中直接复制的。

因此,要先下载官方的系统包,解压并挂载所需要的镜像到你的电脑上,然后直接指定目录让脚本从电脑上挂载的镜像里复制。

具体可以看lineage的官方wiki介绍。

https://wiki.lineageos.org/extracting_blobs_from_zips

干活时大概是这个样子

四、生成release-keys并应用

AOSP在构建时,会使用默认的test-key ,以满足应用签名的需要。但是,这个key是公开发布的,任何人都可以获取到,并对自己的应用进行签名,所以就有不小的安全隐患。

事实上,当你使用test-key编译时,最后的系统也会使很多应用提示风险环境,导致功能受限,或者根本就无法使用,因此,我们需要先修改签名为我们自己的。

1、生成签名

如上图所示,签名的存放目录为:build/target/product/security

打开README,可以看到里面有这些说明:

key generation
--------------

The following commands were used to generate the test key pairs:

  development/tools/make_key testkey       '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
  development/tools/make_key platform      '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
  development/tools/make_key shared        '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
  development/tools/make_key media         '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
  development/tools/make_key cts_uicc_2021 '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'

不过,lineageOS 提供了一个批量生成签名的方法:

直接在源码的根目录执行如下命令

subject='/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
mkdir ~/.android-certs
for cert in bluetooth cyngn-app media networkstack platform releasekey sdk_sandbox shared testcert testkey verity; do \
    ./development/tools/make_key ~/.android-certs/$cert "$subject"; \
done

可以把签名的信息换成你自己的,其实还是通过make_key来生成的,不过加了个for循环,能一次性解决。

生成的签名在home里:

然后替换掉之前的即可。

如果只是自己用的话,其实有一个releasekey基本就够了。如果您还想为其它模块签名,比如apex模块。那可以再生成一下。

for apex in com.android.adbd com.android.adservices com.android.adservices.api com.android.appsearch com.android.art com.android.bluetooth com.android.btservices com.android.cellbroadcast com.android.compos com.android.configinfrastructure com.android.connectivity.resources com.android.conscrypt com.android.devicelock com.android.extservices com.android.hardware.wifi com.android.healthfitness com.android.hotspot2.osulogin com.android.i18n com.android.ipsec com.android.media com.android.media.swcodec com.android.mediaprovider com.android.nearby.halfsheet com.android.networkstack.tethering com.android.neuralnetworks com.android.ondevicepersonalization com.android.os.statsd com.android.permission com.android.resolv com.android.rkpd com.android.runtime com.android.safetycenter.resources com.android.scheduling com.android.sdkext com.android.support.apexer com.android.telephony com.android.telephonymodules com.android.tethering com.android.tzdata com.android.uwb com.android.uwb.resources com.android.virt com.android.vndk.current com.android.wifi com.android.wifi.dialog com.android.wifi.resources com.google.pixel.vibrator.hal com.qorvo.uwb; do \
    subject='/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN='$apex'/emailAddress=android@android.com'; \
    ~/.android-certs/make_key ~/.android-certs/$apex "$subject"; \
    openssl pkcs8 -in ~/.android-certs/$apex.pk8 -inform DER -nocrypt -out ~/.android-certs/$apex.pem; \
done

详见lineage os 的这一篇wiki

https://wiki.lineageos.org/signing_builds

2、修改编译参数,使用realeasekey

lineage默认的思路是先编译,然后再使用我们的签名来签名生成的文件,从可维护的角度来说,这么做可以避免对源码的修改,这样方便后续的更新合并,但是咱既然自己编译了,那就是有修改的必要,不差这一个。

修改build/core/sysprop.mk ,找到如下内容。

ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/make/target/product/security/testkey)
BUILD_KEYS := test-keys
else
BUILD_KEYS := dev-keys

修改为:

ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/make/target/product/security/testkey)
BUILD_KEYS := test-keys
else
BUILD_KEYS := release-keys

这里是修改系统显示的内容,避免一些软件检查这个。

然后你要指定编译时的签名,这个在

build/core/config.mk

ifdef PRODUCT_DEFAULT_DEV_CERTIFICATE
  DEFAULT_SYSTEM_DEV_CERTIFICATE := $(PRODUCT_DEFAULT_DEV_CERTIFICATE)
else
  DEFAULT_SYSTEM_DEV_CERTIFICATE := build/make/target/product/security/testkey
endif
.KATI_READONLY := DEFAULT_SYSTEM_DEV_CERTIFICATE

修改为:

ifdef PRODUCT_DEFAULT_DEV_CERTIFICATE
  DEFAULT_SYSTEM_DEV_CERTIFICATE := $(PRODUCT_DEFAULT_DEV_CERTIFICATE)
else
  DEFAULT_SYSTEM_DEV_CERTIFICATE := build/make/target/product/security/releasekey
endif
.KATI_READONLY := DEFAULT_SYSTEM_DEV_CERTIFICATE

签名修改就到这里完成了。

五、为内核添加kernel su支持(可选)

kernel su是一个运行在内核空间的root工具,支持gki2.0的设备直接刷入,官方最低支持4.14的kernel

我的内核低于5.10,是没有原生gki支持的,所以要自己编译。我对root没有刚需,只是我这台机器升级到lineage 21 后,上游开发者为其整出了动态分区支持,这对修改系统分区的操作会非常不友好,比如刷入gapps,还有华为应用商店静默安装的功能,只能通过hook的方式来实现。

这个也很简单,在你的内核源码根目录执行如下命令:

curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -

脚本会自动帮你添加。

然后在你的kernel config里添加

CONFIG_KPROBES=y
CONFIG_HAVE_KPROBES=y
CONFIG_KPROBE_EVENTS=y

保存即可。

六、添加GAPPS(可选)

这个主要是针对有动态分区、又需要gapp的用户,因为动态分区塞不进去了,所以需要编译时加入。

这里用的是https://gitlab.com/MindTheGapps/vendor_gapps

里面有说明,就不再赘述了。

七、添加华为应用商店(可选)

为啥选他呢?因为它配置好权限文件后,可以在无root的情况下,实现系统级的静默安装,而且华为的软件分发历史悠久,软件全,且可以换区,还有安装记录漫游,非常方便。

1、添加模块

packages/apps/里创建一个和apk同名的文件夹,比如我这个叫Market

反正都需要HMS的,都一样啦

然后把你的HMS.apk 放进来,并创建一个Android.mk 文件,里面内容如下:

include $(CLEAR_VARS)
LOCAL_MODULE := HMS
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_TAGS := optional
LOCAL_PRODUCT_MODULE := true
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := .apk
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_PRIVILEGED_MODULE := true
LOCAL_REPLACE_PREBUILT_APK_INSTALLED := $(LOCAL_PATH)/$(LOCAL_MODULE).apk
include $(BUILD_PREBUILT)

我想把它放到/product分区里,那里面就多了一句LOCAL_PRODUCT_MODULE := true 的声明。

Market也是一样的。

声明有了,现在该让编译系统把模块添加进去了。

编辑

build/target/product/handheld_product.mk

到这里,就可以编译了。不过,这里的应用没有声明好权限,即便能开机,也无法正常使用,所以需要配置一下。

2、配置特权应用

development/tools/privapp_permissions/privapp_permissions.py

这个脚本需要在编译完成后才能正常生成所需权限,因此先暂且不表。

我最后的权限如下:

<?xml version="1.0" encoding="utf-8"?>
<!-- for the partition: /product -->
<permissions>
    <privapp-permissions package="com.huawei.appmarket">
        <permission name="android.permission.ALLOCATE_AGGRESSIVE"/>
        <permission name="android.permission.DELETE_PACKAGES"/>
        <permission name="android.permission.INSTALL_PACKAGES"/>
        <permission name="android.permission.INTERACT_ACROSS_USERS"/>
        <permission name="android.permission.MANAGE_USERS"/>
        <permission name="android.permission.PACKAGE_USAGE_STATS"/>
        <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
        <permission name="android.permission.READ_RUNTIME_PROFILES"/>
        <permission name="android.permission.REAL_GET_TASKS"/>
        <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
        <permission name="android.permission.STOP_APP_SWITCHES"/>
        <permission name="android.permission.WRITE_APN_SETTINGS"/>
        <permission name="android.permission.WRITE_MEDIA_STORAGE"/>
        <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
    </privapp-permissions>

    <privapp-permissions package="com.huawei.hwid">
        <permission name="android.permission.BLUETOOTH_PRIVILEGED"/>
        <permission name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS"/>
        <permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
        <permission name="android.permission.DISPATCH_PROVISIONING_MESSAGE"/>
        <permission name="android.permission.FORCE_STOP_PACKAGES"/>
        <permission name="android.permission.INSTALL_PACKAGES"/>
        <permission name="android.permission.INTERACT_ACROSS_USERS"/>
        <permission name="android.permission.LOCAL_MAC_ADDRESS"/>
        <permission name="android.permission.MANAGE_FINGERPRINT"/>
        <permission name="android.permission.MANAGE_USERS"/>
        <permission name="android.permission.MASTER_CLEAR"/>
        <permission name="android.permission.MODIFY_PHONE_STATE"/>
        <permission name="android.permission.PACKAGE_USAGE_STATS"/>
        <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
        <permission name="android.permission.READ_SEARCH_INDEXABLES"/>
        <permission name="android.permission.READ_WIFI_CREDENTIAL"/>
        <permission name="android.permission.REAL_GET_TASKS"/>
        <permission name="android.permission.SCHEDULE_EXACT_ALARM"/>
        <permission name="android.permission.STATUS_BAR"/>
        <permission name="android.permission.STOP_APP_SWITCHES"/>
        <permission name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"/>
        <permission name="android.permission.UPDATE_APP_OPS_STATS"/>
        <permission name="android.permission.UPDATE_DEVICE_STATS"/>
        <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
    </privapp-permissions>

</permissions>

也许后面会变更 ,不过应该能管一段时间了。

把上述的文件保存为xml文件,比如hwid.xml,然后让系统复制到/product/etc/permissions

m bacon一下重打包就好了

八、编译

source build/envsetup.sh

初始化编译环境后

输入lunch 可以看到如下内容:

You're building on Linux

Lunch menu .. Here are the common combinations:
     1. aosp_arm-eng
     2. aosp_arm64-eng
     3. aosp_car_arm-userdebug
     4. aosp_car_arm64-userdebug
     5. aosp_car_x86-userdebug
     6. aosp_car_x86_64-userdebug
     7. aosp_cf_arm64_auto-userdebug
     8. aosp_cf_arm64_phone-userdebug
     9. aosp_cf_x86_64_auto-userdebug
     10. aosp_cf_x86_64_auto_mdnd-userdebug
     11. aosp_cf_x86_64_foldable-userdebug
     12. aosp_cf_x86_64_only_phone_hsum-userdebug
     13. aosp_cf_x86_64_pc-userdebug
     14. aosp_cf_x86_64_phone-userdebug
     15. aosp_cf_x86_64_tv-userdebug
     16. aosp_cf_x86_phone-userdebug
     17. aosp_cf_x86_tv-userdebug
     18. aosp_x86-eng
     19. aosp_x86_64-eng
     20. arm_krait-eng
     21. arm_v7_v8-eng
     22. armv8-eng
     23. armv8_cortex_a55-eng
     24. armv8_kryo385-eng
     25. car_ui_portrait-userdebug
     26. car_x86_64-userdebug
     27. gsi_car_arm64-userdebug
     28. gsi_car_x86_64-userdebug
     29. lineage_TP1803-eng
     30. lineage_TP1803-user
     31. lineage_TP1803-userdebug
     32. lineage_gsi_arm-userdebug
     33. lineage_gsi_arm64-userdebug
     34. lineage_gsi_car_arm64-userdebug
     35. lineage_gsi_car_x86_64-userdebug
     36. lineage_gsi_tv_arm-userdebug
     37. lineage_gsi_tv_arm64-userdebug
     38. lineage_gsi_tv_x86-userdebug
     39. lineage_gsi_tv_x86_64-userdebug
     40. lineage_gsi_x86-userdebug
     41. lineage_gsi_x86_64-userdebug
     42. lineage_sdk_car_arm64-userdebug
     43. lineage_sdk_car_x86_64-userdebug
     44. lineage_sdk_phone_arm64-userdebug
     45. lineage_sdk_phone_x86-userdebug
     46. lineage_sdk_phone_x86_64-userdebug
     47. lineage_sdk_tv_arm-userdebug
     48. lineage_sdk_tv_x86-userdebug
     49. qemu_trusty_arm64-userdebug
     50. sdk_car_arm-userdebug
     51. sdk_car_arm64-userdebug
     52. sdk_car_md_x86_64-userdebug
     53. sdk_car_portrait_x86_64-userdebug
     54. sdk_car_x86-userdebug
     55. sdk_car_x86_64-userdebug
     56. sdk_pc_x86_64-userdebug
     57. silvermont-eng
     58. uml-userdebug

Which would you like? [aosp_arm-eng]
Pick from common choices above (e.g. 13) or specify your own (e.g. aosp_barbet-eng): 

输入序号,我这里是31,用userdebug

没有错误的话,会显示这些内容:

Which would you like? [aosp_arm-eng]
Pick from common choices above (e.g. 13) or specify your own (e.g. aosp_barbet-eng): 31
Looking for dependencies in device/nubia/TP1803
Looking for dependencies in kernel/nubia/sm8150
kernel/nubia/sm8150 has no additional dependencies.

Hint: next time you can simply run 'lunch lineage_TP1803-userdebug'

============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=14
LINEAGE_VERSION=21.0-20240220-UNOFFICIAL-TP1803
PRODUCT_INCLUDE_TAGS=com.android.mainline
TARGET_PRODUCT=lineage_TP1803
TARGET_BUILD_VARIANT=userdebug
TARGET_ARCH=arm64
TARGET_ARCH_VARIANT=armv8-a
TARGET_CPU_VARIANT=generic
TARGET_2ND_ARCH=arm
TARGET_2ND_ARCH_VARIANT=armv7-a-neon
TARGET_2ND_CPU_VARIANT=cortex-a9
HOST_OS=linux
HOST_OS_EXTRA=Linux-6.1.0-18-amd64-x86_64-Debian-GNU/Linux-12-(bookworm)
HOST_CROSS_OS=windows
BUILD_ID=UQ1A.240205.004
OUT_DIR=out
PRODUCT_SOONG_NAMESPACES=device/nubia/TP1803 hardware/google/interfaces hardware/google/pixel vendor/nxp/nfc vendor/nubia/TP1803 vendor/gapps/arm64 vendor/gapps/common vendor/gapps/overlay hardware/qcom-caf/sm8150 vendor/qcom/opensource/commonsys/display vendor/qcom/opensource/commonsys-intf/display vendor/qcom/opensource/display vendor/qcom/opensource/data-ipa-cfg-mgr-legacy-um vendor/qcom/opensource/dataservices hardware/qcom-caf/wlan
============================================

最后,m bacon 开始编译。

成功后会输出如下内容:

Licensed under CC BY-NC-SA 4.0