Docker 中编译 vim8.0
linux vim
Lastmod: 2019-08-17

vim 的最新版 vim8.0 提供了很多新的特性,而且一些流行的 vim 插件很多功能也依赖于 8.0 版本,如果你要使用 vim8.0,那么最好的办法当然是使用操作系提供的软件包管理器一键安装,省时省力。

但是总有那么一些蛋疼的情况 ——你需要自己编译 vim。

本文就是记录下具体的步骤,并且把编译源码时需要安装的依赖软件全部做成 docker 镜像。

事情起因

某台服务器上我要用 vim8.0 的新特性,但是在服务器上我没有任何超级权限,只能读写我自己的 home 目录。

所以没法直接安装vim,只能从源码编译。

制作编译 vim 的docker image

编译 vim 需要系统中安装很多依赖软件,比如 vim 最基本的要包括 python2.7,luajit 等。

都 2019 年了,最好的方式当然是制作一个 docker 镜像,具体的步骤就不一一解释,贴上 Dockerfile 以示诚意。

FROM ubuntu:18.04

RUN apt-get update && apt-get install -y \
    liblua5.1-dev \
    luajit \
    libluajit-5.1 \
    python-dev \
    ruby-dev \
    libperl-dev \
    libncurses5-dev \
    libatk1.0-dev \
    libx11-dev \
    libxpm-dev \
    libxt-dev \
    gnupg2 \
    curl \
    && gpg2 --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB \
    && curl -sSL https://get.rvm.io | bash -s stable \
    && /bin/bash -l -c "rvm install 2.6 && rvm use 2.6.3 --default"

COPY ./configure.sh  /root/

ENTRYPOINT ["/bin/bash"]

其中 configure.sh 是编译 vim 时你输入的一些 configure 选项,其实这个文件可有可无,没有的话手动输入就行了

#!/bin/bash

./configure \
--enable-multibyte \
--enable-perlinterp=dynamic \
--enable-rubyinterp=dynamic \
--with-ruby-command=/usr/local/bin/ruby \
--with-ruby-command=/usr/local/rvm/rubies/ruby-2.6.3/bin/ruby \
--enable-pythoninterp=dynamic \
--with-python-config-dir=/usr/lib/python2.7/config-x86_64-linux-gnu \
--enable-luainterp \
--with-luajit \
--enable-cscope \
--enable-gui=auto \
--with-features=huge \
--with-x \
--enable-fontset \
--enable-largefile \
--disable-netbeans \
--with-compiledby="Name" \
--enable-fail-if-missing

#--enable-python3interp \
#--with-python3-config-dir=/usr/lib/python3.5/config-3.5m-x86_64-linux-gnu \

把以上文件放在一个文件夹,制作 docker 镜像

docker build -t vim-dev:0.1 . 

耐心等待几分钟,因为有很多很多包需要安装。

编译 vim

有了 docker image 以后开始编译 vim

首先 git clone https://github.com/vim/vim

然后运行 docker image,并挂载源码目录,在这里我把源码挂载到了 /tmp 下,

docker run -it --rm -v $PWD:/tmp vim-dev:0.1

进入 /tmp 目录并把 /root 下的 configure.sh 拷贝到 /tmp,其实不拷贝也行,只需要把 configure.sh 的内容复制运行就行了。

root@ffd7bdd97a86:/# cd /tmp/
root@ffd7bdd97a86:/tmp# cp /root/configure.sh ./
root@ffd7bdd97a86:/tmp# ./configure.sh
root@ffd7bdd97a86:/tmp# make VIMRUNTIMEDIR=/usr/local/share/vim/vim81

最后就能得到一个 vim 的二进制文件。

运行 vim

把编译好的 vim 拷贝到目标机器上,运行一下试试看,幸运的话直接可以运行(取决于目标机器安装了多少依赖库文件),

解决 libluajit-5.1.so.2

但是如果目标机器没有安装 luajit 的话你会看到如下错误

$ ./myvim
./myvim: error while loading shared libraries: libluajit-5.1.so.2: cannot open shared object file: No such file or directory

如果解决? 把 docker image 系统中的 libluajit-5.1.so.2 拷贝出来就好啦。

重新进入 docker,找到 luagit

libluajit-5.1.so.2 => /usr/lib/x86_64-linux-gnu/libluajit-5.1.so.2

拷贝到 docker run 时挂载的目录,退出容器后就能看到了,然后拷贝到目标机器。

运行 vim 时候我们需要 load 我们指定的这个 libluajit-5.1.so.2,方法是 设置 LD_PRELOAD

can’t open syntax.vim 警告

运气再不好,还能看到这个警告

Error detected while processing /home/xxx/.vimrc:
line   49:
E484: Can't open file /usr/local/share/vim/syntax/syntax.vim
Error detected while processing function plug#end:
line   86:
E484: Can't open file /usr/local/share/vim/syntax/syntax.vim

原因是我们在编译 vim 时,没有设置好 VIMRUNTIME 的路径,在 make 的时候指定 VIMRUNTIME

make VIMRUNTIMEDIR=/usr/local/share/vim/vim81 

或者也可以说,编译好 binary 后我们需要 make install,这样 vim 和它依赖的运行文件就全部拷贝到系统了。

但是因为现在的场景特殊,我没有任何修改系统目录的权限,因此不可能 make install。

绕过这个警告的方法是告诉 vim8 去用系统现在已有的 vim版本的 syntax 文件,比如系统默认 vim 是 /usr/share/vim/vim74/

那么可以在 bash 事先设置这个变量值

export VIMRUNTIME=/usr/share/vim/vim74/

myvim 脚本

以上两个错误/警告 每次在运行 vim 的时候都会出现,所以可以把它写成一个 bash script

#!/bin/bash

export LD_LIBRARY_PATH=.
export VIMRUNTIME=/usr/share/vim/vim74/

LD_PRELOAD=$HOME/libluajit-5.1.so.2 $HOME/vim  $1

把这个 bash script 命名为 myvim, 使用的时候是这样的 myvim test.txt

(完)

comments powered by Disqus