在CentOS7等老系统上配置clangd进行C/C++开发

应该有许多公司开发机器上还是用着比较老的环境,比如CentOS7之类的。这类系统上很可能他的glibc的版本不到2.18,clangd要求的最低glibc版本就是2.18,因此我们没办法直接在这类老系统上运行clangd。
但是vscode上微软的那个c++插件一坨史,慢不说,补全也差劲。

我的要求有几点:

  1. 不能升级内核的glibc版本,因为这可能导致许多服务出现错误,而且这是公司机器更加不敢乱折腾。
  2. 不安装clang,头文件等基于CentOS下的gcc4.5.8。
  3. 安装在用户目录下,不需要root。

折腾了许久,终于搞出了一个能用的方案。

手动编译glibc2.18

首先clangd本身除了对glibc版本大于2.18之外,没有别的要求,所以我们可以在用户目录下编译一个只供运行clangd的glibc,这样就不需要升级内核的glibc版本。

wget https://mirrors.tuna.tsinghua.edu.cn/gnu/glibc/glibc-2.18.tar.gz
tar -zxvf glibc-2.18.tar.gz
cd glibc-2.18
mkdir build
cd build
../configure --prefix=/home/用户名/myglibc
make -j 8
make install

注意,在../configure的过程中,可能会失败,原因可能有缺少依赖比如autoconf之类的,缺什么我们就装什么即可。如果提示LD_LIBRARY_PATH包含当前目录的错误,我们只需要在当前终端用命令export LD_LIBRARY_PATH=即可,这个命令的效果在关闭终端后就消失,因此无须担心。而且我们只需要编译完成之后就再也不需要输入这个命令。

下载已经编译好的clangd

可以在https://github.com/clangd/clangd/releases/tag/16.0.2此处下载已经编译好的clangd。

wget https://github.com/clangd/clangd/releases/download/16.0.2/clangd-linux-16.0.2.zip
unzip clangd-linux-16.0.2.zip
cd clangd_16.0.2/bin
# 尝试用刚刚编译出来的glibc运行这个clangd
/home/用户名/myglibc/lib/ld-2.18.so /home/用户名/clangd_16.0.2/bin/clangd

如果运行成功没问题,那这一步就成功了。

编写运行clangd的脚本

但是此时就算前台能够成功运行LSP,vscode-clangd也是没办法找到LSP的进程的。我们需要在vscode的settings.json中配置clangd.path这一项才行。
但是我们的clangd没办法直接运行,如果你直接./clangd,还是会报错/lib64/libc.so.6: version GLIBC_2.18' not found`。所以我们可以用一个迂回的办法,写一个脚本,把这个脚本伪装成clangd,然后在clangd.path中填上该脚本的路径即可。

cd clangd_16.0.2/bin
vim start_clangd.sh
#在文件中加入以下这行内容
/home/用户名/myglibc/lib/ld-2.18.so /home/用户名/clangd_16.0.2/bin/clangd $@
#退出vim,赋予该脚本执行权限
chmod +x start_clangd.sh

尝试运行一下脚本,看看是否能成功执行clangd,sh start_clangd.sh,能成功执行就没问题。

接下来到vscode的settings.json中,加入这一项:"clangd.path" : "/home/用户名/clangd_16.0.2/bin/start_clangd.sh"

接下来ctrl + shift + preload window重新加载一下vscode,就会发现vscode能够与LSP建立通信了,vscode-clangd可以work。

(可选)配置clangd

有可能clangd正常运行后,出现了头文件找不到之类的异常。我在这里总结一下我遇到的几个找不到头文件的异常。

C++的头文件找不到

这个问题主要是我们没有给clangd配置使用gcc的库,我们需要在vscode的settings.json中加入这一项即可:

"clangd.arguments" : [
	"--query-driver=/usr/bin/g++"
]

诸如stdarg.h之类的头文件找不到

查看了clangd的官方文档后,可以知道,由于这些头文件与parser的关系过于密切,所以和clangd绑定了,这些路径的目录是写死的,是../lib/xxx。这里是相对路径形式给出的,经过测试,用本文的方法,会以ld-2.18.so会起点算相对路径。所以我们先去clangd的文件夹把这些头文件拷贝出来。

cd /home/用户名/clangd_16.0.2
cp -r ./lib /home/用户名/myglibc

这样的话,到时候clangd就会去路径/home/用户名/myglibc/lib/../lib找头文件,就能正确找到那些头文件了。

基于makefile生成compile_commands.json

有可能接触的项目并没有使用CMake,但是clangd需要compile_commands.json的数据才能提供补全和索引等功能。
此时可以考虑使用bear(在CentOS上同样需要手动编译老版本),所以这里更推荐使用compiledb。

compiledb只需要有pip就可以安装,一般环境上都有Python和pip,没有的话包管理工具也能很方便装上。在使用pip install compiledb即可了。
compiledb就可以很方便的生成compile_commands.json给clangd使用。至此,就在老系统上拥有了一个相对现代化的C/C++开发环境。

热门相关:女大学生管家   寻找与嫂子的契合度   被侮辱的耶稣   想做的日子   表姐和她的朋友