Sep 2018 [|]

安裝 Vim 與配置 YouCompleteMe 外掛

「編輯器戰爭」(Editor War) 雖說是一場 VimEmacs 兩派無休止的論戰。但在我看來,只要完成了編輯器的配置並將其投入了日常生產,不論 Vim 還是 Emacs 的死忠粉,都是值得尊敬的。產生這一想法的原因是我剛剛在 Vim 上做了一次痛苦的嘗試。特別是 YouCompleteMe 這個名字連聽起來都些許曖昧的外掛程式,更是竭盡全力地讓我感受到了它的惡意。

本文雖然沒有忠實還原掉坑的全過程,對操作順序進行了調優,但保留了可能出現問題之處的描述,也對解決方案進行了解釋。

Vim 版本 & 配置環境

欲編譯安裝的 Vim 版本是 Github 官方倉庫中目前最新的 8.1

安裝的作業系統環境是 Windows 10 17134 版本下 Windows Subsystem for Linux 提供的 Debian GNU/Linux。所以這裡的 Debian 是 9/Stretch 的 stable 版本。

Windows Subsystem for Linux(以下簡稱 WSL)提供的 Debian 9 具有一定的特殊性,主要體現在環境相比大型的發行版本更為精簡乾淨,但這並不影響 Vim 的安裝流程的體現。

編譯安裝 Vim 8

為什麼編譯安裝

事實上,除了軟體源缺失需要安裝的套裝軟體這一情況,一般用軟體源下載安裝軟體應是首選方案。包管理器會好好地處理依賴,也不容易把系統變髒。所以推薦的在 Debian 系的發行版本上的做法應該是:

sudo apt-get install vim

但是一些 Vim 外掛程式(如本文的 YouCompleteMe )需要 Vim 對 Python 的支援。而這樣默認安裝的 Vim 是默認不開啟對於 Python / Lua / Ruby 等語言的支援的。

那麼如何開啟,本文採用編譯安裝加入開啟 Python 支援的選項,由此得到符合需求的 Vim 。其他解決方案如 vim-nox 則不再討論範圍之內。

下載 Vim 源碼

先安裝 Git 。儘管也可以直接前往 Vim 官方倉庫獲取源碼,但考慮到多數的 Vim 外掛程式管理器也都依賴 Git 對外掛程式安裝升級,所以 Git 應是我們的第一個安裝項目。

sudo apt-get install git

你不需要對 Git 進行複雜的配置,雖然未來你有很大的必要這麼做。這裡我們只需要使用 Git 的簡單操作獲取源碼。

git clone https://github.com/vim/vim

不出意外的話,這將需要幾秒鐘的等待。

編譯 Vim 開啟 Python 3 的支持

前面解釋編譯安裝的原因時已經陳述了開啟 Python 支持的必要性,那麼這裡不再重複,先安裝 Python 3 與 其支援函式庫 libpython3-dev

sudo apt-get install python3 libpython3-dev

理論上主流發行版本如 Debian 應已包含 Python3 的支持,但 WSL 並沒有涵蓋,所以補充安裝之。

回到放置 Vim 源碼的目錄,進入 src 子目錄。在編譯之前,應確保 build-essential 包含的編譯工具成功安裝,否則將會因為找不到編譯工具而報錯。

sudo apt-get install build-essential 

編譯工具準備妥當後便可以開始編譯安裝。開始「編譯三連」。

./configure --with-features=huge \
            --enable-multibyte \
            --enable-python3interp=yes \
            --with-python3-config-dir=/usr/lib/python3.7/config-3.7m-x86_64-linux-gnu \
            --enable-rubyinterp=yes \
            --enable-perlinterp=yes \
            --enable-luainterp=yes \
            --prefix=/usr/local/vim-8.1

第三條與第四條配置選項中,我選擇開啟了 Python 3 支援並告知了 config 檔所在目錄。如果在上面遺漏了 libpython3-dev 的安裝,可能會導致 config 檔的缺失。

當然,以上兩個目錄也會隨著安裝 Python 的版本變化(比如此處本機安裝的是 3.7 的版本),若報錯,可以在 /usr/lib 下目錄尋找含有 config 欄位的資料夾的 Python 目錄填入。

如果需要 Python 2 的支援,比如有些老舊的外掛程式仍然只支持 Python 2 但又沒有其它外掛程式可供選擇,則應該加入:

--enable-pythoninterp=yes \
--with-python-config-dir=/usr/lib/python2.7/config \

相應地,你需要提前安裝 Python 2 和 libpython2-dev。需要注意的是如果安裝了 Python 3 的所需檔,卻錯誤地開啟了 enable-pythoninterp 選項,Vim 會因為開啟了 Python 2 支持而找不到 Python 2 相關檔而啟用 Python 失敗。所以,應注意安裝相應的版本,開啟相應的選項。

你或許也注意到了 Ruby 、Perl 和 Lua 的支援選項的開啟,可以相應地進行改動如果確定你不需要這些支援。

prefix 後的目錄指定了 Vim 安裝目標目錄。

如果在執行 ./configure 時得到了一個這樣的錯誤:

no terminal library found
checking for tgetent()… configure: error: NOT FOUND!
You need to install a terminal library; for example ncurses.
Or specify the name of the library with –with-tlib.

解決方案是如錯誤提示所說,安裝 libncurses5-dev 即可。

sudo apt-get install libncurses5-dev

如果 ./configure 一切順利,接下來你只需要執行:

sudo make
sudo make install

註冊 Vim 為 Editor

Debian 下有以下用法可以將 Vim 註冊為 editor :

sudo update-alternatives --install /usr/bin/editor editor /usr/local/vim-8.1/bin/vim 1

使用通用的軟連結鏈上「vim」:

sudo ln -s /usr/local/vim-8.1/bin/vim /usr/bin/vim

這樣一來,在命令列中輸入 vim 即可運行 Vim

這時為了確保 Vim 的 Python 支持如計畫被啟用,以下命令可以進行驗證:

vim --version | grep python

不出意外輸出結果其中有兩項分別為:

-python
+python3

專案前存在加號則表明此項啟用,存在減號即未啟用。所以此處 Python 3 的支持被成功啟用了。

安裝 YouCompleteMe 外掛程式

YouCompleteMe(以下簡稱 YCM)是 Vim 上的一款強大而充滿惡意的自動補全外掛程式。官方倉庫 的 issues 中,其作者 Valloric 不厭其煩地提醒 issues 作者們好好閱讀官方文檔,所以跟著官方的 Installation Instructions 並在碰到坑之後先查閱一番 User Guide 也是接下來我們應堅守的流程。

本文中配置 YCM 的目標是讓其支援 C/C++ 的自動補全,其它語言不在本文討論範圍內。值得一提的是,對於 C Family 的語義自動補全,官方指定一定要閱讀 這份資料

安裝 vim-plug 外掛程式管理器

雖然我們的目標僅僅是安裝 YCM,但為以後 Vim 的使用做考慮,使用外掛程式管理器的極大幫助是不容忽視的。這裡我們選擇的是支援非同步安裝的 Github 上 Star 數目排名第二的 Vim 外掛程式管理器 —— vim-plug

需要下載倉庫中的 plug.vim 檔並將其放入 autoload 目錄中。

autoload 資料夾存在於 ~/.vim 目錄中,兩個目錄若不存在都可以簡單新建得到。

編輯 ~/.vimrc 檔(如果沒有請新建),加入對 YCM 的引用。

Plug 'Valloric/YouCompleteMe'

vim-plug 的使用方法在官方文檔中的 README 中就已經介紹得十分完備了。簡單地說,你可以把上面的那一行配置中單引號間的內容修改為其它外掛程式的位址(按照 「Username/Plugname」 的格式)對外掛程式進行引用。

如果現在對於 Vim 不是很熟悉,可以使用 nano 對 ~/.vimrc 進行修改。

安裝 Clang

對於 C Family 的語義補全,YCM 採用了 Clang 的語義檢索引擎。雖說自帶 libclang 但是文檔中還是給出了自行編譯得到 libclang 的建議。這意味著 Clang 被正確配置在這台電腦上是大前提。

Clang 作為一款基於 LLVM 的編譯器,也需要安裝 LLVM 框架系統。你可以使用軟體源安裝(寫作時最新版本為6.0):

sudo apt-get install clang-6.0

這是最快捷方便的安裝 Clang + LLVM 的方式。如果分別下載源碼編譯安裝,其實也並不繁瑣。當然,LLVM 在 Download Page 也提供了針對不同系統不同發行版本的預編譯包。所以,你也可以把下載下來的預編譯包移動到 /usr/local 也就是 Vim 安裝目錄旁邊。

以下版本號均使用 xxxxxxx 代替,請以實際下載下來的檔案名為准。

sudo mv /path/to/package/clang+llvm_xxxxxxx /usr/local

別忘了連結到 clangclang++

sudo ln -s /usr/local/clang+llvm_xxxxxxx/bin/clang /usr/bin/clang
sudo ln -s /usr/local/clang+llvm_xxxxxxx/bin/clang++ /usr/bin/clang++

至此,Clang 準備完畢。而 libclang 也靜靜地藏在了 /usr/local/clang+llvm_xxxxxxx/x86_64-linux-gnu/lib 裡了。

安裝 Cmake

Cmake 是 YCM 默認支援的編譯工具,所以使用 Cmake 來編譯 YCM 是最安全穩妥的方式。如果這裡嫌麻煩不安裝 Cmake 去編譯 ycm_core,Vim 在啟動後會給出錯誤

The ycmd server SHUT DOWN (restart with ':YcmRestartServer'). Unexpected error while loading the YCM core library.

同時好消息是 Cmake 提供了 Shell 的安裝腳本,在 Download Page 中尋找到自己的平臺下載即可。下載完成後到達腳本所在目錄,移動到 /usr/local ,讓剛安裝的那幾個呆在一起,執行安裝。

sudo mv /path/to/cmake-x.xx.x-Linux-x86_64.sh /usr/local
sudo /usr/local/.cmake-x.xx.x-Linux-x86_64.sh

x.xx.x 指版本號,以下載下來的檔為准。

輸入 y 選擇接受協定並根據提示再次輸入 y 安裝到所在目錄單獨子目錄。

於是,Cmake 準備好了。

使用 vim-plug 安裝 YCM

剛剛僅僅是在 ~/.vimrc 中引用了 YCM ,並沒有真正下載安裝它,現在才是到了編譯安裝 YCM 的時候。YCM 安裝腳本需要 Cmake 生成一些設定檔並自行編譯,所以我們在安裝好 Cmake 後執行安裝腳本會為我們省不少事情。

打開 Vim ,鍵入 : 進入命令模式,輸入 PlugInstall,回車確認。此時 vim-plug 開始通過 Git 獲取每一個外掛程式,並妥善處理安裝目錄。目前只引用了一個外掛程式,所以任務列表中應該只有一項 YouCompleteMe 的安裝。

YCM 是較為複雜的 Vim 外掛程式,所以下載下來之後有自己獨特的從 Github 獲取依賴包的過程,這需要一定的時間。

執行安裝腳本並加入 clang-completer 參數

這一步是向 YCM 添加對於 C-Family 的語義補全支持中的重要一步。所以需要做的是在它的目錄下執行 install.sh 加入 --clang-completer 參數:

cd ~/.vim/plugged/YouCompleteMe
./install.sh --clang-completer

相應的存在 --js-completer, --java-completer--rust-completer 等參數,可以視需要添加。

如果流覽了一遍 YCM 的目錄,你或許會發現有一個 install.py 的 Python 腳本。所以如果想使用這個腳本,這也是可行的選擇。

cd ~/.vim/plugged/YouCompleteMe
python3 install.py --clang-completer

如果你使用 vundle 外掛程式管理器,YCM 的安裝目錄應該在 ~./vim/bundle 下,而非 vim-plug 指定的 ~/.vim/plugged

編譯 ycm_core

理論上執行了上一步就已經完成了 YCM 的安裝,但是此時啟動 Vim 可能仍會得到來自 YCM 的若干錯誤。其中,它會對尋找 Python 的運行庫有不小的困難。

這裡 YCM 給出的錯誤在網路上有多種形式,以「無法載入種種 Python 模組」一類居多。

別忘了還要讓 YCM 使用我們剛剛裝好的 libclang 。所以編譯 ycm_core 加入提供 Python 所在目錄的相關參數的同時,順便加入 -DEXTERNAL_LIBCLANG_PATH

cmake -G "Unix Makefiles" ~/.vim/plugged/YouCompleteMe/third_party/ycmd/cpp/ \
    -DUSE_SYSTEM_BOOST=ON \
    -DEXTERNAL_LIBCLANG_PATH=/usr/local/clang+llvm-xxxxxxx/lib/libclang.so \
    -DPYTHON_LIBRARY=/usr/lib/python3.7 \
    -DPYTHON_INCLUDE_DIR=/usr/include/python3.7 \
    -DUSE_PYTHON2=OFF

LIBCLANG_PATH 指的是 libclang.so 檔所在位置,這取決於前面對 Clang 的安裝所選擇的目錄。

PYTHON_LIBRARYPYTHON_INCLUDE_DIR 則與 Python 版本號(此處是3.7)或安裝目錄相關。

特別值得注意的是,YCM 此處的 Makefile 默認使用 Python 2 編譯,所以如果你沒有安裝 Python 2 而且設定的 Python 的運行庫和標頭檔目錄是 Python 3 的目錄,會得到報錯:

You set USE_PYTHON2 to make CMake find python2 libs only, but CMake found python3 libs instead. Either don't set USE_PYTHON2 or install the necessary python2 headers.

解決方案是正如所給的參考參數中最後一行在 Cmake 命令後再添加一行 -DUSE_PYTHON2=OFF 。當然,如果從頭你就是用 Python 2 進行操作的,就應該把這行去掉,直接執行命令。

指定 .ycmextraconf.py

此時使用 Vim 打開一個 C 檔,有一定的可能還會看到這樣的一條錯誤,同樣來自 YCM:

No .ycm_extra_conf.py file detected, so no compile flags are available. Thus no semantic support for C/C++/ObjC/ObjC++. See the docs for details.

深呼吸,這個問題在 YCM 的 倉庫 issues 列表以各種描述形式存在。這是由於 YCM 找不到最為關鍵的 C-Family 自動補全的設定檔導致的。實際上,這個 ycm_extra_conf.py 檔位置是在這個藏得很深的目錄之下的。

~/.vim/plugged/YouCompleteMe/third_party/ycmd/cpp/ycm

~/.vimrc 中指定它所在的位置即可

let g:ycm_global_ycm_extra_conf = '~/.vim/plugged/YouCompleteMe/third_party/ycmd/cpp/ycm/.ycm_extra_conf.py' 

有人也選擇把 ycm_extra_conf.py 檔從深處的目錄中拷貝出來,到 YCM 主目錄較為淺層的地方,然後再修改 g:ycm_global_ycm_extra_conf 變數。

更進一步

如果不出意外,安裝應該是順利完成。至此,我敘述完畢了安裝 Vim 和 YouCompleteMe 外掛程式的流程。除去 issues 中一些奇怪的問題,本文基本覆蓋了經典的坑。

進一步的配置不是本文所涉及的內容,所以在這裡推薦大家閱讀:

最重要的是,不在調優工具上花費太多的時間,趕緊熟悉 Vim 的鍵位,儘快地將工具投入生產才是硬道理。

感謝閱讀 💗