まえがき
Golangのクロスコンパイルは非常に魅力的だと思うのですが、Vimのプラグインとして配布する場合に少し悩んだので、調査した内容を残しておきます。
配布方法1: ユーザーにビルドしてもらうパターン
ユーザーにGoのビルドをしてもらうケース。
基本的にREADME.mdのInstallationの項目に
$ cd /ビルド可能なパス && go get -d&& go build
と書いておけばすむので、用意する側はかなり気楽です。
ユーザーにgo build
してもらえれば必ずその環境にあったバイナリが出来上がるのでこの点はメリットになりうるのですが、ユーザー側にGoの環境がなければいけないため、もしGoの環境がなければ使う側は少しハードルが高くなるかもしれません。
参考: Go で Vim プラグインを書く - http://haya14busa.com/vim-go-client/
配布方法2: バイナリを配布するパターン
バイナリ配布したいですよね。でも、インストール周りどうしましょう?
ここで個人的に大好きなfzf先生(Golang製)を参考にしてみました。
fzfにはインストールスクリプトがあり、shell scriptでアーキテクチャを判定してバイナリをダウンロードしているようです。
fzfのインストールスクリプトの実際のアーキテクチャを判定している箇所はこちらになります。
# Try to download binary executablearchi=$(uname-sm)binary_available=1
binary_error=""case"$archi"in
Darwin\ *64) download fzf-$version-darwin_${binary_arch:-amd64}.tgz ;;
Darwin\ *86) download fzf-$version-darwin_${binary_arch:-386}.tgz ;;
Linux\ armv5*) download fzf-$version-linux_${binary_arch:-arm5}.tgz ;;
Linux\ armv6*) download fzf-$version-linux_${binary_arch:-arm6}.tgz ;;
Linux\ armv7*) download fzf-$version-linux_${binary_arch:-arm7}.tgz ;;
Linux\ armv8*) download fzf-$version-linux_${binary_arch:-arm8}.tgz ;;
Linux\ aarch64*) download fzf-$version-linux_${binary_arch:-arm8}.tgz ;;
Linux\ *64) download fzf-$version-linux_${binary_arch:-amd64}.tgz ;;
Linux\ *86) download fzf-$version-linux_${binary_arch:-386}.tgz ;;
FreeBSD\ *64) download fzf-$version-freebsd_${binary_arch:-amd64}.tgz ;;
FreeBSD\ *86) download fzf-$version-freebsd_${binary_arch:-386}.tgz ;;
OpenBSD\ *64) download fzf-$version-openbsd_${binary_arch:-amd64}.tgz ;;
OpenBSD\ *86) download fzf-$version-openbsd_${binary_arch:-386}.tgz ;;
CYGWIN*\ *64) download fzf-$version-windows_${binary_arch:-amd64}.zip ;;
MINGW*\ *86) download fzf-$version-windows_${binary_arch:-386}.zip ;;
MINGW*\ *64) download fzf-$version-windows_${binary_arch:-amd64}.zip ;;
MSYS*\ *86) download fzf-$version-windows_${binary_arch:-386}.zip ;;
MSYS*\ *64) download fzf-$version-windows_${binary_arch:-amd64}.zip ;;
Windows*\ *86) download fzf-$version-windows_${binary_arch:-386}.zip ;;
Windows*\ *64) download fzf-$version-windows_${binary_arch:-amd64}.zip ;;*)binary_available=0 binary_error=1 ;;esac
https://github.com/junegunn/fzf/blob/373c6d8d55066251dc7af58598de6af4ff4570cf/install#L176-L202
download fzf-$version ~~~
となっている箇所はバイナリをダウンロードするスクリプト内の関数を呼び出しています。
こんなイメージで、初回起動時やプラグインマネージャでインストールスクリプトを叩いてあげれば、適切なバイナリを落としてくることができるようになりそうです。
配布方法3: 少し横着な方法
2つ目の方法で少し横着するとすれば、バイナリサイズが小さいうちはVimプラグインリポジトリにアーキテクチャごとのバイナリファイルをpushして、実行時に適切なバイナリが選ばれるようにすることもできるかと思います。
(無駄にファイルをダウンロードすることになるので怒られそうな気もしなくもないですが...)
Vim script側
lets:go_bin_path=v:null
" windowsで極力外部コマンドを実行したくないのでここで判定できればここでif has('win32')lets:go_bin_path='win-386'elseif has('win64')lets:go_bin_path='win-amd64'else" 正しいパスが得られているかチェックはしたほうが良いかもlets:go_bin_path= trim(system('path/to/archi_info.sh'))endififl:go_bin_path !=v:null
lets:result= system('"path/to/plugin/'.s:go_bin_path.'/goで実行するバイナリファイル"')endif
アーキテクチャ判定スクリプト
#!/usr/bin/env bashset-u# Echo binary path executable to stdout.archi=$(uname-sm)case"$archi"in
Darwin\ *64)echo darwin-amd64 ;;
Darwin\ *86)echo darwin-386 ;;
Linux\ armv5*)echo linux-arm5 ;;
Linux\ armv6*)echo linux-arm6 ;;
Linux\ armv7*)echo linux-arm7 ;;
Linux\ armv8*)echo linux-amd64 ;;
Linux\ aarch64*)echo linux-amd64 ;;
Linux\ *64)echo linux-amd64 ;;
Linux\ *86)echo linux-386 ;;
FreeBSD\ *64)echo freebsd-amd64 ;;
FreeBSD\ *86)echo freebsd-386 ;;
OpenBSD\ *64)echo openbsd-amd64 ;;
OpenBSD\ *86)echo openbsd-386 ;;
CYGWIN*\ *64)echo windows-amd64 ;;
MINGW*\ *86)echo windows-386 ;;
MINGW*\ *64)echo windows-amd64 ;;
MSYS*\ *86)echo windows-386 ;;
MSYS*\ *64)echo windows-amd64 ;;
Windows*\ *86)echo windows-386 ;;
Windows*\ *64)echo windows-amd64 ;;*);;esac
Vim scriptからアーキテクチャ判定用のshell scriptを実行し、結果をもとにVim scriptから適切なGoのバイナリを実行します。
メリットとしてはVimプラグインのバージョンに対して正しいバイナリが落とされているか気にする必要がないため、用意する側も少し気が楽になりそうです。
まとめ
Golangで作成されたVim プラグインの配布方法の3つをまとめました。
実際に自分もVimプラグインでGoのバイナリを配布する必要があったのですが、現在は3つ目の方法で暫定的に用意しています。
ちなみに、今回作ったプラグインはこちらです。
Qiita: Neovimでpopup-menuを実装できるプラグイン
Github: https://github.com/kamykn/popup-menu.nvim
(もしも、需要が高まれば2つ目の方の方法に移行する、というのも考えられるかと思います。)
色々方法はありましたが、そのプロジェクトに応じて適切な方法を選択できればいいかなと思いました👍