WindowsのVim8でYouCompleteMeをインストールする

公式に詳しい手順は書いているのですが、手順通りに進めても上手く行かない箇所があったため、備忘録を兼ねてYouCompleteMe(以下YCM)をインストールする手順を残します。

# デモ

C++の補完もちゃんと動く
![cpp-fs8.png](https://qiita-image-store.s3.amazonaws.com/0/51728/76b60a10-8439-40fe-84af-cd050e2c149c.png)

C#のLINQもちゃんと補完してくれる
![rapture-fs8.png](https://qiita-image-store.s3.amazonaws.com/0/51728/df765e5f-36f4-29a9-2bf5-ff2f46f752af.png)

# 環境

環境はすべて64bitです。

- Windows 10 Pro
- [Visual Studio Community 2017](https://www.visualstudio.com/ja/downloads/)
    - C++は必須。
    - C#の補完もするならC#も、追加でC++インストール時のMSBuildも必要。
- [LLVM 5.0.0](http://releases.llvm.org/download.html#5.0.0)
    - 5.0.0じゃないといけない、5.0.1だと上手くいかなかった。
    - ダウンロード: Pre-Built Binaries:のClang for Windows (64-bit)
- [Python 3.5.x(リンクは3.5.4)](https://www.python.org/downloads/release/python-354/)
    - ダウンロード: Windows x86-64 executable installer
- Git

また、Vimの環境は次の通りです。

- [Vim 8.0.0596 +kaoriya (2017/05/02)](https://github.com/koron/vim-kaoriya/releases)
- vimproc
    - vimproc_win64.dllをビルドする際に必要になるwin32.makは[Microsoft Windows SDK for Windows 7 and .NET Framework 4](https://www.microsoft.com/en-us/download/details.aspx?id=8279)に含まれている
- NeoBundle
    - ~~dein.vimではない。[^1]~~dein.vimでもいけた

[^1]: ~~dein.vimでYCMをインストールすると、:YcmRestartServerをしても補完サーバーが起動しない謎挙動にぶつかった。~~

# YCMのインストール

## 1. NeoBundleの場合

- 1. vimrcにYCMを追加

```:vimrc
NeoBundle 'Valloric/YouCompleteMe'
```

YCMプラグインフォルダは

```
path\to\\.vim\bundle\YouCompleteMe
```

## 1. dein.vimの場合

※dein.tomlは設定済みとする

- 1. dein.tomlにYCMを追加、その時に``merged = 0``を設定する [^2]

[^2]: https://github.com/Shougo/dein.vim/issues/144

```:dein.toml
[[plugins]]
repo = 'Valloric/YouCompleteMe'
merged = 0
```

YCMプラグインフォルダは

```
path\to\.vim\dein\repos\github.com\Valloric\YouCompleteMe
```

## 2. から続き

- 2. YCMプラグインフォルダへ

\YouCompleteMe\third_party\ycmd\cpp\ycm\CMakeLists.txt
を開き、LLVMへのパスを追加する。
この設定はスキップすれば最新バージョンを自動でダウンロードして使用してくれるので手軽。

```:CMakeLists.txt
# 25行あたり
set( PATH_TO_LLVM_ROOT "path/to/LLVM" CACHE PATH "Path to the root of a LLVM+Clang binary distribution" )
```

- 3. YCMのビルド

コマンドプロンプトを「VS 2017用 x64 Native Tools コマンドプロンプト」で開き、
MSBuild.exeとcmake.exeにパスを通す

※パスは省略

```:コマンドプロンプト
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.5.2
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'

>where msbuild
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe

>where cmake
情報: 与えられたパターンのファイルが見つかりませんでした。

>set path=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin;%path%

>where cmake
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe
```

このままYCMのパスへ行き、念のためgit submodule udpateをしておく

```:コマンドプロンプト
path\.vim\bundle\YouCompleteMe>git submodule update --init --recursive
```

ようやくビルド、pythonによるビルド時のビルドオプションに補完したい言語を指定する、
--allを指定すると、C-family(C、C++、Objective C、Objective C++)、C#、Python、Go、TypeScript、JavaScript、Rustでコード補完が効くようになる。

```:コマンドプロンプト
path\.vim\bundle\YouCompleteMe>python install.py --all
```

ビルドに10分くらいかかる

# C++用の設定

C++の補完用の設定にthird_party\ycmd\examples\.ycm_extra_conf.pyをコピーして使う。
自分はユーザーホームディレクトリに置いてるのでvimrcにそれを読み込むように設定する。

```:vimrc
let g:ycm_global_ycm_extra_conf = $HOME . '/.ycm_extra_conf.py'
```

このままではC++の補完が効かないのでC++ヘッダのincludeディレクトリを設定するのだが、この時にVisual Studio 2015(VC14)のだと上手くいった。[^3]

[^3]: 他のヘッダ(VS2017やmsys2上のGCCなど)だと、補完時にバグったような挙動になった。

```:~/.ycm_extra_conf.py
flags = [
'-Wall',
'-Wextra',
# '-Werror',
'-fexceptions',
'-DNDEBUG',
'-std=c++14',
'-x',
'c++',
# C++
'-I',
'C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include',
# Boost
'-I',
'E:/SDKs/boost_1_65_1',
]
```

# 参考

- YCM公式: https://github.com/Valloric/YouCompleteMe#full-installation-guide
- win32.makがない: https://qiita.com/s_of_p/items/fe522eb6b1d48b8b3885#win32mak-%E3%81%8C%E3%81%AA%E3%81%84