废话

生命在于折腾。

之前不用这个插件的原因:

  • 因为要使这个插件起作用,前前后后需要下载几百MB(win下更是超过了1GB)的东西,包括了Clang编译器,ycmd的c艹源码还有ycm本身的vim script,也就是说我安装这个插件比一个IDE的体积还大。

  • 另外一个原因就是就是Windows下使用安装插件及其麻烦,这样的话就有可能无法保持相同体验,还不如不要算了。

现在为什么使用呢?第一句话。

熟悉之后感觉前面的折腾还是非常值得的,体验接近ide了,ycm不仅提供了语义级别的智能补全,还提供了函数定义跳转,而所有这些都是非常迅速不会导致vim变卡。

编译流程


主要参考官方wiki中的这一部分Instructions for 64-bit using MinGW64 clang

这短短的几句话忽略了大量的细节,如果是新手的话相信是很难搞得定的。所以我来细化它。

编译环境——MSYS2


MSYS2是作为MinGw的替代者出现的,它的出现可以说结束了Windows下模拟Linux环境混乱的局面,它移植来自Arch Linux中强大的包管理器:pacman。我们通过pacman来安装其它东西,比如说MinGw(目的在于提供编译WIndows本地程序的工具集),git(我们再也不需要装一个msysgit然后再装一个MinGw了)。

这是一篇较为详细的对比:Cygwin 与 MinGW/MSYS/MSYS2,如何选择?

官方对比How does MSYS2 differ from Cygwin

Cygwin的话,我的理解,它提供接口更加兼容POSIX,在win api和应用之间加了一层兼容层(cygwin1.dll,所以由Cygwin的gcc编译出来的应用程序在效率是输给MinGw)的,所以在win下编译unix下开源软件,首选是MinGw,你可以看到好多IDE(CodeBlock,QT等)其实包含了MinGW。

官网:msys2,下载对应平台的exe安装好之后,在开始菜单打开MSYS2 Shell,你还会发现另外两个快捷方式MinGW-W64 win64 ShellMinGW-W64 win32 Shell,不过现在它们还打不开。

$ pacman --needed -Sy bash pacman pacman-mirrors msys2-runtime

执行完毕之后,关闭Shell,重新打开。

$ pacman -Su #更新其它组件到最新..

关闭重打开,更换pacman的源。

$ cd /etc/pacman.d
$ gvim -p mirrorlist.mingw32 mirrorlist.mingw64 mirrorlist.msys #你在文件浏览器打开这个路径然后用其它编辑器,这里只是示意而已.

然后在这三个文件最开头分别添加一行(按照上面的顺序)

Server = http://mirrors.ustc.edu.cn/msys2/REPOS/MINGW/i686

Server = http://mirrors.ustc.edu.cn/msys2/REPOS/MINGW/x86_64

Server = http://mirrors.ustc.edu.cn/msys2/REPOS/MSYS2/$arch

# 安装以下东西..
pacman -Sy
pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-gdb mingw-w64-x86_64-make tmux zsh git mingw64/mingw-w64-x86_64-cmake winpty-git

解释下,第一个是编译器,第二个是调试器,第三个工程管理工具make,后面两个是文本三巨头之二,在后来是版本管理神器,cmake则是很受欢迎的新一代工程管理工具也是我们编译YCM需要的工具,最后一个是解决mintty下有些工具卡死没有输出的情况的工具。

# winpty使用示例,这里直接调用python会卡死..
$ winpty python

mingw-w64相关默认安装/mingw64下,所以在MSYS2 Shell下默认找不到gcc命令的,你可以将相关路径添加到诸如/etc/profile.bashrc.zshrc这样的文件中,也可以在win下面改Path变量。

但更直接的方式在打开前面提到的快捷方式MinGW-W64 win64 Shell,注意别看错打开win32的shell了。

pacman的基本使用

# 安装新包
pacman -S <package_names|package_groups>
# 移除包
pacman -R <package_names|package_groups>
# 搜索包,支持正则搜索
pacman -Ss <name_pattern>

编译一个64位的gvim/vim (非必须,你可以直接到官网下载安装即可,我有点强迫症,想保证两者 都是64位的)


打开MinGW-W64 win64 Shell

VIM官网只提供了32位的程序,按照上面的wiki我们需要编译一个带有python2特性的64位vim好来验证我们是否安装成功了。

这里可以使用我的编译脚本和vim配置,从github上脱下之后,里面有一个build_vim.sh脚本用于编译vim。

$ git clone https://github.com/tracyone/vim vim_conf && cd vim_conf

在执行这个脚本之前你需要,你需要编辑这个脚本最开头宏定义,里面定义诸如安装路径,python安装路径,架构等..

其中有python2,python3,ruby,lua,tcl,perl等外部接口支持,注意把不需要的接口对应的变量注释掉,否则会编译失败

去官网下载最新python2,并加入Path变量,然后安装,然后修改下面几个变量

# python2 support
PYTHON=/e/program_files/Python27
DYNAMIC_PYTHON=yes
PYTHON_VER=27
$ ./build_vim.sh all

上面那条命令会下载vim源代码(接近800MB),并编译gvim和vim最终打开文件管理器,你只需要双击install.exe然后再弹出的界面中输入d就能完成最后的安装了。另外,也拷贝了我的vimrc到vim安装目录下。所以首次打开时会自动安装插件,请确保网络通畅,由于需要安装较多插件(并且包含了接近200MB的YCM插件),请非常耐心等待。

安装YCM(非编译)

上面那一步顺利完成的话已经装好,如果没有就自己按照下面的方法来做。

第一种方法:

"使用vim-plug插件来安装ycm,下面这句话加入你的vimrc然后重启vim,执行`:PlugInstall YouCompleteMe`
Plug 'Valloric/YouCompleteMe', { 'do': 'git submodule update --init --recursive' }

第二种:你可以手动安装YCM,执行下面命令之后,将YouCompleteMe整个拷贝到vim插件管理器指定的路径之下。

git clone https://github.com/Valloric/YouCompleteMe.git
cd YouCompleteMe
git submodule update --init --recursive

编译YCM


打开MinGW-W64 win64 Shell

首先你得下载一个编译好的64位的LLVM with Clang Support的安装包,奇怪的是官网只提供了32位的安装包,一度我想用MinGw从源代码编译一个,后来太多错误就放弃了,最后发现这个项目有提供64位的安装包ClangOnWin

安装到你想要安装的地方,这里我安装到c:/LLVM

Windows路径的变换:如果Windows路径是"C:\Program Files\Vim",那么你需要用转义符号转义空格,并改变斜杠的方向,最后变成"C:/Program\ Files/Vim"。

$ cd <root of vim installed>/vimfiles/bundle/YouCompleteMe
$ mkdir build ;cd build
$ cmake -G "MSYS Makefiles" -DCMAKE_MAKE_PROGRAM=E:/msys64/mingw64/bin/mingw32-make.exe -DPATH_TO_LLVM_ROOT=C:/LLVM . E:/program_files/Vim/vimfiles/bundle/YouCompleteMe/third_party/ycmd/cpp
$ mingw32-make ycm_core

至此结束,要确保正常运行,需要保证添加到Path环境变量中,在MSYS2 Shell中同样需要保证这两个路径在Path变量中,否则会出现加载模块的错误。

  • Python2所在路径
  • mingw64/bin路径
  • llvm所在路径

也可以分别将相关的dll拷贝到YouCompleteMe/third_party/ycmd路径下:libstdc++-6.dll,libwinpthread-1.dll,libclang.dlllibgcc_s_seh-1.dll

使用教程和配置

使用YouCompleteMe对工程进行补全,需要为每个工程提供一个项目文件:.ycm_extra_conf.py,主要指定的是编译器的option,比如说连接的库,库路径,头文件路径,宏定义,编译器优化标志等等。

这里要介绍一个插件,YCM-Generator,他能根据项目中Makefiles等文件生成对应的.ycm_extra_conf.py文件。很多时候这东西是不错的,但是某些情况还是不够灵活,比如说如果Makefile里面是交叉编译器的话,它不支持。

项目根目录下打开vim并执行:call GenYcm()(我的配置里面的函数)。

另外一个插件ycm_simple_conf,这个插件需要编写一个xml文件,然后根据这个xml文件生成,这样的话就比较灵活点。

在每个项目的根目录下编写.ycm_simple_conf.xml文件。

<project type="c++">
<include path="/home/local/libA/include"/>
<include path="/home/local/libB/include"/>
<include path="include"/>
<include path="build"/>
</project>
这个函数是为插件YCM-Generator的写的。
function! GenYCM()
let l:cur_dir=getcwd()
cd $VIMFILES/bundle/YCM-Generator
:silent execute ":!./config_gen.py ".l:cur_dir
if v:shell_error == 0
echom "Generate successfully!"
:YcmRestartServer
else
echom "Generate failed!"
endif
exec ":cd ". l:cur_dir
endfunction "下面三个映射是YCM提供函数跳转功能
nnoremap <leader>jd :YcmCompleter GoToDefinitionElseDeclaration<CR>
nnoremap <leader>jl :YcmCompleter GoToDeclaration<CR>
nnoremap <leader>jf :YcmCompleter GoToDefinition<CR> "由于Clang编译器的限制,ycm跳转功能有致命缺陷,无法跳到另外文件的函数定义上面
"所以我写了YcmGotoDef函数加上插件a.vim,实现粗略的跳转,原理是当Ycm跳到对应函数
"声明的头文件时使用a.vim的功能跳到对应源文件,在使用正则搜索,跳到函数定义上面。
nnoremap <Leader>g :call TracyoneGotoDef("")<cr>
nnoremap <C-\>g :call TracyoneGotoDef("sp")<cr> function! TracyoneGotoDef(open_type)
let l:ycm_ret=s:YcmGotoDef(a:open_type)
if l:ycm_ret < 0
try
execute "cs find g ".expand("<cword>")
catch /^Vim\%((\a\+)\)\=:E/
call s:EchoWarning("cscope query failed")
if a:open_type != "" | wincmd q | endif
return -1
endtry
else
return 0
endif
return 0
endfunction func! s:YcmGotoDef(open_type)
let l:cur_word=expand("<cword>")."\s*\(.*[^;]$"
:redir => l:msg
execute a:open_type
silent! execute ":YcmCompleter GoToDefinition"
:redir END
let l:rs=split(l:msg,'\r\n\|\n')
"make sure index valid
if get(l:rs,-1,3) !=3 && l:rs[-1] =~ 'Runtime.*'
:redir => l:msg
silent! execute ":YcmCompleter GoToDeclaration"
:redir END
let l:rs=split(l:msg,'\r\n\|\n')
if get(l:rs,-1,3) != 3 && l:rs[-1] !~ 'Runtime.*'
execute ":silent! A"
" search failed then go back
if search(l:cur_word) == 0
execute ":silent! A"
return -2
endif
return 3
elseif get(l:rs,-1,3) == 3 "not exist no error
return 0
else
return -3
endif else
return 1
endif
endfunc "当tab补全时vim上面会分裂一个小窗口显示函数变量原型,我们按下esc或者结束补全时
"自动关闭那个窗口
autocmd misc_group InsertLeave * if pumvisible() == 0|pclose|endif let g:syntastic_always_populate_loc_list = 1
let g:ycm_confirm_extra_conf=0
let g:syntastic_always_populate_loc_list = 1
let g:ycm_semantic_triggers = {
\ 'c' : ['->', ' ', '.', ' ', '(', '[', '&'],
\ 'cpp,objcpp' : ['->', '.', ' ', '(', '[', '&', '::'],
\ 'perl' : ['->', '::', ' '],
\ 'php' : ['->', '::', '.'],
\ 'cs,java,javascript,d,vim,python,perl6,scala,vb,elixir,go' : ['.'],
\ 'ruby' : ['.', '::'],
\ 'lua' : ['.', ':']
\ }
let g:ycm_collect_identifiers_from_tag_files = 1
let g:ycm_filetype_blacklist = {
\ 'tagbar' : 1,
\ 'qf' : 1,
\ 'notes' : 1,
\ 'unite' : 1,
\ 'text' : 1,
\ 'vimwiki' : 1,
\ 'pandoc' : 1,
\ 'infolog' : 1,
\ 'mail' : 1
\}
let g:ycm_global_ycm_extra_conf = $VIMFILES . "/bundle/YouCompleteMe/third_party/ycmd/cpp/ycm/.ycm_extra_conf.py"

关于.ycm_extra_conf.py的生成,最后我用ultisnips这个插件,自定义snippets,生成.ycm_extra_conf.py的配置,你可以参考

snippetspython.snippets的写法。

ubuntu 32bit 安装ycm流程

下面假设你已经通过vim的vundle之类的插件管理器安装好Ycm了。

编译安装clang编译器到/opt/Clang

sudo update;sudo apt-get upgrade
sudo apt-get install g++ subversion cmake autoconf automake
cd ~;mkdir -p work/clang && cd work/clang
svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
cd llvm/tools
svn co http://llvm.org/svn/llvm-project/cfe/trunk clang
cd ../../
mkdir build && cd build
cmake ../llvm
cmake --build .
cmake -DCMAKE_INSTALL_PREFIX=/opt/Clang -P cmake_install.cmake

编译ycm

cd ~/.vim/bundle/YouCompleteMe/
mkdir build
cd build
cmake -G "Unix Makefiles" -DPATH_TO_LLVM_ROOT=/opt/Clang . ~/.vim/bundle/YouCompleteMe/third_party/ycmd/cpp && make ycm_core

其它

在Visual Studio编译gvim和ycmd

ycm的github主页上已经提供了在vs下编译ycmd的官方方法,详细点这里

Windows下编译YouCompleteMe流程的更多相关文章

  1. [转] Windows下编译OpenSSL

    简述 OpenSSL是一个开源的第三方库,它实现了SSL(Secure SocketLayer)和TLS(Transport Layer Security)协议,被广泛企业应用所采用.对于一般的开发人 ...

  2. Windows下编译objective-C

    Windows下编译objective-C 2011-08-31 14:32 630人阅读 评论(0) 收藏 举报 windowscocoa工具objective clibraryxcode   目录 ...

  3. 在Windows下编译FFmpeg详细说明

    MinGW:一个可自由使用和自由发布的Windows特定头文件和使用GNC工具集导入库的集合,允许你生成本地的Windows程序而不需要第三方C运行时 MinGW,即 Minimalist GNU F ...

  4. 如何在WINDOWS下编译BOOST C++库 .

    如何在WINDOWS下编译BOOST C++库 cheungmine 2008-6-25   写出来,怕自己以后忘记了,也为初学者参考.使用VC8.0和boost1.35.0.   1)下载boost ...

  5. 在Windows下编译OpenSSL(VS2005和VC6)

    需要说明的是请一定安装openssl-0.9.8a .  openssl-1.0.0我没有编译成功. 如何在Windows下编译OpenSSL (Vs2005使用Vc8的cl编译器)1.安装Activ ...

  6. windows下编译java源文件的编码错误

    import java.util.Arrays;public class ArrayAsAReference{ public static void main(String[] args) { int ...

  7. Windows下编译SDL

    Windows下编译SDL的理由我就不多说了,无论用VS来编译或调试SDL库都是很方便的.而且SDL源代码中也包含了VC工程,你所要做的只是解压VC工程,进行适当的配置,然后编译.调试. 编译SDL大 ...

  8. Windows下编译安装 FFmpeg

    在Linux/Mac下编译 ffmpeg是非常方便的.但要在 Windows下编译 ffmpeg还真要花点时间.以下就是在 Windowns下编译ffmpeg的步骤: 一.安装Cygwin 在wind ...

  9. windows下编译php7图形库php_ui.dll

    CSDN博客 具有图形化编程才有意思,这几天看到了php ui 图形扩展,只是现在只能下载php 7.1的 本次教程编译php7.2.6的 php ui 要是linux下编译起来比较简单 但是 win ...

随机推荐

  1. Linux查看系统与内核信息(uname、file和lsb_release -a)

    uname 命令 uname 命令可以用来查看系统与内核的相关信息,命令格式如下: [root@localhost ~]# uname [选项] 选项: -a:查看系统所有相关信息: -r:查看内核版 ...

  2. SQL学习笔记之MySQL索引知识点

    0x00 概述 之前写过一篇Mysql B+树学习,简单的介绍了B+数以及MySql使用B+树的原因, 有了这些基础知识点,对MySql索引的类型以及索引使用的一些技巧,就比较容易理解了. 0x01 ...

  3. Eclipse安装Activiti插件(流程设计器)

    Eclipse安装Activiti插件(流程设计器) 一.安装步骤: 1,打开Eclipse的 Help -> Install New Software,填上插件地址: Name:Activit ...

  4. Mysql 整理错误

    Mysql 启动报PID错误 Starting MySQL..ERROR! The server quit without updating PID file (/usr/local/mysql/da ...

  5. 20145313张雪纯 《Java程序设计》第4周学习总结

    20145313张雪纯 <Java程序设计>第4周学习总结 教材学习内容总结 6.1何谓继承 程序代码重复时,可以把相同的程序代码提升为父类.继承除了可避免类之间重复的行为定义以外,还有i ...

  6. Linux命令:chmod、chgrp、chown的区别

    chmod是更改文件的权限: chgrp只是更改文件的属组: chown是更改文件的属主与属组. 1.chmod:更改文件的权限 文件权限的设置方式有两种,分别是数字和标记. mode : 权限设定字 ...

  7. vue知识汇总

    关于slot solt插槽,用来进行预定义,比如app里面的heard,各种情况下未必一致,把每种情况都加上solt,对应的情况下覆盖solt就可以了

  8. 微服务(一)eureka

    Eureka概述 一个简单的服务注册,服务发现架构 在CAP理论中,eureka选择了ap,作为注册中心,数据可用比数据不一致更重要 逻辑架构图 Eureka特性 1.当注册中心挂了,客户端之间依然可 ...

  9. python ConfigParse模块(转)

    最近写程序要用到配置文件,那么配置文件的解析就很重要了,下文转自chinaunix 一.ConfigParser简介 ConfigParser 是用来读取配置文件的包.配置文件的格式如下:中括号“[ ...

  10. 如何使移动web页面禁止横屏?

    https://segmentfault.com/q/1010000005813183 一般只有移动版有这种需求,我们一般不去禁止,而是比例缩放,css实现,竖屏1rem = 9pt ,横屏1rem ...