为Pixel 4编译LineageOS 20(Android 13)

准备工作

修改仓库配置后更新和升级
apt update
apt full-upgrade
  • 安装LineageOS编译依赖:

在容器中安装Ubuntu编译LineageOS需要的依赖软件包
apt install bc bison build-essential ccache curl flex g++-multilib gcc-multilib git gnupg gperf \
    imagemagick lib32ncurses5-dev lib32readline-dev lib32z1-dev liblz4-tool libncurses5 libncurses5-dev \
    libsdl1.2-dev libssl-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools \
    xsltproc zip zlib1g-dev python-is-python3
  • 添加一个普通用户账号,注意这里关闭了密码:

添加一个 admin 账号并切换到这个账号
adduser --disabled-password admin
chown -R admin:admin /home/admin

# 切换到admin账号
su - admin
  • 设置缓存 50G 并且在 admin 账号配置中启动 ccache :

启用 ccache
# 在admin账号身份下执行
ccache -M 50G
echo 'export USE_CCACHE=1' >> ~/.profile

备注

编译LineageOS需要惊人的磁盘空间,按照官方文档参考,linage-18.1就需要300GB空间,更高版本要求的空间更多…

我的实践(LineageOS 20.0/Android 13):

  • repo sync 仓库同步占用 146G

  • breakfast flame 后仓库占用 150G ( tar cfz 压缩以后大小 97G )

安装仓库

  • 创建目录并下载安装仓库:

创建repo
mkdir -p ~/bin
mkdir -p ~/android/lineage

curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
  • 配置 ~/bin 到执行目录(添加到 ~/.profile )

将repo的 ~/bin 路径添加到 ~/.profile
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
    PATH="$HOME/bin:$PATH"
fi
  • 配置 git :

配置git
# 这里git配置请按照自己的github账号配置,以便能够从GitHub同步代码仓库
git config --global user.email user@localhost
git config --global user.name user
在Ubuntu上安装git-lfs
apt install git-lfs
  • 在用户目录下执行 git-lfs 初始化:

每个使用 Git Large File Storage 的用户账号下需要执行 git lfs 初始化
git lfs install
  • 初始化android仓库以及获取源代码:

初始化android仓库以及获取源代码
# 创建源代码目录
mkdir -p ~/android/lineage/
cd ~/android/lineage/

# 初始化仓库(这里需要根据设备对应的代码分支): 一定要使用 --git-lfs 参数
repo init -u https://github.com/LineageOS/android.git -b lineage-20.0 --git-lfs

# 代码同步
repo sync

备注

访问GitHub仓库可能受到GFW干扰,所以需要采用:

不过,我实践还是遇到一个困难 git配置代理 使用HTTP/HTTPS代理时需要使用 使用OpenSSL的git 来解决 Squid父级socks代理 出现的TLS连接报错:

git HTTPS代理访问 googlesource 报错 TLS连接中断
platform/external/ppp:
fatal: unable to access 'https://android.googlesource.com/platform/external/ppp/': gnutls_handshake() failed: The TLS connection was non-properly terminated.
platform/external/ppp: sleeping 4.0 seconds before retrying
fatal: unable to access 'https://android.googlesource.com/platform/external/ppp/': GnuTLS recv error (-110): The TLS connection was non-properly terminated.
error: Cannot fetch platform/external/rust/crates/ash from https://android.googlesource.com/platform/external/rust/crates/ash
error: Cannot fetch platform/external/ppp from https://android.googlesource.com/platform/external/ppp

采用 使用OpenSSL的git 解决

此外,使用 OpenSSL 的 curl 也需要重新编译最新版本 编译OpenSSL支持的curl ,以便解决OpenSSL 3.0.x 的 unexpected EOF 报错

警告

我最后放弃了通过代理翻墙方式来同步仓库 原因是 实在难以找到合适的能够在墙内畅通访问的VPS (真是非常非常恶劣的网络环境)

实际采用的方式是直接在墙外租用一个小型VPS进行源代码同步,然后通过 rsync 同步到墙内高性能服务器上进行编译(或许可以部署一个持续集成环境?)

备注

repo sync 同步命令默认参数是 -j 4 -c 表示:

  • -j 4 表示并发4个同步线程(连接)

  • -c 表示 repo 值同步当前分支而不是GitHub上该仓库的所有分支

LineageOS 建议使用默认配置,不过我发现由于翻墙网络非常缓慢,适当增加同步并发可以加快同步。例如 repo sync -j 12 (按照服务器的cpu core数量调整)

  • 准备设备特定代码:

备注

这里针对 Pixel 4 设备编译源代码,对应的code名字是 flame

同步设备特定代码
source build/envsetup.sh
# 这里同步pixel4对应的设备代码 flame
# 注意,如果 从LineageOS安装zip文件中提取专有blobs (解决第一次breakfast flame失败)之后,还是需要再执行一次 breakfast flame
breakfast flame

上述步骤会下载设备特定的配置文件以及内核

提取专有blobs

如果你已经在设备中安装了LineageOS,就可以从设备中提取blobs。这个工作由 Android platform tools ( Android Debug Bridge (adb) )完成,执行以下命令:

获取设备特定的专有blobs
~/android/lineage/device/google/flame/extract-files.sh

此时会在 ~/android/lineage/vendor/google 找到提取出来的 blobs

我实际采用的方法 是: 从LineageOS安装zip文件中提取专有blobs ,完成后在 ~/android/lineage/vendor/google 就存放了 blobs 文件

警告

我这里也遇到了官方文档所说的 “部分设备需要一个vender(供应商)目录,然后才能 breakfast 成功。也就是说遇到类似如下的 makefile 错误,则需要从 最新的LineageOS设备 中提取响应的第一份专有blobs,然后才能完成 breakfast “ :

执行 breakfast flame 错误信息
...
In file included from build/make/core/config.mk:353:
In file included from build/make/core/envsetup.mk:352:
In file included from build/make/core/product_config.mk:237:
device/google/coral/lineage_flame.mk:31: error:  vendor/google/flame/flame-vendor.mk does not exist..
06:41:57 dumpvars failed with: exit status 1
In file included from build/make/core/config.mk:353:
In file included from build/make/core/envsetup.mk:352:
In file included from build/make/core/product_config.mk:237:
device/google/coral/lineage_flame.mk:31: error:  vendor/google/flame/flame-vendor.mk does not exist..
06:41:58 dumpvars failed with: exit status 1

** Don't have a product spec for: 'lineage_flame'
** Do you have the right repo manifest?

这里有一个悖论,我没有这样已经安装过LineageOS的设备,如果有的话,则连接手机设备执行:

获取设备特定的专有blobs
~/android/lineage/device/google/flame/extract-files.sh

实际上我是从官方网站下载这个对应 blobs ,也就是 Install LineageOS on Google Pixel 4 官方下载 LineageOS installation package

采用 从LineageOS安装zip文件中提取专有blobs 提取 blobs

然后再次执行 :

同步设备特定代码
source build/envsetup.sh
# 这里同步pixel4对应的设备代码 flame
# 注意,如果 从LineageOS安装zip文件中提取专有blobs (解决第一次breakfast flame失败)之后,还是需要再执行一次 breakfast flame
breakfast flame

编译

  • 终于到了最后一步:

编译
croot
brunch flame
  • 完成编译后,在 $OUTPUT 目录下(执行 cd $OUTPUT 到达该目录)会有如下编译后生成文件:

编译生成的文件
# LineageOS recovery镜像
boot.img

# 分区镜像,在刷入LineageOS之前需要为手机增加一个recovery分区
dtbo.img

# LineageOS 安装包
lineage-20.0-20231102-UNOFFICIAL-flame.zip

HPE ProLiant DL360 Gen9服务器 服务器上编译完成时间大约是 1小时50分:

[100% 164133/164133] build bacon
Package Complete: out/target/product/flame/lineage-20.0-20231103-UNOFFICIAL-flame.zip

#### build completed successfully (01:49:31 (hh:mm:ss)) ####

可以开始 Pixel 4上安装LineageOS 20

编译问题排查

depmod 报错

  • 首先遇到的是 depmod 报错:

编译过程出现无法找到 modules 的 depmod 报错
  DEPMOD  4.14.326-gee1db14248b6
make[1]: Leaving directory '/home/admin/android/lineage/out/target/product/flame/obj/KERNEL_OBJ'
make: Leaving directory '/home/admin/android/lineage/kernel/google/msm-4.14'
depmod: WARNING: could not open modules.order at /home/admin/android/lineage/out/target/product/flame/obj/PACKAGING/depmod_vendor_intermediates/lib/modules/0.0: No such file or directory
depmod: WARNING: could not open modules.builtin at /home/admin/android/lineage/out/target/product/flame/obj/PACKAGING/depmod_vendor_intermediates/lib/modules/0.0: No such file or directory
00:51:28 ninja failed with: exit status 1

#### failed to build some targets (01:07:27 (hh:mm:ss)) ###

这个问题的解决方法我没有google到,不过我发现是我忽略了 Build LineageOS for Google Pixel 4 的一句话导致的:

If you receive an error here about vendor makefiles, jump down to Extract proprietary blobs. The first portion of breakfast should have succeeded, and after completing you can rerun breakfast

也就是我在首次执行 brekafast flame 来获取设备特定代码时失败(因为没有blobs),所以我转为采用 从LineageOS安装zip文件中提取专有blobs 完成 blobs 提取。这个步骤完成后,我只执行了 source build/envsetup.sh 但是没有重新执行 breakfast flame 就会出现上述报错。

webview.apk: Invalid file 报错

再次编译遇到错误:

webview.apk: Invalid file
...
[ 11% 7599/63502] Verifying uses-libraries: external/chromium-webview/prebuilt/arm64/webview.apk
FAILED: out/target/common/obj/APPS/webview_intermediates/enforce_uses_libraries.status
/bin/bash -c "(rm -f out/target/common/obj/APPS/webview_intermediates/enforce_uses_libraries.status ) && (build/soong/scripts/manifest_check.py           --enforce-uses-libraries      --enforce-uses-libraries-status out/target/common/obj/APPS/webview_intermediates/enforce_uses_libraries.status          --aapt out/host/linux-x86/bin/aapt                             --enforce-uses-libraries-relax         external/chromium-webview/prebuilt/arm64/webview.apk )"
zipro W 11-03 11:39:22 13171 13171] Error opening archive external/chromium-webview/prebuilt/arm64/webview.apk: Invalid file
ERROR: dump failed because no AndroidManifest.xml found
error: Command '['out/host/linux-x86/bin/aapt', 'dump', 'badging', 'external/chromium-webview/prebuilt/arm64/webview.apk']' returned non-zero exit status 1
[ 12% 7637/63502] Building Kernel Config
make: Entering directory '/home/admin/android/lineage/kernel/google/msm-4.14'
make[1]: Entering directory '/home/admin/android/lineage/out/target/product/flame/obj/KERNEL_OBJ'
  GEN     ./Makefile
...
  DTBOIMG arch/arm64/boot/dtbo.img
create image file: arch/arm64/boot/dtbo.img...
Total 12 entries.
make[1]: Leaving directory '/home/admin/android/lineage/out/target/product/flame/obj/DTBO_OBJ'
make: Leaving directory '/home/admin/android/lineage/kernel/google/msm-4.14'
11:40:32 ninja failed with: exit status 1

#### failed to build some targets (12:04 (mm:ss)) ####

我检查了一下 external/chromium-webview/prebuilt/arm64/webview.apk ,发现这个文件是一个ASCII文件:

webview.apk
version https://git-lfs.github.com/spec/v1
oid sha256:feddb0a30690da03177b9fae71d6acf04ffb94ce778698facef5688937afc4e2
size 210372668

但是我关注到这个文件中的版本 git-lfs 似乎是官方文档中提到的需要支持 --git-lfs

这是因为我最初不知道必须支持 Git Large File Storage (默认系统没有安装 git-lfs 软件包,所以 git lfs install 初始化命令是报错的),在初始化仓库使用去除了 --git-lfs 导致了这个后续仓库同步问题。

重新安装了 Git Large File Storage 并重新同步仓库来完成

参考