1. 准备工作
笔者主要是为了在CentOS7环境下给vim安装YouCompletteMe插件。这个插件需要的安装环境很恶心,号称是vim最难安装的插件。下面是它的几点要求。
- 必须是Vim 7.4.1578以上的版本,CentOS7 通过yum install vim安装的最高版本恰恰不满足要求,所以我们直接安装VIM8 。
- vim必须支持pyhon2或python3,由于CentOS7python默认安装版本是2.7版本,由于笔者主要在Linux下开发C/C++程序,所以Python环境就直接利用默认环境。
- 编译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
- 将third_party中内部依赖文件克隆下来
git submodule update --init --recursive
如果你跳过此部直接运行编译脚本,也会提示你运行此命令。
- 然后进入到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了,根据我们配置的快捷键
键可以联想补全 - 将光标停留在希望查看的类型或者函数上,同时按住 +j+d ,则可以跳转到定义。
- 如果需要回到上一个光标的位置 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等等,在打磨工具的过程中也算是一种磨练,痛苦并快乐着。
本文很基础,后续会根据所需对设置进行扩充,未完待续...