[Unix]在程序中取得当前程序可执行文件的路径

[Unix]编译定制一个可移动的Vim

Ervin posted @ 2012年1月07日 21:33 in Unix , 2198 阅读

    Mint 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!
      */

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter