0 序言: LSP
现代 C/C++ 开发中,代码补全、跳转定义等功能是提升开发效率的关键, 今年来的IDE 都支持 LSP 来实现这些功能,而 clangd 是目前最流行的 C/C++ 语言服务器。
如果你使用过像 clangd、ccls 或 cquery 这样的语言服务器(LSP),你一定对compile_commands.json这个文件不陌生——它记录了每个源文件是如何被编译的(包括头文件路径、宏定义、编译选项等), 例如:
1 | [ |
通常, 现代化项目的编译脚本都会支持 compile_commands.json 文件的生成,但对于那些没有原生生成 compile_commands.json 能力的构建系统(比如 Makefile、CMake 未启用特定选项、或者手写的构建脚本),我们该怎么办?
这时,Bear 就派上用场了。
1 Bear简介
Bear(Build EAR)是一个命令行工具,通过拦截构建过程中对编译器(如 gcc、clang)的调用,记录完整的编译命令,并将其转换为标准的 compile_commands.json 文件。
具体来说, Bear 并不解析你的 Makefile 或构建脚本,而是利用 动态链接库预加载(LD_PRELOAD,在 Linux/macOS 上)或 进程监控 技术,在你运行构建命令(如 make)时:
- 劫持(intercept)所有子进程中对编译器(如 gcc、g++、clang 等)的调用;
- 记录每个源文件对应的完整命令行、工作目录和环境;
- 构建完成后,将这些信息整理成符合
Clang Compilation Database格式的JSON文件——即compile_commands.json。
后面我们会结合具体的例子来说明他的原理。
Bear的安装参考仓库主页: https://github.com/rizsotto/Bear
2 Bear 的使用
2.1 基础使用
Bear 的使用非常简单, 只需要在你正常构建的脚本前加上bear --即可。例如, 对于一个使用 Makefile 的项目:
1 | bear -- make |
对这个命令来说, Bear 实际做了:
- 启动
make; - 在
make调用命令时拦截并记录
假设你的make执行时有gcc -I./include -DDEBUG -c src/main.c -o src/main.o 这个命令,Bear 会捕获到这个调用,并记录下来, 其对应compile_commands.json 中的条目如下:
1 | { |
需要说明的是, Bear 并非仅仅用于make, 它基本上支持所有的构建系统:
1 | bear -- ninja |
2.2 高级选项
- –output FILE:指定输出文件名(默认为
compile_commands.json) - –append:追加到已有的
compile_commands.json - –verbose:显示详细日志
实际效果:配合 clangd 使用
一旦生成了 compile_commands.json,只需将其放在项目根目录,clangd 就会自动读取。此时,在 VS Code(安装 clangd 插件)、Neovim(配置较为复杂…)等编辑器中,你将获得:
- 精准的代码跳转(Go to Definition)
- 智能补全(包括宏和模板)
- 实时错误诊断
- 查找所有引用(Find References)
这大大提升了阅读大型 C/C++ 项目(如 Linux 内核、Postgresql 等)的体验。