3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

WindowsネイティブなVimとMSYSビルドなVimで同一のvimrcを読む状況で、dein.vimを使って両環境のvimproc DLLを作るまで

Last updated at Posted at 2016-10-28

はじめに

私が扱う特殊な環境のひとつに、mingw-w64でビルドしたVimと、msys2でビルドしたVimが共存している環境がある。
どちらも$HOMEを同じ場所にしているため、同一の.vimrcruntimepathを見に行くようになっている。

このような環境で問題になるのは各環境用にビルドが必要なvimprocで、以前pathogenで管理していたときはそれぞれの環境でmakeを手動実行すればよかったのだが、dein.vimに乗り換えてからはそれだけでは済まなくなってしまった。
特殊な状況なので同一のことに悩まれている方は少ないかと思うが、ひとまず解決に至ったので記事にまとめることにする。

前提となる環境

下記の環境でVimを扱う場合を想定している。

  • Windowsネイティブ環境: mingw-w64でビルドしたVim、またはvim-jpで配布されているVim
  • msys2のシェル内: vimパッケージのvim
  • mingw32/64のシェル内: vimパッケージのvim

また、vimprocはTOMLに以下のように書いてあると想定する。

[[plugins]]
repo = 'Shougo/vimproc'
hook_post_update = '''
  if dein#util#_is_windows()
    let cmd = 'tools\\update-dll-mingw'
  elseif dein#util#_is_cygwin()
    let cmd = 'make -f make_cygwin.mak'
  elseif executable('gmake')
    let cmd = 'gmake'
  else
    let cmd = 'make'
  endif
  let g:dein#plugin.build = cmd
'''

問題点

1. どちらかのDLLしか作られない

前提とする環境だと2種類のDLL(Windows用のDLLとCygwin用のDLL)を作らなければならないのだが、この設定だとdein#install()dein#update()した環境のDLLしか作られない。
DLLが作られなかった環境でdein#reinstall('vimproc')すればよいのかとも思ったが、「そんなプラグインはねーよ!」と怒られてしまった。

2. mingw32/64のシェルでVimを立ち上げるとvimprocのビルドに失敗する

前提とする環境の場合、WindowsネイティブなVimではなくmingw32/64でもmsysでビルドしたVimを利用するようにしている。
dein#install()dein#update()でvimprocのビルドが走るのだが、msysでビルドしたVimなのでdein#util#_is_cygwin()1を返すこととなり、上記の設定だとmake -f make_cygwin.makが走ることとなる。
ただし、シェル環境自体はmingw32/64なので、このままだとビルドに失敗してしまう。

解決策

2016/10/31 Update

以下のようにTOMLを修正することでとりあえずうまく動くようになった。

[[plugins]]
repo = 'Shougo/vimproc'
merged = 0
hook_add = '''
  if dein#util#_is_windows()
    let s:vimproc_dll_basename = has('win64') ?
          \ 'vimproc_win64.dll' : 'vimproc_win32.dll'
  elseif dein#util#_is_cygwin()
    let s:vimproc_dll_basename = 'vimproc_cygwin.dll'
  elseif dein#util#_is_mac()
    let s:vimproc_dll_basename = 'vimproc_mac.so'
  elseif glob('/lib*/ld-linux*64.so.2', 1) != ''
    let s:vimproc_dll_basename = 'vimproc_linux64.so'
  elseif glob('/lib*/ld-linux*.so.2', 1) != ''
    let s:vimproc_dll_basename = 'vimproc_linux32.so'
  elseif system('uname -s') =~? '^.\+BSD\n$'
    let s:vimproc_dll_basename = system(
          \ 'uname -sm | tr "[:upper:]" "[:lower:]"'
          \ .' | sed -e "s/ /_/" | xargs -I "{}" echo "vimproc_{}.so"')[0 : -2]
  else
    let s:vimproc_dll_basename = 'vimproc_unix.so'
  endif

  let s:vimproc_dll = get(g:, 'vimproc#dll_path', dein#get('vimproc').path . '/lib/'. s:vimproc_dll_basename)

  if !filereadable(s:vimproc_dll)
    call dein#call_hook('post_update')
    call dein#build('vimproc')
  endif
'''
hook_post_update = '''
  if dein#util#_is_windows()
    let cmd = 'tools\\update-dll-mingw'
  elseif dein#util#_is_cygwin()
    let cmd = 'make -f make_cygwin.mak'
    if $MSYSTEM == "MINGW32" || $MSYSTEM == "MINGW64"
      let cmd = "MSYSTEM=MSYS bash --login -c 'cd " . g:dein#plugin.path . ";" . cmd . "'"
    endif
  elseif executable('gmake')
    let cmd = 'gmake'
  else
    let cmd = 'make'
  endif
  let g:dein#plugin.build = cmd
'''

mingw32/64のシェルからmsysのVimが起動された場合はmsysのシェルからmakeを叩くようにしてみた。
さらに、hook_addフックでg:vimproc#dll_pathにファイルがあるかを調べ、なければビルドしてdein#recache_runtimepath()でキャッシュを再構築するようにしている。
このタイミングでdein#recache_runtimepath()して問題ないのかはよく調べていないが、今のところ問題なく動いているようだ。

dein.vim作者のShougo氏がコメント欄にmore betterな解決方法を教えてくださったので反映を行った。

  • merged = 0とする
  • dein#buildを使用する

さらに上記修正を行うと、私の環境では稀にg:vimproc#dll_pathに値がセットされる前にhook_addフックが呼ばれることがあったため、hook_add内の判定を若干修正した。

恐らくdein#buildはこの記事で私がビルドし直そうとしていたがために実装してくれたのだろう。非常に感謝である。
本来ならばbuild = "make"としておけば解決なのだが、MinGW32/64なシェルでMSYSビルドのVimを使おうとしているためにmakeだけの場合だとmake -f make_mingw32.makまたはmake -f make_mingw63.makが走ることになり、vimproc_cygwin.dllが作られないためにこのようなトリッキーな手法をキメなければならなくなっている。
MinGW32/64なシェルでMSYSビルドのVimを使うことがなければこのような手法は不要なので、どうかbuild = makeだけ書いて、必要なときに手動でcall dein#build('vimproc')するようにしてほしい。

3
3
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?