最近在 CentOS 7 服务器上写程序时没有 LSP 的帮助,感觉写起来很费劲,于是折腾了一下 clangd 使之能为 coc.nvim 所用。
基本环境要求
-
Anaconda/Miniconda 可以去各大镜像站下载安装包,然后直接
sh Anaconda_xxx.sh进行安装。这里推荐使用 miniconda ,因为 Anaconda 内置的包太多,每次conda install解析依赖冲突都会耗时 114514 年,而 miniconda 因为内置的包更少,依赖解析起来反倒更快。 -
Vim 及其插件 使用
conda命令安装 Vim 8.0 或更高的版本1conda install -c conda-forge vim然后查看 vim 的版本号:
1 2 3 4 5 6 7 8$ vim --version VIM - Vi IMproved 9.0 (2022 Jun 28, compiled Aug 31 2022 01:19:52) Included patches: 1-335 Compiled by conda@065326dfb3d2 Huge version without GUI. Features included (+) or not (-): +acl +file_in_path +mouse_urxvt -tag_any_white ... ...是 9.0 ,说明安装成功。
然后安装
vim-plug和coc.nvim,直接 Follow 官网上的安装教程即可
安装 clangd
CentOS 7 的 yum 源里也有 llvm 和 clang 的包,但它们都没有提供 clangd ,那我们只能去自己安装了。
其实如果你使用 coc-clangd 的话,它会帮你下载 clangd 的可执行文件,但网上预编译的 clangd 没有对
CentOS 7 这种老平台适配,运行时会报这个经典错误
|
|
这是因为 CentOS 7 默认的 glibc 只有 2.17 ,而贸然升级 glibc 又是管理 Linux 服务器的大忌(各种程序会炸),
那就只能寻求别的办法了。
所幸 Anaconda 提供了 clangd ,我们只需要执行下面的命令即可
|
|
然后检查一下各个程序的版本
|
|
写一个 C 的 Hello world :
|
|
看能不能用 Clang 编译
|
|
看来是没问题的;那么 C++ 的 Hello world 呢?
|
|
使用 clang++ 编译:
|
|
这又是一个很经典的错误,它表示 clang++ 找不到头文件 iostream ,解决它的办不是添加 -I/usr/include/... 等参数,而是告诉 clang++ 借用 gcc 工具链内的一些头文件和链接库,具体办法就是使用 --gcc-toolchain 这个参数,
官网1
上对这个参数的说明中表示
|
|
那就很好办了,直接指定 --gcc-toolchain=/usr 即可:
|
|
编译运行成功。
此时关于 Clang 的安装就完成了。
配置 coc.nvim
coc.nvim 的官网提供了 clangd 的配置模板,直接复制到 ~/.vim/coc-settings.json 里即可
|
|
此时,用 Vim 打开刚才写的 C Hello world main.c 应该已经可以提供补全了,如图所示

接下来配置 C++ 源文件的补全。如果不添加别的参数,那么打开刚刚的 C++ Hello world main.cpp ,应该会出现以下错误
这和之前直接用 clang++ 编译时的错误一模一样,之前是通过给 clang++ 加一个参数 --gcc-toolchain=/usr 来解决的,
那么一定有方法可以把编译参数传给 clang++ 来让 clangd 正常工作。 clangd 官网上给出的解决方案是在 main.cpp 同目录下写一个配置文件让 clangd 来正确调用相关的程序,有三种格式可供选择:
-
compile_commands.json这个就是用 json 的格式把编译时需要的命令和参数记录下来传给
clangd,它需要把每个文件的编译命令都显式写出来, 我想没人会喜欢手写 json ,并且是如此啰嗦的 json , 下面是一个示例21 2 3 4 5 6 7[ { "directory": "/public/home/xxx/tests/cxx", "arguments": ["/public/home/xxx/.miniconda/bin/clang++", "--gcc-toolchain=/usr", "main.cpp"], "file": "file.cc" }, ] -
compile_flags.txt这个文件的格式非常简单,把参数逐行写到这个文件里即可
1 2--gcc-toolchain=/usr --std=c++11然后
clangd就能正常工作了。
-
.clangd这个文件格式会稍微复杂一些,官网3上有详细的解释,这里给出一个可用的示例
1 2CompileFlags: Add: [--gcc-toolchain=/usr]
将上述三个文件中的任意一个放到 main.cpp 的同目录下,用 Vim 打开 main.cpp , LSP 应该能正常补全了

看起来效果不错,但总要写这些配置文件总让人不爽,倒不是说参数太长,而是连建个 Hello world 都要写个配置文件难免过于麻烦了,而且编译参数在 Makefile 里已经写过一遍,再写一遍岂不很累。有没有办法不用写这些配置,就把参数传给 clang++ ?经过上网冲浪,在 vscode 和 coc-clangd
的配置里有个参数叫 --fallbackFlags ,它表示当
clangd 找不到上面 compile.json 、 compile_flags.txt 和 .clangd 中任意一个时所使用的参数。从 coc-clangd
的源码4里得知,
这个参数应该被放在 initializationOptions 下面。打开 ~/.vim/coc-settings.json ,加上这个参数:
|
|
删掉 compile.json 、 compile_flags.txt 和 .clangd ,然后打开 main.cpp ,补全依然正常工作,大功告成。
当然如果你需要为某个工程写特定的编译参数,那还是老老实实用那三个配置文件吧, initializationOptions 仅限简单场景使用。