编译LineageOS以及自定义内核(LOS 21.0)
目录
由于一些需求,需要自行调整Lineage内核编译配置、打补丁。记录一下必要的知识。
说明🔗
本文由笔者在Lineage OS 21.0、Pixel 4a(Sunfish)上折腾(添加KernelSU)的经历整理而成,其它环境请视情况调整。哦对了,我用的host os是ArchLinux+Zsh。
什么LOS起源于CM之类的历史啊什么的就不写了。
和直接编译内核有什么不同?🔗
简单地说,没什么不同,只是编译环境配置方式稍有区别。在配置好工具链、源码的情况下,可以说基本没区别。但是笔者觉得想搞清楚内核编译用哪个工具链、哪个配置,还是要先学习Android编译环境(因为真的没搞清楚)。
脱离Android源码环境直接编译内核的好处:
- 下载的源码少得多
- Android一套源码加上编译完内核会超过150G
- 直接编译内核加上源码工具链什么的占用硬盘大概不到30G
- 可以按Linux那套熟悉的来操作
坏处:
- 需要自己配置环境(比源码环境里麻烦一点)
- 不熟悉Android源码环境可能找不到需要的编译配置/工具链
Android源代码仓库介绍🔗
简单说,Android源代码库就是许许多多git仓库按一定层次放置在一起得到的超级仓库,该仓库使用repo
进行一部分管理,而具体到某一仓库的修改(如内核),则使用git进行操作。
repo
构建项目工作目录所加载的<manifest>.xml
描述了整体项目所使用的各个源码库的来源(仓库地址、分支等)和存放位置,以及处理一些软链接。
GKI(通用内核)推出后,部分设备的内核和Android的源码库可以分离、单独编译内核和系统。不过Lineage还是放一起的。
中国大陆内有Lineage OS的源码镜像仓库,若有需求可以选用。
按照LineageOS自动生成的文档开始工作🔗
这是相对简化的版本,毕竟笔者只是想编译内核!
推荐阅读:Android官方文档:构建系统、Android官方文档:编译Android
目标平台:Pixel 4a(Sunfish)
对于ArchLinux,安装所需工具(有些包之间可能有依赖关系懒得排查了):
PACKAGES=(
base-devel android-tools android-udev
bc cpio gettext git libelf pahole perl python tar xz
unzip zip libxcrypt-compat
curl git-lfs libxml2 gperf imagemagick sdl_image libxslt
lzop pngcrush rsync schedtool squashfs-tools
ccache # 如果用上的话,装
nsjail # 可选,我装了但还没配置好
noto-fonts # 编译完整OS需要一套字体,不然会报fontconfig相关错误,可能中间要生成什么图片
)
此外还需安装AUR软件包:ncurses5-compat-libs
仅编译内核的话,上述部分软件包是不必要的。
安装repo,随后初始化仓库(请根据实际情况修改代码):
&&
需要改镜像站的现在可以改了,具体看镜像站说明。搞定了之后开始同步代码:
要下载不少数据(下载量约60G,占用空间约翻倍,因为有一半数据相当于副本),硬盘空间务必留够。
激活环境和设备配置:
# 仅支持bash、zsh,其它shell不兼容/不支持
注意上一步对于Pixel 4a平台会报错,因为需要提取私有blobs。可以从已经装有LineageOS的设备或官方完整刷机包中提取blobs。如从装有LineageOS的Pixel 4a上提取,则需要开启adb调试、root身份调试,然后在刚才的终端执行下面的操作:
然后再试着激活设备配置
前面每一步都没有报错的话,源代码工作空间就都准备好了。
使用完整Android源码环境编译Linux kernel🔗
不妨重新开一个shell,激活一遍环境(也就是说每次新开shell都要这样):
编译内核
然后等编译完成,最后会输出内核位置(例如out/target/product/sunfish/kernel
)。
根据Android官方文档,应该可以这样启动这个内核:
但我得到的却是这样的信息:
creating boot image...
creating boot image - 20695040 bytes
Sending 'boot.img' (20210 KB) OKAY [ 0.216s]
Booting FAILED (remote: 'Error verifying the received boot.img: Invalid Parameter')
fastboot: error: Command failed
经过一些检查,发现是内核没带上dtb,出现了一点问题。要手动合成一下:
也可以用下面指令编译得到完整的boot.img
并测试(会多生成至少4G数据):
boot.img
比kernel-dtb多了ramdisk和一些参数。
kernel启动了就算成功了!
比较令人在意的一点:Lineage OS的内核编译配置在vendor/lineage/build/tasks/kernel.mk
,对应在线仓库位置在https://github.com/LineageOS/android_vendor_lineage/blob/HEAD/build/tasks/kernel.mk
给内核打补丁——例如添加KernelSU🔗
自己编译内核不就是为了自己改么!现在终于到改的部分了!
要修改内核,需要去内核源码库。而对于sunfish,内核在kernel/google/msm-4.14/
。
不过Android是用 我貌似搞错了什么,这不行。但是在每个子项目内创建branch是可以的。repo
管理项目的,那就标准一点,新建一个分支进行开发:repo start linux-ksu
先给内核打上特殊的印记٩( ᐛ )و:
这是一个KBUILD(Linux的构建系统)自带的一个小功能,localversion。最后的内核版本会从4.14.336
(加后面一串)变成4.14.336{-FaintDay}
(加后面一串,不含花括号)。
开个新的干净shell进入内核源码库,准备打KernelSU补丁:
# 用官方脚本打补丁
|
# 启用内核kprobe特性, 测试过了sunfish直接加这行就行
其实官方脚本就是把源码链接进内核源码树、添加了编译依赖,把集成用的依赖启用后,KSu就能正常编译了。有时手动改kernel config不够靠谱,那么就试试make menuconfig
然后make savedefconfig
吧!示例如下:
# 仅仅生成配置只需要host端工具链齐全,交叉编译用的工具链在这里没必要
# 然后进行需要的调整
# 下面保存最小化的配置
# 更新配置
修改完后运行一下make mrproper
打扫干净战场,然后git commit一下(避免被自动标记成dirty),再按前一节所述编译并启动内核。
使用Anykernel3打包内核安装包🔗
总不可能每次开手机都接一下电脑加载内核,那样多麻烦!可以选择直接生成一个完整的boot.img刷入,也可以仅仅编译内核、dtbo、dtb然后修改原本的boot.img。我选后者,搭配Anykernel3制作安装包。
先编译需要的文件:
下载一份AnyKernel3,准备把它改成需要的样子。更换内核不需要修改Ramdisk,placeholder之类的可以完全删除;为了极致精简,有些用不到的binary executables也可以删。
下面假设AnyKernel3模板在ak3文件夹,和lineageos-workspace在同一位置:
# 内核可以直接copy,注意名称
# 也可以解压
# 编辑anykernel.sh
# 然后打包
可以用KernelFlasher刷入这个安装包。先用和之前一样的方式启动带有KSU的内核(也就是需要root权限),随后操作KernelFlasher在活动分区(如果是A/B分区的话)刷入AK3安装包。
额外内容:拆分内核编译环境🔗
这里我打算直接用Google提供的现成环境稍加修改。TBW(感觉自己不会再写下去了,毕竟目的已经达成了)