##【はじめに】
MSYS2ではzshパッケージが提供されているので簡単にzsh環境を構築できます。
→ [MSYS2でWindowsにzsh環境を導入する]
しかし、残念ながらMSYS2で提供されているzshはバグがあって履歴ファイルを扱うことが出来ません。
調べてみるとヒストリファイルのロック部に問題があるようで、本家でも問題が指摘されております。
zshで履歴ファイルが使えないのは個人的に**「ありえない」**ので対策を行いたいとおもいます。
【原因解明&対策方針】
zshのソースコードを追ってみると、履歴ファイルのロック部はhist.cファイル内に記述さている*lockhistfile()*関数で行っています。
この関数をみてみると履歴ファイルのロックファイルを作成する方法として、symlink()関数を使っているようで、これが要因となってロックファイルの作成に失敗しているようです - 結果として履歴ファイルが開けません。
そこで、今回はロックファイルの作成に*symlink()関数を使用しないようにコードを修正することで対策したいと思います。(幸いなことにsymlink()関数を使わずにlink()*関数で実装しているコードも#ifdef
で記述されていますのでこちらを使います)
【補足】
*symlink()関数は第一引数に「リンク元のパス」、第二引数に「リンク先(作成するシンボリックリンク)のパス」を渡すのですが、MSYS以外のシステム -ファイルシステムでシンボリックリンクが扱えるシステム- では、第一引数のリンク元に存在しないパスを入れてもエラーとして扱わずリンク先が無効なシンボリックリンクを作成し正常終了します。
zshでは上記のようなsymlink()*関数の仕様を利用して、第一引数にロックを保持しているプロセスID等の情報を入力したリンク先が無効なシンボリックリンクを作成してロックファイルとして利用しているのです。
ところがMSYSではシンボリックリンクが扱えないため、*symlink()*関数は特殊な仕様になっており、内部的に単なるファイルコピーが実行されます。その為、第一引数に入力したリンク元が無効な場合はコピーが出来ずにエラーを返します。zshはこのエラーに当然対応していないため失敗するようです。
##【zshをビルドする環境の準備】
それではMSYS2上でzshをビルドするためのコンパイル環境の構築から開始します。
まず、コンパイラ(gcc)がインストールされていない場合はインストールします。
$ pacman -S gcc gcc-libs
...
$ gcc --version
gcc (GCC) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
次にヘッダファイル・ライブラリ郡をインストールします。
$ pacman -S base-devel
$ pacman -S base-devel
:: There are 52 members in group base-devel:
:: リポジトリ msys
1) asciidoc 2) autoconf 3) autoconf2.13 4) autogen 5) automake-wrapper
6) automake1.10 7) automake1.11 8) automake1.12 9) automake1.13
10) automake1.14 11) automake1.6 12) automake1.7 13) automake1.8
14) automake1.9 15) bison 16) diffstat 17) diffutils 18) dos2unix
19) file 20) flex 21) gawk 22) gdb 23) gettext 24) gperf 25) grep
26) groff 27) help2man 28) intltool 29) lemon 30) libtool 31) libunrar
32) m4 33) make 34) man-db 35) nasm 36) pacman 37) patch
38) patchutils 39) perl 40) pkg-config 41) pkgfile 42) rcs 43) scons
44) sed 45) swig 46) texinfo 47) texinfo-tex 48) unrar 49) wget
50) xmlto 51) yasm 52) yasm-devel
選択して下さい (デフォルト=all): <-特に問題ない場合はそのまま[Enter]
...
大量のパッケージがインストールされますので、しばらく待つと、MSYS2上にコンパイル環境一式が構築されます。
【MSYS2パッケージを作成環境の構築】
次にzshをビルドするためにMSYS2パッケージのリポジトリからMSYS2のパッケージ開発の環境一式を取得します。
リポジトリからの環境取得はgitを使用しますので、もしインストールしていない場合はインストールします。
$ pacman -S git
...
$ git --version
git version 2.2.0
次に適当な作業エリアを作成して
$ mkdir workspace
$ cd workspace
MSYS2のパッケージ開発の環境一式を取得します
$ git clone https://github.com/Alexpux/MSYS2-packages.git
...
$ cd MSYS2-packages
$ ls
apr mpfr
apr-util msys2-installer
asciidoc msys2-keyring
aspell msys2-runtime
aspell-en msys2-unlocker
autoconf msys2-w32api-headers
autoconf2.13 msys2-w32api-runtime
autogen nano
automake1.10 nano-syntax-highlighting-git
automake1.11 nasm
automake1.12 ncurses
...
これzshをビルドする為の環境がすべてそろいました。
【zshをビルドする】
今回はzshを作るので*/zsh*ディレクトリに移動します。
$ cd zsh
$ ls
add-pwd-W-option.patch msysize.patch zprofile zsh-doc.install
Makefile.in.patch PKGBUILD zsh.install
今回の「ロックファイルの作成にsymlink()関数を使用しないようにする」為のソースコード修正は単純にhist.c の#ifdef SYMLINK
の行を全て#if 0
に置き換えるだけです。
今回はpatchファイルを作らずに単純にsedを使って書き換えることにします。
これはzshディレクトリ以下にあるPKGBUILDファイルを編集して
...
patch -p0 -i "${srcdir}/Makefile.in.patch"
patch -p1 -i "${srcdir}/add-pwd-W-option.patch"
patch -p1 -i "${srcdir}/msysize.patch"
sed -i -e 's/ifdef HAVE_SYMLINK/if 0/g' Src/hist.c <------この行を追加
...
と一行追加するだけでOKです。
早速パッケージを作成してみます。パッケージの作成はmakepkgコマンドを使用します。
$ makepkg -s
==> パッケージを作成: zsh 5.0.7-3 (2014年 11月 30日 日曜日 18:05:20 )
==> ランタイムの依存関係を確認...
==> ビルドタイムの依存関係を確認...
==> ソースを取得...
...
(中略)
...
==> エラー: ファイルが整合性チェックをパスしませんでした!
???
私の環境でばなぜかエラーがでましたので、とりあえずチェックサム検証をスキップすることで対応します。
$ makepkg -s --skipchecksums
==> パッケージを作成: zsh 5.0.7-3 (2014年 11月 30日 日曜日 18:05:20 )
==> ランタイムの依存関係を確認...
==> ビルドタイムの依存関係を確認...
==> ソースを取得...
...
(中略)
...
==> インストールを整理...
-> 不要なファイルを削除...
-> libtool ファイルを削除...
-> man と info ページを圧縮...
-> バイナリとライブラリから不要なシンボルを削除...
==> パッケージを作成 "zsh-doc"...
-> .PKGINFO ファイルを生成...
-> install ファイルを追加...
-> .MTREE ファイルを生成...
-> パッケージの圧縮...
==> 作成完了: zsh 5.0.7-3 (2014年 11月 30日 日曜日 18:11:49 )
このように表示されると完成です。再度zshディレクトリを見ると、
$ ls
add-pwd-W-option.patch pkg zsh-5.0.7.tar.bz2
config.guess PKGBUILD zsh-5.0.7-3-x86_64.pkg.tar.xz
config.sub src zsh-5.0.7-doc.tar.bz2
Makefile.in.patch zprofile zsh-doc.install
msysize.patch zsh.install zsh-doc-5.0.7-3-x86_64.pkg.tar.xz
パッケージファイル zsh-5.0.7-3-x86_64.pkg.tar.xz が作成されているのがわかります。
早速パッケージファイルをインストールしてみます。
$ pacman -U zsh-5.0.7-3-x86_64.pkg.tar.xz
パッケージをロード...
警告: zsh-5.0.7-3 は最新です -- 再インストール
...
...
##【動作確認】
今回の修正で履歴ファイルが扱えるかを確認をします。
~/.zshrcに
HISTFILE=~/.zsh_history
HISTSIZE=10000
SAVEHIST=10000
を追加してzshを起動してみます。
% ls -a
. .bash_history .bashrc .minttyrc .zcompdump .zshrc
.. .bash_profile .inputrc .tmux.conf .zsh_history work
問題なく履歴ファイルが作成されているようです。
中身を確認してみると・・
% cat .zsh_history
: 1417167947:0;ls -a
: 1417167964:0;cat .zsh_history
$
問題無く履歴が書き込まれているようです。