[Unix]编译定制一个可移动的Vim
Posted on 2012年1月07日 21:33Mint 12源里面的Vim并不支持lua脚本扩展,于是就想自己编译一个。如果能编译成可以移动的就更好了,这样使用不同机器的时候只需要scp一个目录就可以了。
下载了Vim 7.3的源码包准备编译,首先就发现不能外部构建,必须要在源代码目录下configure,因为源代码根目录下的configure文件是这样写的:
cd src && exec ./configure "$@"
然后研究了一下可用的选项,最后使用的选项如下:
./configure --prefix=/opt/vim73/ --with-features=huge --disable-darwin \ --disable-selinux --enable-luainterp=yes --enable-cscope --enable-xim \ --enable-gui=gtk2 --without-local-dir --with-vim-name=pvim --with-ex-name=pex \ --with-view-name=pview
不过这些选项里并没有指明使用的vimrc以及其他.vim文件的路径,如此编译安装后,使用的的vimrc应该还是和系统自带的Vim是一样的。我希望编译出的Vim使用它安装目录下的vimrc。不过configure脚本似乎没有选项可以指明这个。
细想一下,默认的vimrc的路径有可能是在代码中指定的,于是用grep搜索代码,发现src/feature.h这个文件甚是可以,打开一看发现这个文件就是预留用来自定义某些配置的。关于vimrc主要有一下几个宏:
/* #define VIMRC_FILE ".vimrc" */ /* #define GVIMRC_FILE ".gvimrc" */ /* #define USR_VIMRC_FILE "~/foo/.vimrc" */ /* #define USR_VIMRC_FILE2 "~/bar/.vimrc" */ /* #define USR_VIMRC_FILE3 "$VIM/.vimrc" */ /* #define USR_GVIMRC_FILE "~/foo/.gvimrc" */ /* #define USR_GVIMRC_FILE2 "~/bar/.gvimrc" */ /* #define USR_GVIMRC_FILE3 "$VIM/.gvimrc" */ /* #define SYS_VIMRC_FILE "/etc/vimrc" */ /* #define SYS_GVIMRC_FILE "/etc/gvimrc" */
和上面贴的一样,在src/feature.h中这些宏都是注释掉的。这其中主要起作用的宏有:
USR_VIMRC_FILE SYS_VIMRC_FILE USR_GVIMRC_FILE SYS_GVIMRC_FILE
添加这几个宏的定义,使得vimrc的路径依赖于VIMRUNTIME变量。然后make && make install。
看起来似乎大功告成,但这时我发现只要将安装好的Vim移动到别的路径,Vim就找不到各种配置文件了。看来VIMRUNTIME的预设值也是在编译时确定的。google了一下这个变量,发现如果在Vim执行前用export设置这个变量的值到正确的路径,那么Vim仍然能够找到vimrc等配置文件。
这样依赖就有两种方法来解决:
1.用shell脚本wrap一下Vim的可执行文件。
2.修改Vim源文件,在main函数刚开始的地方用setenv设置这个环境变量。
考虑了一下决定采用第二种方法,结果发现在程序中获取可执行文件的路径竟然相当麻烦(上一篇博客讲了这个问题)。不过毕竟我的环境基本是Linux,于是写了一个Linux Only的patch,哪天需要在新环境使用再改吧。
diff --git a/src/main.c b/src/main.c index 435e607..cf3a0fc 100644 --- a/src/main.c +++ b/src/main.c @@ -174,6 +174,29 @@ main #endif /* + * Set $VIMRUNTIME. + */ +#ifdef UNIX + char exe_path_buff[512]; + char *exe_path_ptr; + ssize_t exe_path_len = + readlink("/proc/self/exe", exe_path_buff, sizeof(exe_path_buff)); + if(exe_path_len > 0) + { + exe_path_buff[exe_path_len] = 0; + exe_path_ptr = exe_path_buff + exe_path_len; + while(exe_path_ptr != exe_path_buff && *exe_path_ptr != '/') + exe_path_ptr --; + *exe_path_ptr = 0; + while(exe_path_ptr != exe_path_buff && *exe_path_ptr != '/') + exe_path_ptr --; + *exe_path_ptr = 0; + strcat(exe_path_buff, "/share/vim/vim73/"); + setenv("VIMRUNTIME", exe_path_buff, 0); + } +#endif + + /* * Do any system-specific initialisations. These can NOT use IObuff or * NameBuff. Thus emsg2() cannot be called! */