本文将介绍如何在 WSL2 环境下,利用 VSCode 结合 clangd 插件,构建一个能够高效美观地阅读大型 C 项目的 IDE 环境。clangd 插件版本为 0.4.0,本地 clangd 后端版本为 18.1.3。

基本配置

WSL2 配置的基本流程如下所示:

  1. (如果启用)禁用 Microsoft 的 C/C++ 扩展中的 IntelliSense 功能,防止冲突。
  2. 扩展应用商店安装 clangd 插件。
  3. 在 WSL2 中安装 clangd 后端:sudo apt install clangd
  4. 创建 compile_commands.json
  5. 在项目根目录下创建 .clangd 配置文件进行进一步调整。

在此简单解释一下 compile_commands.json.clangd 配置文件的作用:compile_commands.json 存储着项目的编译命令,clangd 正式根据该命令列表推断出不同源代码之间的关系,实现符号跳转的功能;而 .clangd 则相当于一个“微调选项”,对项目的 clangd 分析工具进行进一步调整。

接下来,我将介绍我平常接触较多的两个项目——Linux 内核和 QEMU,来介绍具体的配置方法。

QEMU

生成编译命令

QEMU 下可以通过编译前的配置(configure)来生成编译命令:如下所示:

1
./configure --target-list=x86_64-softmmu

这样文件 compile_commands.json 就生成在了 build 目录下。

编写配置文件

接下来编写 .clangd 配置文件,首先需要通过 CompilationDatabase 选项指定 compile_commands.json 文件所在的目录,即 build。另外,由于像 QEMU 和 Linux 内核这种 20 年以上历史、几百万上千万行代码的大型项目,由于 VSCode 的 clangd 插件又是基于单文件分析,因此会遇到很多稀奇古怪的警告和错误,体现在 VSCode 中就是黄色和红色的波浪线,但其实项目本身编译起来并没有什么问题… 因此我的选择是:

  • 保留符号跳转等提示功能。
  • 禁用所有的警告和错误分析。

虽然这样会降低一定的功能性,但相比我原本的 vim + ctags 的解决方案还是要现代太多了。总之,QEMU 的配置文件如下所示:

1
2
3
4
5
6
7
8
9
10
11
CompileFlags:
CompilationDatabase: "build"
Add: [-w, -ferror-limit=0]

Diagnostics:
Suppress: ["*"]
ClangTidy:
Remove: ["*"]

Index:
Background: Build

Linux

生成编译命令

Linux 内核的 Makefile 中准备了一个专门的生成编译命令的选项:如下所示:

1
make compile_commands.json -j$(nproc)

生成的 compile_commands.json 直接就在项目根目录下。

编写配置文件

接下来编写 .clangd 配置文件,基本的配置和 QEMU 类似,区别第一在于 compile_commands.json 文件的位置为根目录;另外,由于我使用的是 gcc 编译,会遇到一些 gcc 专用的编译优化选项,clangd 无法识别,需要在 CompileFlags::Remove 中手动将其移除,如果使用是 clang 进行编译,可能不会遇到该问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
CompileFlags:
CompilationDatabase: "."
Remove:
- -m*
- -fno-delete-null-pointer-checks
- -fno-allow-store-data-races
- -fconserve-stack
- -fpatchable-function-entry=*
- -ftrivial-auto-var-init=*
- -fstrict-flex-arrays=*
- -fno-stack-clash-protection
- -fcf-protection=*
- -fno-jump-tables
- -fno-omit-frame-pointer
- -mindirect-branch=*
- -mfunction-return=*
- --param=*
Add: [-w, -ferror-limit=0]

Diagnostics:
Suppress: ["*"]
ClangTidy:
Remove: ["*"]

Index:
Background: Build

我上述的 Remove 列表可能并不全面,如果后面遇到部分源文件仍然提示了错误提示,可以使用 Claude Code 等 Agent 进一步对其进行完善。