简介
由于一个工程为兼容很多代码,如果不进行编译是很难确认编译关系的,这导使用source insight阅读linux kerne时存在如下明显和严重的问题:
- 多个相同的语法Token乃至于文件不知道用了哪个?
- 打不开嵌套宏!
- 哪个选项参与了编译,哪个宏是启用的?
另外,为什么使用clangd而不是c/c++常规插件,原因很简单,就是它不编译需要阅读时动态索引,速度远无法和编译型阅读器比较。
因此bear+clangd的组合,可以精准规避这种二义性,更贴近实际工程需求。
这样的精准度,可以彻底解决source insight上困扰的问题:
- 嵌套宏识别异常,无法正确展开SYSCALL等很多宏
- 规避工程导入重复符号后的定义分歧
- 正确显示宏分支与参与编译的内容
- 规避C/C++插件的引用树缺陷
Linux环境
这里使用的是ubuntu20发行版本,其他任意版本均可,可以通过虚拟机安装。
推荐链接(清华源): ubuntu20.04
虚拟机使用的是vmware16,其他任意版本均可,网上自行下载。
vscode
可直接进入vscode官网下载,支持linux Ubuntu和window等多种环境。因为vscode是基于高级语法设计,内部的模块线程分割得很好。其编辑器支持广泛,linux或windows都能够正常使用。
clangd
clang是一个非常好的C语言编译器前端,效率和框架比老旧的GCC更优秀,其优点就是GCC的缺点,clang唯一的缺点就是很多老工程陷入GCC导致clang没参与进来。
但要注意的是案例中我们要装的是clangd这个语法服务,而不是clang前端。
- 进入vscode插件管理界面,搜索clangd,直接安装clangd插件(不是clangd服务)
- 一般最新的环境vscode右下角会提示我们安装clangd server,点击安装即可。
- 为了保证插件兼容性,需要禁用掉vscode的c/c++插件让其显灰即可,否则会产生冲突
- 如果下载或安装失败,则需要通过apt包管理安装或者去官网下载安装。
bear
bear插入编译过程,生成 clangd所需的符号索引数据库的工具。
很多环境下以及很多工程下,既不能编译也不是用clang编译的,因此我们需要这种方式来生成符号json。
而本案例在linux环境下使用bear工具生成的,通过apt工具直接安装即可。
sudo apt install bear
本项目中,bear结合gcc编译完成后,会生成一个名为compile_commands.json的文件。
Linux Kernel源码获取
本案例用于阅读kernel源码,由于kernel部分不是本文重点,具体获取和编译过程本文参考了一篇内核编译文章:
如何编译 Linux 内核
linux-kernel镜像下载
源码可以换成apt直接下载:
lab@ubuntu:~$ apt install linux-source
linux-source linux-source-5.4.0
完成后会在/usr/src目录下看到linux-source文件夹,源码就在这。如果需要看其他版本的源码可以去网上自行找。本文使用linux-source来进行编译。
bear编译生成索引文件
我们进入kernel路径,按照上述文章处理内核源码。但是,需要在编译环节插入bear来生成clangd所需的json!成功后即可见json文件。
lab@ubuntu:~/linux-source-5.4.0$ bear make -j8
上述的make不限于x86和gcc,可支持arm等交叉编译链,同理也是在命令行首插入bear指令即可。
由于很多定制工程make起始点不在源码路径,则只需拷贝到目标文件路径或者使用linux的ln –s软链接到工程根目录即可(本案例未进行实践)。
vscode阅读源码
在vscode导入linux源码文件夹,创建一个工程并保存到自己知道的路径上。
为了加入clangd经验选项,我们编辑插件常用的参数。
点击添加项,复制输入如下参数,然后确定:
--compile-commands-dir=${workspaceFolder} --background-index --completion-style=detailed --header-insertion=never -log=info
阅读测试
随机挑选阅读一个进程创建函数fork.c ->copy_process,点击”显示调用层次结构”,可以精准确认其调用关系。
插件切换
由于clangd适用于复杂工程,若干小工程实际并无如此链接的需求,可在插件管理界面对clangd禁用,重启c/c++智能插件即可。