hnwの日記

phpallコマンドでPHPの全バージョンの挙動を試す


追記:1/13頃まで、install-all-php.shにバグがありました。ごめんなさい。今は全バージョンを一気にコンパイルできるはずです。


第38回PHP勉強会でも紹介しましたが、私はPHP5.0.0〜PHP5.2.8までの全バージョンのPHPバイナリを持っています。これはPHPのバージョン間の差異やバグを確認したいときなどに便利です。(参考:「第38回PHP勉強会に参加してきました」)


このような環境を作る方法について紹介します。基本的には各バージョンのPHPコンパイルするだけですが、コンパイルが通らない場合があるのでその回避方法と、かんたんインストールスクリプトを用意したのでそれを紹介します。また、全てのバージョンのPHPを順に実行するコマンドphpallについても紹介します。

PHP5をgcc4環境でコンパイルする

実は、PHP 5.0.0-5.0.3はgcc4 でコンパイルできないという問題点があります。gcc4でコンパイルするためには、http://bugs.php.net/bug.php?id=32150 の通り、Zend/zend_modules.h を修正する必要があります。


こんなときgcc3でコンパイルするのも一つの手ですが、MacOSX10.4や10.5ではgcc3が提供されていません。今後このような環境が増えてくるのではないでしょうか。


また、PHP 5.2.0-5.2.3は./configureの途中で下記のように怒られてしまいます。

configure: error: installation or configuration problem: C++ compiler cannot create executables.

原因は追いかけていませんが、autoconfでconfigureスクリプトを作り直すと問題なくバイナリのビルドまで通ります。


Ubuntu 8.04環境のgcc4で実験しましたが、上記の2点以外は特に問題なくコンパイルできました。

MacOSX上でのコンパイル

MacOSX上でコンパイルするためには他にも工夫が必要です。


まず、MacOSX環境でPHP 5.0.0-5.0.5をコンパイルするためにはCFLAGS='-fnested-functions'の指定が必要です。というのも、configureスクリプト中でコンパイルしているCプログラムがXcodegccではコンパイルできないため、configureで間違った判定をしてしまうのです。(参考:http://developer.apple.com/jp/technotes/tn2006/tn2161.html


また、PHP 5.0.0-5.0.5では鬼車同梱のlibxml2とLeopard標準のlibxml2がコンフリクトしてしまう問題があります。これはどちらも使わずに最新のlibxml2を使えば問題なく動くようですので、私はHomebrewのlibxml2を利用することにしました。

らくらくコンパイル&インストール

上記の手順を全部含んだシェルスクリプトを作りました。まず作業ディレクトリにphpのパッケージを必要なだけダウンロードして、PHPを片っ端からインストールするシェルスクリプトinstall-all-php.sh)を実行してください。パッケージを展開してコンパイルして、出来たバイナリを$HOME/binにphp-5.?.?という名前でインストールします。


事前にflexやbisonやlibxml2やlibiconvなど必須パッケージのインストールをお忘れなく。

$ ls php-*.tar.*
php-5.0.0.tar.gz  php-5.1.0.tar.gz   php-5.1.6.tar.bz2  php-5.2.5.tar.bz2
php-5.0.1.tar.gz  php-5.1.1.tar.gz   php-5.2.0.tar.bz2  php-5.2.6.tar.bz2
php-5.0.2.tar.gz  php-5.1.2.tar.gz   php-5.2.1.tar.bz2  php-5.2.7.tar.bz2
php-5.0.3.tar.gz  php-5.1.3.tar.gz   php-5.2.2.tar.bz2  php-5.2.8.tar.bz2
php-5.0.4.tar.gz  php-5.1.4.tar.bz2  php-5.2.3.tar.bz2
php-5.0.5.tar.gz  php-5.1.5.tar.bz2  php-5.2.4.tar.bz2
$ wget http://github.com/hnw/phpall/raw/master/install-all-php.sh
$ sh ./install-all-php.sh


下記の手順でも同じことですが、それぞれ時間がかかるのでシェルスクリプト一発の方がおすすめです。

$ for i in php-*.tar.gz ; do tar xvzf $i; done ; for i in php-*.tar.bz2 ; do tar xvjf $i; done
$ for i in php-5.0.[0123] ; do cd $i ; perl -i.bak -pe 's|#include "zend.h"|#include "zend.h"\n#include "zend_compile.h"|' Zend/zend_modules.h; cd ..; done
#MacOSXのみ
$ for i in php-5.0.? ; do cd $i ; CFLAGS='-fnested-functions' ./configure --with-libxml-dir=/opt/local -with-iconv=/opt/local --enable-mbstring --disable-cgi ; make ; cd .. ; done
#MacOSX以外
$ for i in php-5.0.? ; do cd $i ; ./configure --enable-mbstring --disable-cgi ; make ; cd .. ; done
$ for i in php-5.[12].? ; do cd $i ; ./configure --enable-mbstring --disable-cgi || ( autoconf && ./configure --enable-mbstring --disable-cgi ) ; make ; cd .. ; done
$ for i in php-5.?.? ; do install $i/sapi/cli/php $HOME/bin/$i; done

phpallコマンド

上記のphpたちを簡単にテストするためのシェルスクリプトphpallを作りました。$HOME/bin(またはphpをインストールしたディレクトリ)にインストールして使います。


phpallコマンドはPHPのコードを引数として受け取り、それを実行します。実行結果が標準出力に出力がない場合はコード全体をvar_dump()で囲んで再実行します。また、引数がファイルだった場合はPHPとして実行します。

$ phpall '"0x1"=="1e0"'
php-5.0.0: bool(true)
php-5.0.1: bool(true)
php-5.0.2: bool(true)
php-5.0.3: bool(false)
php-5.0.4: bool(false)
php-5.0.5: bool(false)
php-5.1.0: bool(false)
php-5.1.1: bool(false)
php-5.1.2: bool(false)
php-5.1.3: bool(false)
php-5.1.4: bool(false)
php-5.1.5: bool(false)
php-5.1.6: bool(false)
php-5.2.0: bool(false)
php-5.2.1: bool(true)
php-5.2.2: bool(true)
php-5.2.3: bool(true)
php-5.2.4: bool(true)
php-5.2.5: bool(true)
php-5.2.6: bool(true)
php-5.2.7: bool(true)
php-5.2.8: bool(true)


これさえあれば簡単にPHPの実験ができますね!


注意点ですが、PHPの複文(foo(123);bar("str");など)を実行して標準出力が空だった場合も全体をvar_dump()で囲んで再実行してしまい、結果として全バージョンでエラーになってしまいます。これは現時点でのphpallのバグです。複文を実行したい場合は明示的にprint_r()やvar_dump()してください。

githubにプロジェクトを作りました

中身はシェルスクリプト2つだけですが、githubで管理してみました。


もし不具合などがあった場合は、よろしければissueやPull Requestなど頂ければできる範囲で対応いたします。