vscode中使用clangd

vscode官方推荐的微软的 cpptools 既实现了 lsp 协议(提供语法高亮等),又实现了 dap 协议(调试),而且也不需要compile_commands.json ,还支持递归查找头文件。很适合

  • c语言项目
  • 小型c++语言项目
  • 文件经常变动的demo。不必写 cmake 等,更也不需要经常重新生成compile_commands.json
  • 刷力扣题

但是面临使用 bazel 的大型c++项目(如TensorFlow)时,cpptools性能差,开始力不从心了

lsp

clangd是llvm项目推出的C++语言服务器,通过LSP(Language Server Protocal)协议向编辑器如vscode/vim/emacs提供语法补全、错误检测、跳转、格式化等等功能。

可以使用 vscode插件clangd。其会在后台调用 clangd 可执行文启动程序作为 lsp 服务。

bazel

通常是使用hedronvision/bazel-compile-commands-extractor: Goal: Enable awesome tooling for Bazel users of the C language family在bazel项目里产生 compile_commands.json 。

使用bazel进行编译时,其会产生bazel-bin等符号链接,其中external指向项目依赖的第三方库。

当查看代码定义等跳转到第三方库里时,会因为vscode(或clangd?)将解析符号链接,将文件的实际绝对路径传给lsp服务器,进而导致lsp服务器无法在 compile_commands.json 找到相关的文件的编译命令(其实 compile_commands.json 里有第三方库文件的编译命令,但是其记录的是其相对于当前项目的相对路径)。之前尝试多种办法都没法让lsp服务器也对第三方代码进行正确的代码解析。好在有心栽花花不开,无心插柳柳成荫,无意中发现配置下--compile-commands-dir就可以解决问题。

个人的vscode的settings.json中clangd.arguments相关配置,可供参考

    "clangd.arguments": [
        "--compile-commands-dir=${workspaceFolder}/",
        "--completion-style=detailed",
        "--suggest-missing-includes",
        "--all-scopes-completion",
        "--pch-storage=memory",
        "--cross-file-rename",
        "--background-index",
        "--log=verbose",
        "--clang-tidy",
        "--pretty"
    ]

之前使用"--query-driver=**"可能匹配到非预期的gcc等,导致clangd报错说unordered_map的mapped_type有问题,有些结构体找不到定义等奇怪问题

另外环境变量TEST_TMPDIR可能会导致bazel产生的文件(如根据.proto产生的.h文件)不在clangd的搜索范围,导致其报错说找不到一些头文件。进行bazel build时不配置该环境变量即可。

dap

既然都用llvm的clangd了,那使用lldb进行调试也是顺理成章的事情。vscode插件codelldb

当然可以继续使用ms的cpptools,只是需要把其lsp相关功能(与clangd冲突)关闭

其他

多年前写代码时,就被代码的正确跳转和自动补全所困扰。最初是在 vim 上使用 ctags 这种基于 tag 标签分析的(估计是基于正则表达式匹配)。在我看来,最大的缺点是其不会预处理宏,所以无法理解那种在宏里定义的变量。后来基于语义解析的 YouCompleteMe(YCM) 出现解决了这种问题,但是 YCM 安装太麻烦了。当时的 YCM 还是调用 libclang 而不是 clangd 来作为编译器前端来进行代码解析生成 AST 树。

后来发现了 vscode(比 vim 好用多了。特别是其支持 remote development 后,更是没有理由用 vim 了)。

C_Cpp.IntelliSenseEngineTag Parser 是不感知上下文的标签分析,而 default 是感知上下文的,估计会预处理宏的。

但是在开发大型 bazel 项目(其通常会下载多个第三方库,使用 protoc 产生些头文件等)时,使用 ms 的 cpptools,经常会找不到头文件,或反应迟钝(可能是递归查找太多头文件导致的),基本上不可用。挨个手动指定些第三方库的头文件又是费时费力。

想不到时隔多年,最后使用 clangd 搭配折腾许久才摸索出来的配置项等,终于解决了这个老顽疾,真是可喜可贺,感慨万千。

posted @ 2025-04-22 22:24  Tifa_Best  阅读(643)  评论(0)    收藏  举报