应该有许多公司开发机器上还是用着比较老的环境,比如CentOS7之类的。这类系统上很可能他的glibc的版本不到2.18,clangd要求的最低glibc版本就是2.18,因此我们没办法直接在这类老系统上运行clangd。
但是vscode上微软的那个c++插件一坨史,慢不说,补全也差劲。
我的要求有几点:
- 不能升级内核的glibc版本,因为这可能导致许多服务出现错误,而且这是公司机器更加不敢乱折腾。
- 不安装clang,头文件等基于CentOS下的gcc4.5.8。
- 安装在用户目录下,不需要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 + p
,reload 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++开发环境。