Android内核编译入门

来自Uotan Wiki · 刷机百科

Android 内核简介

安卓内核用的也是linux(LTS),google把LTS内核和Android的一些补丁、模块结合形成自己的Android通用内核(Android common kernel,ACK)。也就是GKI, Generic Kernel Image。如果你的手机是量产机(Google除外),还会被cpu厂商例如高通,联发科再次开发,下放到手机厂商还会有部分修改。

相当于现在变成了一个Image,镜像了。

GKI 内核会与包含系统芯片 (SoC) 和板级代码的硬件专用供应商模块进行交互。GKI 内核与供应商模块之间的交互通过内核模块接口 (KMI) 来实现,该接口由标识供应商模块所需的函数和全局数据的符号列表组成。

配置使用环境

推荐的编译环境

Ubuntu 20.04 / 22.04

Arch Linux

(因为主播使用的就是这个喵)

考虑到编译环境的稳定性不是很推荐装一些其他的系统

你可以使用 VMware virtual machine 或者 WSL2 (Windows Subsystem on Linux)

目前我更推荐使用 WSL 因为其安装较为方便,并且可以与 Microsoft VScode 协同工作方便你对Git的使用以及对内核源码的修改

(当然 Vmware 也可以,只不过我印象不太好,这货 bug 稍微有点多)

关于这两者方案优劣对比详见百度,此处不赘述。

安装WSL2教程

需要先启用适用于 Linux 的 Windows 子系统以及虚拟化:

按下键盘win+R,并输入powershell回车

poershell终端内输入以下内容:

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

wsl --set --default-version 2

随后打开你的微软应用商店 Microsoft Store

搜索 Ubuntu,选择一个你喜欢的版本安装即可

在安装完WSL后,我们可以注意到其默认安装目录为:C:Program Files\WindowsApps

如果你需要拉内核源码的话后续会占用你大量C盘的空间,因此下一步我们对WSL进行迁移。

我们首先打开 powershell

随后输入 wsl -l -v之后powershell会输出一段:

NAME STATE VERSION

* Ubuntu-20.04 Stopped 2

确认目前状态为 Stopped 之后,我们输入:

wsl --export Ubunut-20.04 D:\WSL\ubuntu-20.04.tar

将WSL的系统镜像导出到其他盘,随后注销目前系统的WSL

wsl --unregister Ubuntu-20.04

随后我们导入刚才导出的tar文件wsl --import <导入名称> <导入盘的路径> <刚才导出的tar的路径> --version 2

例如根据上面的:

wsl --import Ubuntu-20.04 D:\WSL D:\WSL\ubuntu-20.04.tar --version 2

随后再次打开即可

安装一些必要的工具依赖

apt-get update

apt-get install -y build-essential bc bison python curl git zip ftp gcc-aarch64-linux-gnu gcc-arm-linux-gnueabi libssl-dev lftp wget libfl-dev gcc bc zip make

这些依赖可以通过百度查到对应的作用,此处不赘述。

如若你在编译时遇见提示缺依赖的情况,你也可以百度依赖的名字来查询解决方式。

  • 安装/下载交叉编译工具链

Clang

此处推荐两个

一个是Google官方提供的Clang编译器:Google Clang

一个是由知名大佬kdrag0n 提供的预编译Clang:Proton Clang

拉取内核源码

关于如何找到你的内核源码这件事,大部分内核源码在开源时都会参照以下命名规则命名

android_kernel_厂商_平台 例如 android_kernel_xiaomi_sm8250

在针对特定机型进行优化或者重构后的源码也会有开发者将其命名为

android_kernel_厂商_设备代号(或者机型名称)

设备代号请参照这里 :设备代号收录集合

我们一般可以在Github找到这些源码

如果您需要拉取ACK(Android Common Kernel)请前往Google OpenSource

设置环境变量并开始编译

本文将以较新的内核为示例,使用clang编译。部分设备内核可能需要纯gcc编译,此处暂时不做介绍。

首先你需要进入你内核源码的目录,你也可以将下列的指令写在脚本里面

export CC='放clang的路径/bin/clang'
export CLANG_TRIPLE=aarch64-linux-gnu-
export CROSS_COMPILE='aarch64-linux-gnu编译器的路径/bin/aarch64-linux-gnu-'
export CROSS_COMPILE_ARM32='arm-linux-gnueabi编译器的路径/bin/arm-linux-gnueabi-'
export ARCH=arm64
export SUBARCH=arm64
export KBUILD_BUILD_HOST = "hostname"
export KBUILD_BUILD_USER = "username"
make O=out ''device''_defconfig

这里需要注意的是,最后的device

取决于你编译的设备的代号,查看你设备的代号请见:设备代号收录集合

如果是直接从apt等软件包仓库安装的GNU编译套件,那么CROSS_COMPILE可以直接设定为aarch64-linux-gnu. ...ARM32同理 而defconfig则是你设备在内核中的配置文件,一套内核源码可能被多个设备共有。在编译的时候,make通过不同的配置文件来区分这些设备,这些配置文件在arch/[架构]/config下,在make的时候无需指定路径,直接输入配置文件名字即可。[1]

举个简单的例子,内核源码就是一个大超市,defconfig购物清单)则负责告诉make你需要购买什么东西(对其进行编译),从而达成对设备驱动的区分

获取编译结果并刷入测试

内核文件在[你的项目/输出路径/arch/目标内核架构/boot]下

例如我们编译了xiaomi_sdm8250的内核,则在android_kernel_xiaomi_sm8250/out/arch/arm64/boot/里面

其名为Image或者Image.gz或者Image.gz-dtb

他们的区别在于

随后你需要刷入测试,以前有一种方法是使用 Android Image Kitchen 来解开boot.img 并将你编译好的dtb替换进去,现在看来这种方法未免太不优雅,因此我们可以使用由osm0sis大佬开发的Anykernel3打包卡刷包文件,并可以在 TWRP REC 或者 Horizen Kernel Flasher内进行刷入附链接:

①Anykernel3 ②Horizen Kernel Flasher ③TWRP rec



资料参考:

[1] Gtibook 安卓内核编译教程:https://jebchou.gitbook.io/android-kernel-magic/02begin_compile

[2] CSDN 安卓架构-内核:https://blog.csdn.net/weixin_40557160/article/details/128388849

  1. 此处引用了 grislux55 在gitbook上的内核编译教程中针对配置文件的介绍,文末贴上了引用资料链接