VIM-ShellのRPMを作ってみました

最近社内のVim使いの方々の間で、VIM-Shellというパッチが話題になっています。これはVimのなかでシェルを実行できるというもので、EmacsのシェルモードがVimにも欲しいねという話が発端です。
Vim&CentOSの環境で開発している人が多いこともあり、どうせならとRPMパッケージを作ってみました。

まずは、RPMを作成するために必要なものをインストールします。今回はひとつひとつ入れていきますが、面倒な場合やビルド専用マシンにする場合などは、開発ツールや開発ライブラリを次のようにまとめてインストールしておくと楽かと思います。


# yum grouplist
# yum groupinstall "Development Tools"
# yum groupinstall "Development Libraries"

まずは、何は無くともrpmbuildコマンドが必要ですので、インストールします。


# yum install rpm-build

SRPMを取得するためにyumdownloaderコマンドを使いますので、インストールします。


# yum install yum-utils

yumdownloaderコマンドでSRPMを取得するためのリポジトリを設定します。一から書くのは面倒ですので /etc/yum.repos.d/CentOS-Base.repo をコピーして書き換えます。


# cd /etc/yum.repos.d/
# cp CentOS-Base.repo CentOS-Source.repo
# vi CentOS-Source.repo

baseurlを近くのミラーサイトにします。また、普段は見に行く必要はありませんので「enabled=0」にしておきます。


# CentOS-Source.repo
[base-source]
name=CentOS-$releasever - Base Source
baseurl=http://ftp.riken.jp/Linux/centos/$releasever/os/SRPMS/
gpgcheck=1
enabled=0
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-5
#released updates
[updates-source]
name=CentOS-$releasever - Updates Source
baseurl=http://ftp.riken.jp/Linux/centos/$releasever/updates/SRPMS/
gpgcheck=1
enabled=0
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-5
#packages used/produced in the build but not released
[addons-source]
name=CentOS-$releasever - Addons Source
baseurl=http://ftp.riken.jp/Linux/centos/$releasever/addons/SRPMS/
gpgcheck=1
enabled=0
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-5
#additional packages that may be useful
[extras-source]
name=CentOS-$releasever - Extras Source
baseurl=http://ftp.riken.jp/Linux/centos/$releasever/extras/SRPMS/
gpgcheck=1
enabled=0
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-5
#additional packages that extend functionality of existing packages
[centosplus-source]
name=CentOS-$releasever - Plus Source
baseurl=http://ftp.riken.jp/Linux/centos/$releasever/centosplus/SRPMS/
gpgcheck=1
enabled=0
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-5
#contrib - packages by Centos Users
[contrib-source]
name=CentOS-$releasever - Contrib Source
baseurl=http://ftp.riken.jp/Linux/centos/$releasever/contrib/SRPMS/
gpgcheck=1
enabled=0
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-5

次に、一般ユーザでRPMを作成するための設定をします。RPMの作成をrootで行うと、SPECファイルの記述ミスや操作ミスなどで環境を破壊する恐れがあるためです。

以下、一般ユーザーで作業を行います。


$ mkdir -p ~/rpm/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
$ echo "%_topdir $HOME/rpm" >> ~/.rpmmacros

これで、HOMEのrpmディレクトリがRPM作成の作業場になります。

さて、準備が整いましたので、Vimのカスタムパッケージ作りに入ります。
まずは、インストールされているVimのバージョンを調べます。


$ yum list installed | grep vim
vim-common.i386                          2:7.0.109-3.el5.3      installed
vim-enhanced.i386                        2:7.0.109-3.el5.3      installed
vim-minimal.i386                         2:7.0.109-3.el5.3      installed

次にパッケージを提供しているリポジトリを調べます。


$ yum search vim | grep vim-common.i386
vim-common.i386                          2:7.0.109-3            base
vim-common.i386                          2:7.0.109-3.el5.3      updates
vim-common.i386                          2:7.0.109-3.el5.3      installed

先ほど調べたバージョンのパッケージは、updatesリポジトリのようですね。では、updatesからSRPMを取得します。


$ yumdownloader --enablerepo=updates-source --source vim

カレントディレクトリに vim-7.0.109-3.el5.3.src.rpm がダウンロードされましたので、これをインストールします。


$ rpm -ivh vim-7.0.109-3.el5.3.src.rpm

VIM-Shellのパッチをダウンロードして、SOURCEディレクトリへ入れます。


$ cd ~/rpm/SOURCES/
$ wget http://www.wana.at/vimshell/vimshell_1.0_vim7.0.patch.bz2

SPECファイルを修正します。

1. Releaseの末尾にVIM-Shellリリース1の意味で「vs1」を追加
2. Patch行の最後にVIM-Shellのパッチファイルを追加
3. %prep部の後半へVIM-Shellパッチの実行処理を追加
4. %changelog部へ変更履歴を追加


Summary: The VIM editor.
Name: vim
Version: %{baseversion}.%{beta}%{patchlevel}
Release: 3%{?dist}.3<strong>vs1</strong>
License: freeware
Group: Applications/Editors
Source0: ftp://ftp.vim.org/pub/vim/unix/vim-%{baseversion}%{?beta}%{?CVSDATE}.tar.bz2


Patch3100: vim-selinux.patch
Patch3101: vim-selinux2.patch
<strong># VIM-Shell</strong>
<strong>Patch9000: http://www.wana.at/vimshell/vimshell_1.0_vim7.0.patch.bz2</strong>
Buildroot: %{_tmppath}/%{name}-%{version}-root


%patch3101 -p1
%endif
<strong># VIM-Shell</strong>
<strong>%patch9000 -p0</strong>
%if "%{withcvim}" == "1"
mkdir cvim


%changelog
<strong>* Mon Nov 26 2007 Your Name <mail@example.com> 7.0.109-3.3vs1</strong>
<strong>- add VIM-Shell 1.0</strong>

それではビルドします。折角なので、アーキテクチャにi686を指定します。また、リリース番号を揃えるためにdist定義を付与します。


$ rpmbuild -ba --target i686 --define 'dist .el5' ~/rpm/SPECS/vim.spec
ビルド対象プラットフォーム: i686
ターゲット i686 用にビルド中
エラー: ビルド依存性の失敗:
        python-devel は vim-7.0.109-3.3.i386 に必要とされています
        libtermcap-devel は vim-7.0.109-3.3.i386 に必要とされています
        libacl-devel は vim-7.0.109-3.3.i386 に必要とされています
        gpm-devel は vim-7.0.109-3.3.i386 に必要とされています
        autoconf は vim-7.0.109-3.3.i386 に必要とされています
        libselinux-devel は vim-7.0.109-3.3.i386 に必要とされています
        gtk2-devel は vim-7.0.109-3.3.i386 に必要とされています
        libSM-devel は vim-7.0.109-3.3.i386 に必要とされています
        libXt-devel は vim-7.0.109-3.3.i386 に必要とされています
        libXpm-devel は vim-7.0.109-3.3.i386 に必要とされています

gccと表示された必要なものをインストールします。


$ sudo yum install gcc python-devel libtermcap-devel libacl-devel gpm-devel autoconf libselinux-devel gtk2-devel libSM-devel libXt-devel libXpm-devel

再度rpmbuildコマンドを実行します。無事コンパイルまでいったようですが、エラーで止まってしまいました。


gui.c: In function ‘gui_start’:
gui.c:142: 警告: ignoring return value of ‘read’, declared with attribute warn_unused_result
gui.c:2423:2: error: #endif に #if がありません
make: *** [objects/gui.o] エラー 1

VIM-Shellのパッチが src/gui.c に不要と思われる「#endif」を挿入しているようですので、これを削除するパッチを作成します。


$ cd ~/rpm/BUILD/vim70/
$ cp src/gui.c src/gui.c~
$ vi src/gui.c
$ diff -u src/gui.c~ src/gui.c > ~/rpm/SOURCES/vimshell_1.0_vim7.0-gui.patch


--- src/gui.c~  2007-11-22 22:47:18.000000000 +0900
+++ src/gui.c   2007-11-22 22:53:47.000000000 +0900
@@ -2420,7 +2420,6 @@
     long_u     old_hl_mask;
     int                off;
     sattr_T    first_attr;
-#endif
     int                idx, len;
     int                back, nback;
     int                retval = FALSE;

では、このパッチをSPECファイルに追加します。


Patch3100: vim-selinux.patch
Patch3101: vim-selinux2.patch
# VIM-Shell
Patch9000: http://www.wana.at/vimshell/vimshell_1.0_vim7.0.patch.bz2
<strong>Patch9001: vimshell_1.0_vim7.0-gui.patch</strong>
Buildroot: %{_tmppath}/%{name}-%{version}-root


%patch3101 -p1
%endif
# VIM-Shell
%patch9000 -p0
<strong>%patch9001 -p0</strong>
%if "%{withcvim}" == "1"
mkdir cvim

再度rpmbuildコマンドを実行します。またもやコンパイルエラーです。


gcc -c -I. -Iproto -DHAVE_CONFIG_H     -g -O2         -o objects/vim_shell.o vim_shell.c
vim_shell.c:120: error: expected ‘)’ before ‘width’
vim_shell.c: In function ‘vim_shell_start’:
vim_shell.c:229: error: 不完全型のポインタへの間接参照
vim_shell.c:230: error: 不完全型のポインタへの間接参照
vim_shell.c:237: error: 不完全型のポインタへの間接参照
vim_shell.c:237: error: 不完全型のポインタへの間接参照
vim_shell.c:238: error: 不完全型のポインタへの間接参照

~/rpm/BUILD/vim70/src/feature.h を見てみると、


#if defined(FEAT_NORMAL)  &amp; &amp; (defined(UNIX) || defined(MACOS_X))
#define FEAT_VIMSHELL
#endif

となっているので「--with-features=tiny」の場合はエラーになるようです。
対処法はいろいろあると思いますが、今回は src/vim_shell.c と src/terminal.c の中身を「FEAT_VIMSHELL」が未定義の場合はコメントアウトするようにしてみます。


$ diff -u src/vim_shell.c~ src/vim_shell.c > ~/rpm/SOURCES/vimshell_1.0_vim7.0-feature.patch
$ diff -u src/terminal.c~ src/terminal.c >> ~/rpm/SOURCES/vimshell_1.0_vim7.0-feature.patch


--- src/vim_shell.c~    2007-11-22 22:55:56.000000000 +0900
+++ src/vim_shell.c     2007-11-22 23:08:08.000000000 +0900
@@ -16,6 +16,7 @@
 #include "vim.h"
+#ifdef FEAT_VIMSHELL
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
@@ -908,3 +909,4 @@
        return rval;
 }
+#endif
--- src/terminal.c~     2007-11-22 22:55:56.000000000 +0900
+++ src/terminal.c      2007-11-22 23:08:08.000000000 +0900
@@ -32,6 +32,7 @@
 #include "vim.h"
+#ifdef FEAT_VIMSHELL
 #ifdef VIMSHELL_DEBUG
 #  define ESCDEBUG
 /*
@@ -1929,3 +1930,4 @@
        return written;
 }
+#endif

作成したパッチをSPECファイルへ追加します。


Patch3100: vim-selinux.patch
Patch3101: vim-selinux2.patch
# VIM-Shell
Patch9000: http://www.wana.at/vimshell/vimshell_1.0_vim7.0.patch.bz2
Patch9001: vimshell_1.0_vim7.0-gui.patch
<strong>Patch9002: vimshell_1.0_vim7.0-feature.patch</strong>
Buildroot: %{_tmppath}/%{name}-%{version}-root


%patch3101 -p1
%endif
# VIM-Shell
%patch9000 -p0
%patch9001 -p0
<strong>%patch9002 -p0</strong>
%if "%{withcvim}" == "1"
mkdir cvim

再度rpmbuildコマンドを実行します。今度こそー!

……。

…………。

………………。

できたー!

早速インストールして、使ってみます。


$ cd ~/rpm/RPMS/i686/
$ sudo rpm -Uvh vim-common-7.0.109-3.el5.3vs1.i686.rpm vim-enhanced-7.0.109-3.el5.3vs1.i686.rpm vim-minimal-7.0.109-3.el5.3vs1.i686.rpm

Vimを起動して「:vimshell」を実行します。おー、Vimの中でシェルが動く!

といった感じで、CentOS5用のカスタムVimパッケージができあがりました。RPMパッケージは作らずに、ソースから「./configure;make;make install」でもいいのですが、同じ環境が複数ある場合は、やはりパッケージを作ったほうが便利かと思われます。

まぁ、私が普段使うエディタはEmacsですので、このパッケージを使うことはほぼないのですが……。