CentOS 7运行clangd 16
微软官方的VSCode C++插件是单线程模式,在扫描大型工程的时候速度特别慢。所以我一直用vscode-clangd插件。
但是clangd的最低要求是glibc 2.18。在一些比较老的系统上,比如CentOS 7,只有glibc 2.17。这会导致新版的clangd无法启动:
1 |
|
CentOS官方源里只有clangd 7,版本太老,无法运行vscode-clangd插件。
我折腾了好几天,试着找到了一种相对简单的方法,足够让clangd和vscode-clangd插件跑起来,也不破坏系统glibc,也不编译LLVM或GCC。
本文使用的系统是CentOS 7(VMWare Player 17),clangd版本为16.0.2。
原理解释
对原理不感兴趣的可以直接跳过这部分。
我在网上找到的方法大致分为三种:
- 升级系统的glibc。这种方法比较危险,很容易导致系统无法启动。
- 自己编译clangd。且不谈编译得到的clangd能否正确支持VSCode。这需要用cmake 3.x编译LLVM工具链。然而,CentOS 7只自带cmake 2.x。所以你首先要升级cmake等工具链。而且自己编译的clangd依然要依赖于glibc,本质上还是没解决问题。
- 使用容器或虚拟机在CentOS 8里看代码。这样写代码和跑代码的环境不一致,也很不方便。
根据官方的说法,clangd不会引入对glibc 2.17的支持,所以如果想用官方提供的binary,glibc 2.18是绕不开的。
但clangd除了glibc 2.18,没有其它的运行库依赖。可以用ldd
命令列出clangd需要的动态运行库。看上去列出了一大堆,其实都是glibc的库:
1 |
|
所以理论上,除了glibc 2.18,其它任何东西都不需要自己重新编译。
单独替换libc.so
的版本不行。我试过用LD_LIBRARY_PATH
强制加载新版本的libc.so
这一个文件,会报一些莫名其妙的错误。因为glibc里的各种库(包括加载程序使用的ld.so
)是一个整体,不同版本的是不兼容的。
此外,ld.so
搜索glibc库文件的路径是写死在代码里的。所以你必须要指定一个目录,把glibc编译和安装进去,它才能正常使用。
因此我的方法是:编译一个仅用于运行clangd的glibc 2.18,安装到自己的目录里,然后让clangd在运行时动态链接上去。
执行过程
需要安装GCC、GNU make等编译工具。一般这些都是系统自带的。如果没有的话也可以通过yum
安装。
CentOS 7自带GNU Make 3.82和GCC 4.8.5。
编译GLIBC 2.18
GNU官网下载glibc速度很慢。我这里用的是清华的镜像。
注意:本过程不需要root权限。
1 |
|
你可以验证一下你的glibc是否安装成功:
1 |
|
它应该输出如下内容:
1 |
|
用自己的ld.so运行clangd
在编译好的glibc的lib
目录下有个ld-2.18.so
,用它运行clangd:
1 |
|
clangd已经可以正常启动了:
你可以把这行命令写成可执行的shell脚本,就可以供VSCode插件使用。
参考文章
GLIBCs not found on host · Issue #16 · clangd/vscode-clangd
安装clangd:‘GLIBC_2.18‘ not found解决 - 李响Superb的技术博客 - 51CTO博客
Compile and install GLIBC 2.18 in CentOS 7
关于不同版本 glibc 更换的一些问题-Pwn-看雪-安全社区|安全招聘|kanxue.com
c - Can LD_PRELOAD be used to load different versions of glibc? - Stack Overflow