首页
社区
课程
招聘
[原创] Android Kernel 源码环境
发表于: 2022-11-30 15:59 36483

[原创] Android Kernel 源码环境

2022-11-30 15:59
36483

工欲善其事 必先利其器

本篇将会搭建一个完美的Linux Kernel及其内核模块的源码阅读开发环境

当我们开始研究Android Kernel,想要优雅的阅读源码好像是一件费劲的事情。

因为Kernel源码实在是太庞大了,打开一个c文件,想要详细的研究研究,甚至上手写两句代码,即没有高亮提示,也没有代码跳转。在这种情况下,想要理清楚内核源码,相当不易。

用CLion? 貌似不太行。
Kernel的构建体系是make而不是类似于LLVM的CMake。Clion直接打开Kernel源码是无法被CLion解析的。

用Source Insight?貌似不是非常完美。
对于Kernel源码来说,很多函数symbols一样,只是适用于不同架构罢了。Source Insight在跳转的时候,全源引索,并不会帮我们加以区分。诸如此类的问题,Source Insight还有很多...强迫症患者表示很难受~

用VsCode?貌似更不行?
VsCode对C/C++代码的高亮提示,依托于C/C++ Extension Pack这个插件,我不清楚别人体验如何,至少对我来说,这个插件有多烂,我都不想多做评价....

为什么IDE集成开发环境可以完美的索引项目代码?
参考于微软的一篇文档,我了解到了语言服务器这个东西。

什么是语言服务器,有什么作用?

CLion对代码索引的功能 貌似就是通过clangd实现的。

如何让语言服务器运作起来?
我们现在知道了,想要对c语言的代码做解析,就需要clangd这个语言服务器。那么,如何让clangd运作起来呢?clangd对代码做解析,需要compile_commands.json文件。

该文件是什么作用?
这个文件记录着我们对源码编译时候的每个命令,用的什么编译器,提供的什么编译参数,链接了哪些库,设置了什么宏,编译的什么源码文件等等。
如此,clangd就可以通过编译命令,详细的了解到整个编译流程。

如何生成该文件?

这里特别提一嘴,对于mk体系编译的的项目
mk脚本,其本质上是make,但是对于安卓的来说,生成编译描述文件非常简单
官方有文档提供命令

所以,理论上来说,搭建的这套代码解析方案,不仅仅适用于Kernel源码阅读。也适用于各种交叉编译

毫无疑问 Kernel的源码大多是c文件,以及少部分的汇编文件,设备树文件......

Kernel正好是make体系,理论上是可以用Bear的。
由于我做教程的时候,已经把内核编译结束了,实在不想重新编译内核,理论上选哪个都一样,我们只是要个编译描述文件罢。

虽然C/C++ Extension Pack相当的烂,但是部分C/C++方面的东西,还需他提供支持。
所以这里依然需要安装该插件,后续在设置中禁用掉他的代码提示服务,转交给clangd插件即可。

关于clangd插件

完整编译内核

这里默认读者会换源或者其他手法保持网络通畅

生成编译描述文件

对于Out-of-tree编译的内核模块
详细见原项目地址的Out-of-tree module development
这一套代码解析方案也完美的适用于Out-of-tree的内核模块

配置VsCode
对于VsCode来说.vscode目录下,是一些配置文件。
我们修改原项目的setting.json文件,内容修改成如下:

注释已经写到相当清楚,这里不再赘述。

打开Kernel根目录,等待索引结束

你发现会报很多无关痛痒的警告:
Warning

内核源码根目录下,新建一个文件.clangd,内容如下:

 
 
make ## 原编译命令 --> 不生成compile_commands.json
bear make ## 使用bear --> 生成compile_commands.json
make ## 原编译命令 --> 不生成compile_commands.json
bear make ## 使用bear --> 生成compile_commands.json
set(CMAKE_EXPORT_COMPILE_COMMANDS True)
set(CMAKE_EXPORT_COMPILE_COMMANDS True)
ndk-build GEN_COMPILE_COMMANDS_DB=true ## 构建的时候顺便生成compile_commands.json
ndk-build GEN_COMPILE_COMMANDS_DB=true ## 构建的时候顺便生成compile_commands.json
## 这里选择common-android12-5.10分支
repo init -u https://android.googlesource.com/kernel/manifest -b common-android12-5.10
## 这里选择common-android12-5.10分支
repo init -u https://android.googlesource.com/kernel/manifest -b common-android12-5.10
repo sync
repo sync
BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh
BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh
cd common # 进入内核源码根目录
# clone vscode-linux-kernel项目到.vscode文件夹
# 该文件夹为vscode配置文件夹 类似于.idea
git clone --depth=1 https://github.com/amezin/vscode-linux-kernel.git .vscode
cd common # 进入内核源码根目录
# clone vscode-linux-kernel项目到.vscode文件夹
# 该文件夹为vscode配置文件夹 类似于.idea
git clone --depth=1 https://github.com/amezin/vscode-linux-kernel.git .vscode
python .vscode/generate_compdb.py -O ../out/android12-5.10/common/
ls -al | grep compile_commands.json
# -rw-r--r--   1 kali kali 8888862 Nov 30 01:07 compile_commands.json
python .vscode/generate_compdb.py -O ../out/android12-5.10/common/
ls -al | grep compile_commands.json
# -rw-r--r--   1 kali kali 8888862 Nov 30 01:07 compile_commands.json
{
    "files.associations": {
        "iostream": "cpp",
        "intrinsics.h": "c",
        "ostream": "cpp",
        "vector": "cpp"
    },
    "editor.formatOnPaste": true,
    "editor.formatOnSave": true,
    "editor.formatOnType": true,
    // 关闭 C/C++ Extension Pack 插件的提示 防止其与clangd冲突
    "C_Cpp.errorSquiggles": "Disabled",
    "C_Cpp.intelliSenseEngineFallback": "Disabled",
    "C_Cpp.intelliSenseEngine": "Disabled",
    "C_Cpp.autocomplete": "Disabled", // So you don't get autocomplete from both extensions.
    // 指向clangd路径
    "clangd.path": "/tmp/NDK/ndk-r25b/toolchains/llvm/prebuilt/linux-x86_64/bin/clangd",
    "clangd.arguments": [
        // compelie_commands.json 文件的目录位置
        "--compile-commands-dir=${workspaceFolder}/",
        // 让 Clangd 生成更详细的日志
        "--log=verbose",
        // 输出的 JSON 文件更美观
        "--pretty",
        // 全局补全
        "--all-scopes-completion",
        // 建议风格:打包(重载函数只会给出一个建议)相反可以设置为detailed
        "--completion-style=bundled",
        // 跨文件重命名变量
        "--cross-file-rename",
        // 允许补充头文件
        "--header-insertion=iwyu",
        // 输入建议中,已包含头文件的项与还未包含头文件的项会以圆点加以区分
        "--header-insertion-decorators",
        // 在后台自动分析文件 基于 complie_commands
        "--background-index",
        // 启用 Clang-Tidy 以提供「静态检查」
        "--clang-tidy",
        // Clang-Tidy 静态检查的参数,指出按照哪些规则进行静态检查
        // 参数后部分的*表示通配符
        // 在参数前加入-,如-modernize-use-trailing-return-type,将会禁用某一规则
        "--clang-tidy-checks=cppcoreguidelines-*,performance-*,bugprone-*,portability-*,modernize-*,google-*",
        // 默认格式化风格: 谷歌开源项目代码指南
        "--fallback-style=file",
        // 同时开启的任务数量
        "-j=2",
        // pch优化的位置(memory 或 disk,选择memory会增加内存开销,但会提升性能)
        "--pch-storage=disk",
        // 启用这项时,补全函数时,将会给参数提供占位符
        // 我选择禁用
        "--function-arg-placeholders=false"
    ],
}
{
    "files.associations": {
        "iostream": "cpp",
        "intrinsics.h": "c",
        "ostream": "cpp",
        "vector": "cpp"
    },
    "editor.formatOnPaste": true,
    "editor.formatOnSave": true,
    "editor.formatOnType": true,
    // 关闭 C/C++ Extension Pack 插件的提示 防止其与clangd冲突
    "C_Cpp.errorSquiggles": "Disabled",
    "C_Cpp.intelliSenseEngineFallback": "Disabled",
    "C_Cpp.intelliSenseEngine": "Disabled",
    "C_Cpp.autocomplete": "Disabled", // So you don't get autocomplete from both extensions.
    // 指向clangd路径
    "clangd.path": "/tmp/NDK/ndk-r25b/toolchains/llvm/prebuilt/linux-x86_64/bin/clangd",
    "clangd.arguments": [
        // compelie_commands.json 文件的目录位置
        "--compile-commands-dir=${workspaceFolder}/",
        // 让 Clangd 生成更详细的日志
        "--log=verbose",
        // 输出的 JSON 文件更美观
        "--pretty",
        // 全局补全
        "--all-scopes-completion",
        // 建议风格:打包(重载函数只会给出一个建议)相反可以设置为detailed
        "--completion-style=bundled",
        // 跨文件重命名变量
        "--cross-file-rename",
        // 允许补充头文件
        "--header-insertion=iwyu",
        // 输入建议中,已包含头文件的项与还未包含头文件的项会以圆点加以区分
        "--header-insertion-decorators",
        // 在后台自动分析文件 基于 complie_commands
        "--background-index",
        // 启用 Clang-Tidy 以提供「静态检查」
        "--clang-tidy",
        // Clang-Tidy 静态检查的参数,指出按照哪些规则进行静态检查
        // 参数后部分的*表示通配符
        // 在参数前加入-,如-modernize-use-trailing-return-type,将会禁用某一规则
        "--clang-tidy-checks=cppcoreguidelines-*,performance-*,bugprone-*,portability-*,modernize-*,google-*",
        // 默认格式化风格: 谷歌开源项目代码指南
        "--fallback-style=file",
        // 同时开启的任务数量
        "-j=2",
        // pch优化的位置(memory 或 disk,选择memory会增加内存开销,但会提升性能)
        "--pch-storage=disk",

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2022-11-30 21:52 被Ssage泓清编辑 ,原因: 修正
收藏
免费 21
支持
分享
最新回复 (12)
雪    币: 147
活跃值: (345)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
好文默默点个赞
2022-11-30 19:30
0
雪    币: 4462
活跃值: (6711)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
内核学习中,好文章
2022-12-1 02:36
0
雪    币: 126
活跃值: (661)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
linux内核本身就有脚本生成compile_commands.json文件的

https://github.com/torvalds/linux/blob/master/scripts/clang-tools/gen_compile_commands.py
2022-12-1 11:08
0
雪    币: 657
活跃值: (1592)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
Bombs linux内核本身就有脚本生成compile_commands.json文件的 https://github.com/torvalds/linux/blob/master/scripts/cla ...
看了一下,确实如此
感谢,那就是又多一种方案
2022-12-1 11:57
0
雪    币: 2345
活跃值: (10422)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
给大佬点赞
2022-12-1 15:37
0
雪    币: 3814
活跃值: (3102)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
学习一下 对这个很有需求
2022-12-1 18:58
0
雪    币: 3738
活跃值: (3872)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
感谢分享!
2022-12-4 13:10
0
雪    币: 1482
活跃值: (2543)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
谢谢楼主的分享。
2022-12-6 14:05
0
雪    币: 2919
活跃值: (5470)
能力值: ( LV11,RANK:185 )
在线值:
发帖
回帖
粉丝
10
谢谢大佬的新姿势
2022-12-7 14:38
0
雪    币: 303
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
11
感谢大佬
2022-12-15 17:19
0
雪    币: 201
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
"Kernel正好是make体系,理论上是可以用Bear的。"

求教怎么用啊?

2022-12-27 22:03
0
雪    币: 657
活跃值: (1592)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
13
jutang "Kernel正好是make体系,理论上是可以用Bear的。" 求教怎么用啊?

1- Bear的使用极其简单 在make命令之前加上bear即可
2- 我没试过去用bear 所以只是理论可行 对于庞大复杂的内核源码来说 bear能否承担重任 是个问题
3- 建议使用文章所说的py脚本 或者使用内核源码自带的gen_compile_commands.py脚本 这两种选择最优

最后于 2022-12-30 00:20 被Ssage泓清编辑 ,原因:
2022-12-30 00:19
0
游客
登录 | 注册 方可回帖
返回
//