从零开端的内核编译

本教程将根据小米 10S 的内核源码进行实例,其他类型的手机请自行寻觅内核源码。具体内容能够参阅我的内核编译项目。

手机类型查询

1. 获取设备(手机)代号

在安卓设备终端(adb shell)上履行:

getprop | grep device

并寻觅带有 ro.xx.device 这一行,里边的内容即为你的手机代号,例如:

# 手机代号为 thyme
[ro.product.device]: [thyme]

2. 获取设备架构

在安卓设备终端(adb shell)上履行:

uname -m

我的设备显现为 aarch64, 即可判别我的设备架构为 aarch64

3. 获取设备内核版别

在安卓设备终端(adb shell)上履行:

uname -r

输出内容的格局为:

  • [版别].[补丁版别].[子版别号]-[内核标识]-[提交记录]

例如我的设备显现为 4.19.157-Margatroid-gb1b98c3d4fd0

内核源码获取

内核源码的一般格局为 [android_]kernel_设备厂商_cpu/代号,例如,小米 10S(thyme)的代号为 thyme, CPU 类型为 sm8250,生产厂商为 xiaomi,则搜索格局应为下面几种:

kernel_xiaomi_thyme
kernel_xiaomi_sm8250
android_kernel_xiaomi_thyme
android_kernel_xiaomi_sm8250

以下是我搜集的一些小米 10S(thyme)的源码库房:

  • Lynnrin-Studio/android_kernel_xiaomi_thyme: 这是我现在编译内核所运用的内核源码。
  • UtsavBalar1231/kernel_xiaomi_sm8250: CLO 内核升级为 CAF 标签 LA.UM.9.12.r1-14700-SMxx50,AOSP 源码同步上游 android-4.19-stable
  • WeeAris/RK-KSU-mi-kernel-SM8250: 支撑 KernelSU 的 Rohail33/RealKing-kernel-SM8250 分支。
  • Rohail33/RealKing-kernel-SM8250: 根据 LA.UM.9.12.r1-08000-SMxx50.0 标签的内核。

当然除此之外还有很多源码,但这些源码对于我来说是我前期学习的一个途径,因而在这里列出给咱们。

途径 具体介绍
各厂商开源 小米内核开源
华为开源代码
去手机社区找源码 XDA 论坛

获取编译东西链

强烈引荐您学习[内核向] 穿插编译器的挑选以及[白话文版] ClangBuiltLinux Clang 的运用来学习东西链的装备。

一起能够合作 Neutron-Clang 的阐明文档来进行编译参数装备。

现在比较引荐的几个预编译东西链如下:

东西名称 简介
Neutron-Clang 这是为内核开发构建的 LLVM 和 Clang 编译器东西链。构建始终是从最新的 LLVM 源代码而不是安稳版别构建的,因而无法确保彻底的安稳性
阿菌•未霜 Clang/LLVM Toolchain with Binutils 这是一个预构建的东西链,构建始终来自最新的 LLVM 和 Binutils 源而不是安稳版别,因而无法确保彻底的安稳性。它是用 Full LTO、PGO 和 BOLT 构建的,以尽可能削减编译时刻。
ClangBuiltLinux/tc-build 相似前两个东西,但是这个东西需求自己在本地从 LLVM 的源码进行构建,但编译时刻较长。

除此之外,一个比较保险的办法是从预编译内核机器的 /proc/config.gz 提取`,需求对应版别的穿插编译器以及 Clang,自行挑选合适版别下载即可,通过这种办法编译出来的内核一般是不会存在过错的。

1. Neutron-Clang 运用介绍

这是为内核开发构建的 LLVM 和 Clang 编译器东西链。构建始终是从最新的 LLVM 源代码而不是安稳版别构建的,因而不能确保彻底的安稳性。现在该编译链东西运用 AntMan 来同步东西,具体运用办法如下:

mkdir -p "$HOME/toolchains/neutron-clang"
cd "$HOME/toolchains/neutron-clang"
bash <(curl -s "https://raw.githubusercontent.com/Neutron-Toolchains/antman/main/antman") -S

一些更多的 AntMan 指令:

功用 对应指令
同步最新的东西链构建 ./antman -S./antman -S=latest
同步特定的东西链版别 ./antman -S=<release tag>
查看更新 ./antman -U
查看更新和同步更新 ./antman -Uy
同步特定更新 ./antman -S=<release tag>
删除同步构建 ./antman -D
显现有关同步构建的信息 ./antman -I
同步特定的东西链版别 ./antman -S=<release tag>

假如需求更多细节介绍,请运转 ./antman --help 获取。

2. ClangBuiltLinux

假如您想要运用这个东西链的话,那么其间的编译东西则需求你自行编译,对应的编译脚本为 ClangBuiltLinux/tc-build。

固然,自行编译确实是一件造轮子且费时吃力的办法,但是通过这种办法编译出来的东西是最适合您的体系的,不会发生其他的编译中的关于 glibc 等方面的过错。

3. 阿菌•未霜 Clang/LLVM Toolchain with Binutils

这是一个预构建的东西链,构建始终来自最新的 LLVM 和 Binutils 源而不是安稳版别,因而无法确保彻底的安稳性。它是用 Full LTO、PGO 和 BOLT 构建的,以尽可能削减编译时刻。

其编译链东西存储在:

  • GitHub:仅用于发布预构建的压缩文件(*.7z)
  • Gitea:仅用于存储预构建的二进制文件(Current AR Archive、ELF 64-bit LSB shared object 存储在 LFS)

编译脚本编写

内核编译流程其实只要两步:

  1. 生成对应设备的装备文件 make <theDefConfig>
  2. 开端编译内核 make

您能够直接履行这些指令进行编译(参数设置一定要正确),或参阅我下面的编译流程:

1. 设置编译链环境

最简略的设置环境办法便是将编译链东西的途径添加到体系途径中,例如:

export PATH="<absolute/path/to/ur/toolchains>/bin:$PATH"
# 例如,您正在运用 neutron-clang
# export PATH="home/user/toolchains/neutron-clang/bin:$PATH"
# 其间的途径必须为绝对途径

假如您在运用 gcc,可能还需求将 gcc 东西链的途径加入到环境变量中。

2. 简易装备脚本

首先给出一个最基础的装备脚本:

#!/bin/bash
args="-j$(nproc --all) \
O=out \
ARCH=arm64 \
CROSS_COMPILE=aarch64-linux-gnu- \
CC=clang \
CROSS_COMPILE_COMPAT=arm-linux-gnueabi- "
make ${args} <config name>
make ${args}

该脚本是在运用上一节的三个东西时才能够正常运用的,假如您运用其他东西能够需求进行其他装备。

下面是一些参数对应的阐明:

参数 阐明 一般参数
CC 指定运用的编译器,因为 make 默认运用 gcc,因而实际上只要你在运用 clang 进行编译的时分才会运用该参数 clang
CROSS_COMPILE 您的主要穿插编译链东西,假如你在运用谷歌的 gcc 4.9,请指定参数为 aarch64-linux-android-,32 位同理 aarch64-linux-gnu-
CLANG_TRIPLE 只在运用 clang 进行编译的时分才需求运用,用于指定当 clang 不收效时分运用的东西链,但在运用上一节咱们提到的东西中根本不必设置该参数 aarch64-linux-gnu-
CROSS_COMPILE_ARM32 只在编译 32 位内核或许带 vdso 补丁的内核时需求指定该参数 arm-linux-gnueabi-
CROSS_COMPILE_COMPAT 相似于参数 CROSS_COMPILE_ARM32 ,但内核版别为 4.19 及更新版别应运用本参数而非 CROSS_COMPILE_ARM32 arm-linux-gnueabi-

更多参数介绍能够参阅一下 Neutron-Clang 的编译阐明,里边对于一些参数的阐明比较具体。

正常情况下,clang 是无法独立完结内核编译的,需求 gcc 的辅佐。但运用上一节介绍的几种东西并不需求并不需求独自指定 gcc 来辅佐编译。

3. 部分参阅脚本

  • DogDayAndroid/KSU_Thyme_BuildBot:我自己编译的内核运用的本地编译脚本。
  • UtsavBalar1231/Drone-scripts:一个很多人运用的编译脚本,我的部分代码也是参阅自这里。
  • EndCredits/kernel_xiaomi_sm7250:相同的一个编译脚本,但并未供给编译链,但是其间的脚本流程我也有参阅。
  • xiaoleGun/KernelSU_Action:KernelSU 的编译脚本,相同有参阅。

制作刷机包镜像

内核编译完结后的打包请参阅文章[内核向] 论怎么高雅的刷入内核,现在最流行的办法是运用 osm0sis/AnyKernel3 来完结整个内核的打包刷入工作。

假如您更喜欢自己着手,那么请参阅文章内的其他办法。

值得注意的是,不同版别的内核编译出来的内容并不相同,因而需求差异他们之间的打包,详情请参阅文章:关于 Image.xx-dtb 和 Image.xx + dtb 的差异。

来自文章的谈论区:_对应芯片组的。比如 865 只需求 kona-v2.1.dtb。假如弄不清楚,能够运用 cat 指令将多个 dtb 连接在一起,bootloader 会自动识别。

编译常见问题

本教程将根据小米 10S 的内核源码进行实例,其他类型的手机请自行寻觅内核源码。具体内容能够参阅我的内核编译项目。

1. -Werror=implicit-int

/arch/arm64/kernel/smp.c:834:8: error: type defaults to ‘int’ in declaration of ‘in_long_press’ [-Werror=implicit-int]

您能够修改 extern in_long_pressextern int in_long_press;或许去除MakeFile 中对应过错限制。

参阅

  • 自己编译定制一个牛逼的安卓内核
  • 让 Android 手机更省电流畅,你能够试试「刷内核」
  • [内核向] 穿插编译器的挑选
  • [白话文版] ClangBuiltLinux Clang 的运用
  • Neutron-clang 的编译阐明
  • [内核向] 论怎么高雅的刷入内核