CentOS7 安装VIM8+YouCompleteMe

1. 准备工作

笔者主要是为了在CentOS7环境下给vim安装YouCompletteMe插件。这个插件需要的安装环境很恶心,号称是vim最难安装的插件。下面是它的几点要求。

  1. 必须是Vim 7.4.1578以上的版本,CentOS7 通过yum install vim安装的最高版本恰恰不满足要求,所以我们直接安装VIM8 。
  2. vim必须支持pyhon2或python3,由于CentOS7python默认安装版本是2.7版本,由于笔者主要在Linux下开发C/C++程序,所以Python环境就直接利用默认环境。
  3. 编译YouCompleteMe 需要用到CMake,yum install cmake命令安装的版本太低,我们直接通过源码安装最新的CMake版本。
    下面我们开始一步一步进行。

2. 必备组件 的安装

yum install -y gcc gcc-c++ ruby ruby-devel lua lua-devel  \
    ctags git python python-devel \
    tcl-devel ncurses-devel \
    perl perl-devel perl-ExtUtils-ParseXS \
    perl-ExtUtils-CBuilder \
    perl-ExtUtils-Embed

3. 通过yum直接升级vim8

rpm -Uvh http://mirror.ghettoforge.org/distributions/gf/gf-release-latest.gf.el7.noarch.rpm
rpm --import http://mirror.ghettoforge.org/distributions/gf/RPM-GPG-KEY-gf.el7
yum -y remove vim-minimal vim-common vim-enhanced sudo
yum -y --enablerepo=gf-plus install vim-enhanced sudo

直接运行vim --version 可以见到以下版本信息,就证明vim8以安装成功

VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Sep 18 2016 14:42:40)
包含补丁: 1-3
修改者 
编译者 
巨型版本 无图形界面。  可使用(+)与不可使用(-)的功能:
+acl             +file_in_path    +mouse_sgr       +tag_old_static
+arabic          +find_in_path    -mouse_sysmouse  -tag_any_white
+autocmd         +float           +mouse_urxvt     -tcl
-balloon_eval    +folding         +mouse_xterm     +termguicolors
-browse          -footer          +multi_byte      +terminfo
++builtin_terms  +fork()          +multi_lang      +termresponse
+byte_offset     +gettext         -mzscheme        +textobjects
+channel         -hangul_input    +netbeans_intg   +timers
+cindent         +iconv           +num64           +title
-clientserver    +insert_expand   +packages        -toolbar
-clipboard       +job             +path_extra      +user_commands
+cmdline_compl   +jumplist        +perl/dyn        +vertsplit
+cmdline_hist    +keymap          +persistent_undo +virtualedit
+cmdline_info    +lambda          +postscript      +visual
+comments        +langmap         +printer         +visualextra
+conceal         +libcall         +profile         +viminfo
+cryptv          +linebreak       +python/dyn      +vreplace
+cscope          +lispindent      -python3         +wildignore
+cursorbind      +listcmds        +quickfix        +wildmenu
+cursorshape     +localmap        +reltime         +windows
+dialog_con      +lua/dyn         +rightleft       +writebackup
+diff            +menu            +ruby/dyn        -X11
+digraphs        +mksession       +scrollbind      -xfontset
-dnd             +modify_fname    +signs           -xim
-ebcdic          +mouse           +smartindent     -xpm
+emacs_tags      -mouseshape      +startuptime     -xsmp
+eval            +mouse_dec       +statusline      -xterm_clipboard
+ex_extra        +mouse_gpm       -sun_workshop    -xterm_save
+extra_search    -mouse_jsbterm   +syntax
+farsi           +mouse_netterm   +tag_binary
     系统 vimrc 文件: "/etc/vimrc"
     用户 vimrc 文件: "$HOME/.vimrc"
 第二用户 vimrc 文件: "~/.vim/vimrc"
      用户 exrc 文件: "$HOME/.exrc"
       defaults file: "$VIMRUNTIME/defaults.vim"
         $VIM 预设值: "/etc"
  $VIMRUNTIME 预设值: "/usr/share/vim/vim80"
编译方式: gcc -c -I. -Iproto -DHAVE_CONFIG_H     -O2 -g -pipe -Wall -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches   -m64 -mtune=generic -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1
链接方式: gcc   -L. -Wl,-z,relro -fstack-protector -rdynamic -Wl,-export-dynamic -Wl,--enable-new-dtags -Wl,-rpath,/usr/lib64/perl5/CORE  -Wl,-z,relro  -L/usr/local/lib -Wl,--as-needed -o vim        -lm -lnsl  -lselinux  -lncurses -lacl -lattr -lgpm -ldl   -Wl,--enable-new-dtags -Wl,-rpath,/usr/lib64/perl5/CORE  -fstack-protector  -L/usr/lib64/perl5/CORE -lperl -lresolv -lnsl -ldl -lm -lcrypt -lutil -lpthread -lc

4. 安装YouCompleteMe

4.1 安装vim插件管理器Vundle

git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim

打开用户目录下的vim资源配置文件
vim ~/.vimrc
然后将下列信息添加到文件中

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 'Valloric/YouCompleteMe'

" All of your Plugins must be added before the following line
call vundle#end()            " required
filetype plugin indent on    " required
" To ignore plugin indent changes, instead use:
"filetype plugin on
"
" Brief help
" :PluginList       - lists configured plugins
" :PluginInstall    - installs plugins; append `!` to update or just :PluginUpdate
" :PluginSearch foo - searches for foo; append `!` to refresh local cache
" :PluginClean      - confirms removal of unused plugins; append `!` to auto-approve removal
"
" see :h vundle for more details or wiki for FAQ
" Put your non-Plugin stuff after this line

安装方法一:
重启vim在命令行模式下输入PluginInstall,vim将会自动下载所需要的插件并且安装。
过程巨慢,建议在凌晨采用此方式安装
安装方法二:
如果实在是等不及,那就直接git 拉取,后再运行PluginInstall

 cd ~/.vim/bundle/
git clone https://github.com/Valloric/YouCompleteMe.git

下载完YouCompleteMe,还不算完,它需要编译和安装!!!!
下面我们进行编译ycm的准备工作。

4.2 安装CMake

通过源码进行CMake安装
访问https://cmake.org/download/,然后选取3以上的版本,我选择的是最新版


然后通过wget 拉取后安装,操作如下

wget https://github.com/Kitware/CMake/releases/download/v3.15.0-rc1/cmake-3.15.0-rc1.tar.gz
tar zxvf cmake-3.15.0-rc1.tar.gz
cd cmake-3.15.0-rc1
./bootstrap && make && make install

安装好后 ,运行cmake --version ,如果出现下面的版本信息,证明已正确安装。

cmake version 3.15.0-rc1
CMake suite maintained and supported by Kitware (kitware.com/cmake).

4.3 编译YouCompleteMe

  1. 将third_party中内部依赖文件克隆下来
git submodule update --init --recursive

如果你跳过此部直接运行编译脚本,也会提示你运行此命令。

  1. 然后进入到YouCompleteMe,运行编译脚本
cd ~/.vim/bundle/YouCompleteMe/
./install.py --clang-completer

如果使用--clang-completer选项,脚本会判断当前是否有upstream pre-build libclang.so库,如果在缓存位置有,则直接使用缓存位置的包,如果没有则下载。但是下载基本上不成功。然后就会出现以下报错:

-- The C compiler identification is GNU 4.8.5
-- The CXX compiler identification is GNU 4.8.5
-- Check for working C compiler: /bin/cc
-- Check for working C compiler: /bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /bin/c++
-- Check for working CXX compiler: /bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found PythonLibs: /usr/lib64/python2.7/config/libpython2.7.so (found suitable version "2.7.5", minimum required is "2.7")
-- Downloading libclang 8.0.0 from https://dl.bintray.com/micbou/libclang/libclang-8.0.0-x86_64-unknown-linux-gnu.tar.bz2
CMake Error at ycm/CMakeLists.txt:107 (file):
  file DOWNLOAD HASH mismatch

    for file: [/home/hugifish/.vim/bundle/YouCompleteMe/third_party/ycmd/cpp/../clang_archives/libclang-8.0.0-x86_64-unknown-linux-gnu.tar.bz2]
      expected hash: [e81a186cd1180ae80c17d67d8d0c101248f8ee032d138cf6f1e95001e733249c]
        actual hash: [e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855]
             status: [1;"Unsupported protocol"]



CMake Error at ycm/CMakeLists.txt:123 (message):
  Cannot find path to libclang in prebuilt binaries


-- Configuring incomplete, errors occurred!
See also "/tmp/ycm_build_jaT6wf/CMakeFiles/CMakeOutput.log".
Searching Python 2.7 libraries...
Found Python library: /usr/lib64/python2.7/config/libpython2.7.so
Found Python headers folder: /usr/include/python2.7
ERROR: the build failed.

NOTE: it is *highly* unlikely that this is a bug but rather
that this is a problem with the configuration of your system
or a missing dependency. Please carefully read CONTRIBUTING.md
and if you're sure that it is a bug, please raise an issue on the
issue tracker, including the entire output of this script
and the invocation line used to run it.

从报错信息中,我们下载https://dl.bintray.com/micbou/libclang/libclang-8.0.0-x86_64-unknown-linux-gnu.tar.bz2注意此处因版本而异,注意看你的报错信息
进入到缓存文件夹,下载此文件即可

cd ~/.vim/bundle/YouCompleteMe/third_party/ycmd/clang_archives
rm libclang-8.0.0-x86_64-unknown-linux-gnu.tar.bz2
wget https://dl.bintray.com/micbou/libclang/libclang-8.0.0-x86_64-unknown-linux-gnu.tar.bz2
cd ~/.vim/bundle/YouCompleteMe
./install.py --clang-completer

大功告成,此时,你打开vim,就会有少部分提示。
虽然YouCompleteMe安装时比较恶心,但是安装后用起来真的是很爽,功能很强大,为了让未来应用更加的顺畅丝滑,我们来配置一些简要的功能。

4.4 配置YouCompleteMe

打开vim资源配置文件,追加以下内容

let g:ycm_global_ycm_extra_conf='~/.ycm_extra_conf.py'  "设置全局配置文件的路径
let g:ycm_seed_identifiers_with_syntax=1    " 语法关键字补全
let g:ycm_confirm_extra_conf=0  " 打开vim时不再询问是否加载ycm_extra_conf.py配置
let g:ycm_key_invoke_completion = '' " ctrl + a 触发补全,防止与其他插件冲突
set completeopt=longest,menu    "让Vim的补全菜单行为与一般IDE一致(参考VimTip1228)
nnoremap jd :YcmCompleter GoToDefinitionElseDeclaration "定义跳转快捷键

这里需要注意的是.ycm_extra_conf.py,从哪里来的呢,YCM带了一些模版,我们可以在文件夹~/.vim/bundle/YouCompleteMe/third_party/ycmd/examples中找到

拷贝到用户根目录下
cp ~/.vim/bundle/YouCompleteMe/third_party/ycmd/examples/.ycm_extra_conf.py ~/

你在.ycm_extra_conf.py中看到以下片段

flags = [
'-Wall',
'-Wextra',
'-Werror',
'-fexceptions',
'-DNDEBUG',
# THIS IS IMPORTANT! Without a "-std=" flag, clang won't know which
# language to use when compiling headers. So it will guess. Badly. So C++
# headers will be compiled as C headers. You don't want that so ALWAYS specify
# a "-std=".
# For a C project, you would set this to something like 'c99' instead of
# 'c++11'.
'-std=c++11',
# ...and the same thing goes for the magic -x option which specifies the
# language that the files to be compiled are written in. This is mostly
# relevant for c++ headers.
# For a C project, you would set this to 'c' instead of 'c++'.
'-x',
'c++',
'-isystem',
'/usr/include',
'-isystem',
'/usr/local/include',
'-isystem',
'/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1',
'-isystem',
'/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include',
]

flags就是一个头文件搜索列表,实际上是和gcc/g++搜索标准库头文件是一致的。所以我们只需要知道gcc/g++的搜索路径配置,然后替换到这里,即可。在例子中的配置,很显然是mac系统下的配置。
我们可以通过下面的命令查找到我们所需要的头文件搜索配置

`gcc -print-prog-name=cc1` -v
`g++ -print-prog-name=cc1plus` -v

在笔者的系统下显示的是如下信息

$ `g++ -print-prog-name=cc1plus` -v
忽略不存在的目录“/usr/lib/gcc/x86_64-redhat-linux/4.8.5/include-fixed”
忽略不存在的目录“/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../x86_64-redhat-linux/include”
#include "..." 搜索从这里开始:
#include <...> 搜索从这里开始:
 /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5
 /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/x86_64-redhat-linux
 /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/backward
 /usr/lib/gcc/x86_64-redhat-linux/4.8.5/include
 /usr/local/include
 /usr/include
搜索列表结束。

实际上对应的搜索目录就是

/usr/include/c++/4.8.5
 /usr/include/c++/4.8.5/x86_64-redhat-linux
 /usr/include/c++/4.8.5/backward
 /usr/lib/gcc/x86_64-redhat-linux/4.8.5/include
 /usr/local/include
 /usr/include

我们就可以根据其搜索的目录及顺序编写自己的ycm配置,如下

flags = [
'-Wall',
'-Wextra',
'-Werror',
'-fexceptions',
'-DNDEBUG',
# THIS IS IMPORTANT! Without a "-std=" flag, clang won't know which
# language to use when compiling headers. So it will guess. Badly. So C++
# headers will be compiled as C headers. You don't want that so ALWAYS specify
# a "-std=".
# For a C project, you would set this to something like 'c99' instead of
# 'c++11'.
'-std=c++11',
# ...and the same thing goes for the magic -x option which specifies the
# language that the files to be compiled are written in. This is mostly
# relevant for c++ headers.
# For a C project, you would set this to 'c' instead of 'c++'.
'-x',
'c++',
'-isystem',
'/usr/include/c++/4.8.5',
'-isystem',
'/usr/include/c++/4.8.5/x86_64-redhat-linux',
'-isystem',
'/usr/include/c++/4.8.5/backward',
'-isystem',
'/usr/local/include',
'-isystem',
'/usr/include'
]

-std:表示应用的版本如果是C项目,就需要将那一行修改为-std=c99
-x下面是对应的参数配置
'c++'表示的是C++项目
-isystem 下面是系统搜索目录
-I 下面配置的是自己的工程目录
例如,我在编写C工程,那么我的搜索路径就会这样配置
‘-std=c99’,
'-x',
'c',
'-isystem',
'/usr/include', <===假设C头文件都在这个目录
'-I',
'/home/hugifish/myProj' <==我自己的工程目录

下面我们就可以通过vim使用YCM了,根据我们配置的快捷键

  1. 键可以联想补全
  2. 将光标停留在希望查看的类型或者函数上,同时按住 +j+d ,则可以跳转到定义。
  3. 如果需要回到上一个光标的位置 ctrl + o
    这是一些比较基本的操作,如果需要更多的设置,直接移步https://github.com/Valloric/YouCompleteMe 查看更多配置和用法
    在上面我们提到ycm_extra_conf.py中可以添加自己的工程的搜索路径,我们可以直接在全局的配置中添加,但是如果我们有多个项目,每次都修改全局配置,flags列表就会越来越长,头文件搜索目录也会越来越多,这样直接影响到YCM的工作效率。

4.5 项目自定义.ycm_extra_conf.py

为了避免拖慢YCM效率,我们需要为每一个项目设置头文件搜索列表。
为项目配置独占的YCM配置文件主要有以下两种方法

4.5.1 手动拷贝

YCM配置文件的查找顺序是,当前目录》上层目录》... 》根目录》YCM全局目录,所以当我们安装好YCM后没有配置.ycm_extra_conf.py,打开vim时最下边会有一行红色的小字,提示你确认YCM配置文件是否可用。
将YCM全局配置文件,拷贝到项目的根目录,然后将项目根目录以-I的形式添加到flags列表中,这样我们就可以对自定义头文件进行联想补全了。

4.5.2自动生成配置文件插件

Github中有一个项目可以自动生成独占YCM配置文件。
https://github.com/rdnetto/YCM-Generator
使用方法很简单,直接在.vimrc 中加入Plugin 'rdnetto/YCM-Generator'
然后重启VIM后运行:PluginInstall
使用:

~/.vim/bundle/YCM-Generator/config_gen.py  ${你的工程根目录}

当你创建一个空的工程目录后,然后运行,你会发现出错了,报错信息如下:

ERROR: Unknown build system

进入到python 文件里,你会发现有以下几行代码

....
206     if build_system is None:
207         if os.path.exists(os.path.join(project_dir, "CMakeLists.txt")):
208             build_system = "cmake"
209         elif os.path.exists(os.path.join(project_dir, "configure")):
210             build_system = "autotools"
211         elif pro_files:
212             build_system = "qmake"
213         elif any([os.path.exists(os.path.join(project_dir, x)) for x in ["GNUmakefile", "makefile", "Makefile"]]):
214             build_system = "make"
....
333     else:
334         print("ERROR: Unknown build system")
335         sys.exit(2)
....

由上述代码中你可以看到,这个插件是根据你的编译配置文件来生成工程应用列表的,所以你运行此代码之前需要编写自己的编译配置文件,如makefile等。
这种方法相对麻烦,只有存在复杂的目录包含结构时,才会应用,比如说在一些开源代码的基础上进行二次开发,因为一般的开源代码都会提供编译配置文件。
由于此插件的可执行脚本在比较深的文件加,所以你可以编写一个可执行脚本,刷新YCM配置文件。

#!/usr/bash
#filename refreshYCM.sh
myPath="test" #你的工程目录
while :
do
  ~/.vim/bundle/YCM-Generator/config_gen.py ${myPath}
 sleep 10
done

$nohup ./refreshYCM.sh &
这样就可以每5秒钟自动更新一遍配置文件,不过一定要记得不用时,将其干掉。


结束语

vim是一个让你既爱又恨的工具,它很强大,但是也时不时的恶心你一下,作为计算机学科的初学者我建议你用可视化工具,如果你想脱离菜鸟的行列,你就必须掌握一些看似简陋但发展无限的工具,比如vim,gdb等等,在打磨工具的过程中也算是一种磨练,痛苦并快乐着。
本文很基础,后续会根据所需对设置进行扩充,未完待续...

你可能感兴趣的:(CentOS7 安装VIM8+YouCompleteMe)