Vim Plugin: YouCompleteMe 旧版本装配

YouCompleteMe 是 Vim 比较常用的一款代码补全插件, 在 neovim 盛行的当下, 这类补全插件也逐渐淡出了大众视野, 但也有一些场合使用 YouCompleteMe 也有自己的一席之地。

为了开发环境的稳定性, 有些服务器的操作系统版本比较低, 甚至在 CMake 这类编译工具的版本也比较低。 为了尽可能减少对低版本系统环境的更改, 我尝试尽可能通过手动编译配置的方式完成在这类开发环境的 Vim 配置。

其实无奈的是自己没有账户的 sudo 权限。

我选择的是 YCM 的 legacy-c++11 版本, 还未升级到 C++17 因而对编译工具的要求会低一些。 官方在 Ubuntu 20.04 上做过适配是比较成功的, 但我在 Ubuntu 18.04 上也成功安装了。 我的装配环境如下:

  • Ubuntu 18.04
  • GCC v7.5.0
  • CMake v3.10.2
  • Python 3.6.7
  • Vim 8.2.1258
  • YCM legacy-c++11

如果是最新的 YCM 版本, GCC 至少需要 v8.x, Clang 版本需要 v7.x。

0. 编译环境

CMake 和 build-essential 最好能用 apt 的方式装好了, 不然得手动去装会很麻烦。 另外, 如果需要自己手动编译安装 python3, 那 python3-dev 也不是特别必要。

# Ubuntu 16.04 and later
sudo apt-get install build-essential cmake python3-dev

1. Python3.6 安装

安装 Python3.6 的原因是这台服务器的 python3 在安装的时候没有支持 --enable-shared--enable-framework, 另外也是本着不破坏原有编译环境的想法。 最重要的是 Requirements 明确声明了 python 3.6 runtime。

到 python 官网的 https://www.python.org/ftp/python/3.6.7/ 找一找 Python-3.6.7.tar.xz, 用 wget 直接下载到自己的 home 目录下。

tar zxvf Python-3.6.7.tgz
cd Python-3.6.7
./configure --prefix=${HOME}/.local/python3.6 --enable-optimizations --enable-shared
make -j$(nproc)
make install

然后更改 .bashrc 增添相关的执行文件目录就行了。

# .bashrc
export PATH=${PATH}:${HOME}/.local/python3.6/bin

2. LLVM 安装

方便一些直接用 LLVM + Clang 的组合包, 省去了自己编译的麻烦事儿。 我选择的版本是 LLVM 12.0.0, 因为后续在安装 YCM 的时候 10.0.0 版本已经太老给删掉了, 找个稍微接近的新版本是可以平替的。

# wget 不成功直接去 github 的 release 版面下载
wget https://github.com/ycm-core/llvm/releases/download/12.0.0/clang+llvm-12.0.0-x86_64-unknown-linux-gnu.tar.xz
xz -d clang+llvm-12.0.0-x86_64-unknown-linux-gnu.tar.xz
tar -xvf clang+llvm-12.0.0-x86_64-unknown-linux-gnu.tar

解压完之后就配置 .bashrc 即可, 记得 source ~/.bashrc

# .bashrc
export LLVM_PATH=${HOME}/clang+llvm-12.0.0-x86_64-unknown-linux-gnu/bin
export PATH=${PATH}:LLVM_PATH

3. Vim 安装

一般来说 Ubuntu 18.04 默认安装的 Vim 版本是 8.0 的, 而 YCM 的要求是 Vim v8.1.2269 huge build, compiled with Python 3.6 support, 所以不妨手动装个稍微高点的版本。

wget https://codeload.github.com/vim/vim/tar.gz/v8.2.1258
mv v8.2.1258  vim-v8.2.1258.tar.gz
tar -xvzf vim-v8.2.1258.tar.gz
cd vim-8.2.1258
./configure --prefix=${HOME}/.local\
        --with-python3-command=${HOME}/.local/python3.6/bin/python3\
        --enable-python3interp=dynamic\
        --enable-cscope\
        --with-features=huge\
        --enable-multibyte\
        --with-python3-config-dir=${HOME}/.local/python3.6/lib/python3.6/config-3.6m-x86_64-linux-gnu/\
        --enable-largefile\
        --enable-fail-if-missing
make -j$(nproc)
make install

这里需要注意的是 --enable-python3interp=dynamic 选项, 很多编译 vim 都跟你说要填 yes, 然后用 LDFLAG='-rdynamic' 开启相关的 dynamic 编译, 我试过并没有起作用。 安装完之后可以用如下代码检查是否有 +python3/dyn 的支持用以确认安装是否成功。 python3/dyn 也是 YCM 的安装要求之一, 并且仅支持 python3 版本, YCM 已经抛弃了对 python2 的支持, 除非切换到更老旧的对 python2 支持的 branch。

vim --version | grep python3

4. YouCompleteMe 安装

  • Vundle
git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim
  • 直接拷贝 legacy-c++11 分支版本的 YCM
cd ~/.vim/bundle
git clone --branch legacy-c++11 https://github.com/ycm-core/YouCompleteMe.git
cd ~/.vim/bundle/YouCompleteMe
git submodule update --init --recursive

到这一步应该会说在 ~/.vim/bundle/YouCompleteMe/third_party/ycmd/third_party/watchdog_deps/pathtools/docs/source/_themes 下载不成功, 因为人家已经删掉了。

cd ~/.vim/bundle/YouCompleteMe/third_party/ycmd/third_party/watchdog_deps/pathtools/docs/source/
rmdir _themes
git clone https://github.com/pallets/flask-sphinx-themes.git _themes
checkout THE_VERSION_THAT_ASKS
  • 安装 YCM 的 Clang Completer
cd ~/.vim/bundle/YouCompleteMe
python3.6 install.py --clangd-completer

然后又会遇到麻烦了, 说 clangd-10.0.0 这个包的 checksum 不对, 实际上是这个下载地址已经寄了, 那没办法了, 自己手动下载一个吧, 对于这个老的 YCM 版本下载的位置是相应的 third_party 的包的 cache 目录, 并不是传闻的 clang_archives。 为了和前述的 LLVM 的版本匹配我们也装 clangd 12.0.0 版本, 但需要改一下 build.py 的一些内容。

# cd ~/.vim/bundle/YouCompleteMe/third_party/ycmd/build.py
CLANGD_VERSION = '12.0.0'
...

def DownloadClangd( printer ):
  CLANGD_DIR = p.join( DIR_OF_THIRD_PARTY, 'clangd', )
  CLANGD_CACHE_DIR = p.join( CLANGD_DIR, 'cache' )
  CLANGD_OUTPUT_DIR = p.join( CLANGD_DIR, 'output' )

  target = GetClangdTarget()
  target_name, check_sum = target[ not IS_64BIT ]
  target_name = target_name.format( version = CLANGD_VERSION )
  file_name = '{}.tar.bz2'.format( target_name )
  download_url = 'https://github.com/ycm-core/llvm/releases?q={}/{}'.format( CLANGD_VERSION, file_name )

  file_name = p.join( CLANGD_CACHE_DIR, file_name )

  MakeCleanDirectory( CLANGD_OUTPUT_DIR )

  if not p.exists( CLANGD_CACHE_DIR ):
    os.makedirs( CLANGD_CACHE_DIR )
#  elif p.exists( file_name ) and not CheckFileIntegrity( file_name, check_sum ):
#    printer( 'Cached Clangd archive does not match checksum. Removing...' )
#    os.remove( file_name )
    ...

这里我改掉了 CLANGD_VERSION 以及下载的文件地址和文件名, 另外注释掉了 Checksum 的检查。 一般来说这样也是能下载成功了, 要是还不行就手动给它整完。

cd ~/.vim/bundle/YouCompleteMe/third_party/ycmd/third_party/clangd/cache
wget https://github.com/ycm-core/llvm/releases/download/12.0.0/clangd-12.0.0-x86_64-unknown-linux-gnu.tar.bz2

5. .vimrc 配置

  • 拷贝一下 YCM 的配置文件
cp ~/.vim/bundle/YouCompleteMe/.ycm_extra_conf.py ~/.vim
  • 在 home 目录下创建 .vimrc 文件向其中写入以下内容, 关掉 vim 重启之后应该就自动帮你装好了 Vundle 和 YouCompleteMe, 或者用 vim 命令 :PluginInstall 手动安装一下。
" Vundle
set nocompatible        " be iMproved, required
filetype off            " required

" set the runtime path to include Vundle and initialize
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
" alternatively, pass a path where Vundle should install plugins
"call vundle#begin('~/some/path/here')

" let Vundle manage Vundle, required
Plugin 'VundleVim/Vundle.vim'
Plugin 'ycm-core/YouCompleteMe'

" All of your Plugins must be added before the following line
call vundle#end()            " required
filetype plugin indent on    " required

let g:syntastic_python_python_exec = '${HOME}/.local/python3.6/bin/python3'·
let g:ycm_server_python_interpreter='${HOME}/.local/python3.6/bin/python3'
let g:ycm_python_sys_path = '${HOME}/.local/python3.6/lib/python3.6'
let g:ycm_global_ycm_extra_conf='~/.vim/.ycm_extra_conf.py'
关于 YCM 的配置

喜欢折腾的同学肯定不想装完 YCM 就完事儿了, 把它调教成一键趁手的工具才是我们安装这个插件的初心, 这里推荐几篇还不错的配置文档供大家参阅。 我自己也配置了一份精简版的, 可参阅 HangX-Ma/dotfiles: vim/.vimrc.