應該有許多公司開發機器上還是用著比較老的環境,比如CentOS7之類的。這類系統上很可能他的glibc的版本不到2.18,clangd要求的最低glibc版本就是2.18,因此我們沒辦法直接在這類老系統上運行clangd。 但是vscode上微軟的那個c++插件一坨史,慢不說,補全也差勁。 我的要求 ...
應該有許多公司開發機器上還是用著比較老的環境,比如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++開發環境。