近期想尝试一下安卓 kernel 的 kgsl 模块编译以及模拟。

实验环境

基于 Debian 12,clone 了 android-kernel repo 来进行试验。
由于Android 14以后不再支持 ./build.sh,我们这里集中学习如何使用 Bazel 来进行定制化编译。

编译

实际上高通有自己维护的 manifest 开源仓库,直接在 pull 下来全量编译即可(不过最新版的芯片型号是缺了一些库的)。

建立ddk工作区

ddk 工作区是 (Driver Development Kit),用于内核模块开发编译的工作区。
该工作区的目录结构为:

1
2
3
4
5
6
7
.repo
tools
external/kleaf # 完整 android_kernel 源码
external/prebuilts
MODULE.bazel
device.bazelrc
WORKSPACE.bzlmod

以下命令是创建一个 ddk 工作区的命令,会在目录下创建 MODULE.bazel, device.bazelrc, tools/bazel 等文件

1
curl https://android.googlesource.com/kernel/build/bootstrap/+/refs/heads/main/init.py?format=TEXT | base64 --decode | python3 - [flags]

基于以上命令的 flags 分为几种情况:
注意,以下的命令中 python3 init.py 都指代了上面的 curl 命令。

Local sources

提供完整的本地 android kernel 源码分支(ACK, Android Common Kernel),对应参数 --kleaf_repo /path/to/ddk/workspace/external/kleaf
此时命令为:

1
2
3
$ python3 init.py --local \
--ddk_workspace /path/to/ddk/workspace \
--kleaf_repo /path/to/ddk/workspace/external/kleaf

Local sources + prebuilts

提供了内核源码以及 prebuilts 目录(只包含ABI, headers, symbols list, 编译产物)
此时命令为:

1
2
3
4
$ python3 init.py --local \
--ddk_workspace /path/to/ddk/workspace \
--kleaf_repo /path/to/ddk/workspace/external/kleaf \
--prebuilts_dir /path/to/ddk/workspace/prebuilts/kernel

注意 –kleaf_repo 的路径必须是 ddk/workspace 下

从 prebuilts 中进行编译

确保目录结构:

1
2
3
ddk/workspace
|----external/kleaf
|----prebuilts/kernel

在 workspace 下执行 repo init 命令。

我这里直接使用了 Local sources 方法。在本地建立了工作区。

注意 repo 初始化可能需要 init_ddk 以及 bazel,这时候可以先添加 –branch 参数从远程下载初始环境下来

编译自定义内核

利用 build_kernel 宏,这里我们暂不考虑

编译内核模块以及 DTB

in tree kernel modules

需要在内核 BUILD.bazel 的 kernel_build 中设置添加 modules_outs 属性。

external kernel modules

需要额外定义 kernel_module 。要为 build.config 中的 EXT_MODULES 变量中的每一个模块创建 kernel_module 编译目标
kernel_modulekernel_build 属性为 自定义内核,或者 common 通用内核 //common:kernel_aarch64
outs 目录可以在编译过程中根据报错提示来进行更改。
设置 kernel_module 的 visibility 从而 kernel_modules_install 可以看到
如果 模块 依赖于其他模块,设置 kernel_module_deps
如果模块依赖于其他路径的头文件,需要添加 filegroup,然后向 srcs 添加 headers。

定义 depmod 目标

定义 kernel_modules_install 目标。其包含所有 external kernel modules。其等价于 make modules_install

定义目标来构建所有启动镜像

kernel_image 宏会制作可刷写的分区镜像。

定义发行版目标

定义 pkg_filespgk_install 目标,其包含了想要放置在 distribution 目录的目标。

参考链接