PHPのインストール

数多くのWebアプリケーションで利用されているPHPをソースコードからインストールする。

インストール手順

インストール情報
項目 説明
配布元 PHP: Hypertext Preprocessor
リポジトリー
手順
依存情報 PHP: Installation on Unix systems – Manual
依存先 (必須) Make (GNU Make)
依存先 (任意)
  • Web server (Apache HTTP Server or Nginx or Lighttpd)
  • リポジトリーからのビルド用: Autoconf, Automake 1.4+, libtool 1.4.3+, rec2 0.13.4+, bison 2.4+
  • GNU Readline: configureに--with-apxs2指定時のmake testで必要
依存元 PHP拡張機能, Nextcloud, Tiny Tiny RSS, GNU Social, Kanboard
インストール手順
sh -eux <<-"EOT"
LOCAL=~/.local J=$(grep -cs '^processor' /proc/cpuinfo || echo 2)
PKG=php VER=7.3.4 TAG=$PKG-$VER
mkdir -p "$LOCAL/src"
cd "$LOCAL/src"

if command -v git >/dev/null; then
  [ -e $PKG ] || git clone --depth 1 git://git.php.net/php-src.git $PKG
  cd $PKG
  git fetch --depth 1 origin tag $TAG
  git checkout -f $TAG
  git clean -dfX
  ./buildconf --force
else
  [ -e $PKG-$VER ] || wget http://jp2.php.net/distributions/$PKG-$VER.tar.xz
  tar -xf $PKG-$VER.*
  cd $PKG-$VER
  make -kj $J distclean clean || :
fi

./configure --prefix="$LOCAL/stow/$PKG-$VER" --with-config-file-path="$LOCAL/etc" \
  --with-apxs2 --enable-debug --with-mysqli --with-pdo-mysql
make -j $J
if command -v expect >/dev/null; then
  expect -c "set timeout 999; spawn make -j $J test; "'expect "\r\nFAILED TEST" {expect Yns; send s\n; expect " "; exit 1} Yns {send s\n; expect " "; exit 0}'
else
  make -j $J NO_INTERACTION=1 test
fi
make -j $J datarootdir="$LOCAL/stow/$PKG-$VER/share" install

cd "$LOCAL/stow"
echo $PKG-[0-9]* | xargs -n 1 stow --ignore=dir -D
stow --ignore=dir $PKG-$VER
EOT
インストール例
日付 バージョン OS 依存関係
2019-04-01 7.3.3 Ubuntu 14.04
2019-04-01 7.3.3 Ubuntu 18.04 GNU Make 4.2.1, GCC 7.4.0, Bison 2.7.1, Apache HTTP Server 2.4.39
2019-04-28 7.3.4 Ubuntu 18.04 GNU Make 4.2.1, GCC 7.4.0, Bison 2.7.1, Apache HTTP Server 2.4.39

./buildconf実行時に以下のエラーが出たので,--forceオプションを指定した。

You should not run buildconf in a release package.
use buildconf --force to override this check.

PHPはconfigureの実行時に–withオプションで,組み込み機能 (DB接続,画像処理,SSLなど) の有効化できる。ただし,組み込み機能の有効化には対応するライブラリーが必要がある。PHPの組み込み機能は数が多いので,組み込み機能のPHPのビルド時の有効化は現実的ではない

そこで,configureのオプションに--with-apxs2を指定することで,Apache HTTP Serverのモジュールだけを最低限有効にしてインストールした。ApacheのPHPモジュールはPHPビルド時にしか作られないためだ。

その他の必要な機能はphpizeでPHPのインストール後に個別に有効化する。

ただし,MySQL関係の設定に関してはphpizeでインストールできなかった。幸いなことに,追加の依存関係がないため,PHP本体のビルド時のconfigureに以下のオプションを指定することで有効化した。

--with-mysqli --with-pdo-mysql

なお,マニュアルでは--with-mysqlオプションも指定していたが,このオプションはPHP 7.3.4には存在しなかったので,省いた。

設定ファイルはどのPHPでも共通で使いたいので,PHPの設定ファイルであるphp.iniの配置場所を--with-config-file-path="$LOCAL/etc"で指定した。デフォルトだと,PREFIX/libになっており,パッケージ(php-x.x.x)ごとに設定ファイルが分離してしまうからだ。

make install実行時にdatarootdir="$LOCAL/stow/$PKG-$VER/share"環境変数を指定している。これは,phpのmanをshare配下にインストールするためだ。ここで環境変数を指定しない場合,php配下にインストールされてしまい,他のパッケージとディレクトリー構成が変わってしまう。デフォルトだと,datarootdirはPREFIX/shareであり,問題ないはずなのだが,何故か実際はPREFIX/phpとなっている。しかも,configure実行時の–datarootdirオプションの指定により,変更できなかった。しかたなくmake install時に変数を強制上書きした。PHP 7.3.3と7.3.4で確認したが,これはPHPのバグだと推測する。

make installを実行すると最後に以下のメッセージが表示される。

Wrote PEAR system config file at: /home/senooken/.local/stow/php-7.3.3/etc/pear.conf
You may want to add: /home/senooken/.local/stow/php-7.3.3/lib/php to your php.ini include_path

PEARシステムへのinclude_pathの指定を助言している。今はこの設定が必要かどうか判断できないので,放置する。

PHPのインストールができたら,Apache上での動作設定を行おう。

make testでの注意

PHPのmake testでは,テスト実行後に以下のようにログファイルを送信するかどうかの質問が発生する。

You may have found a problem in PHP.
This report can be automatically sent to the PHP QA team at
http://qa.php.net/reports and http://news.php.net/php.qa.reports
This gives us a better understanding of PHP's behavior.
If you don't want to send the report immediately you can choose
option "s" to save it.  You can then email it to qa-reports@lists.php.net later.
Do you want to send this report now? [Yns]:
make: *** [Makefile:206: test] Error 1

この質問への自動回答には注意が必要だ。例えば,試しに以下のように標準入力を使って回答する。

echo s | make test

すると,以下のテストが確実に失敗する。

FAILED TEST SUMMARY
---------------------------------------------------------------------
Test stream_isatty with redirected STDERR [tests/output/stream_isatty_err.phpt]
Test stream_isatty with redirected STDOUT/STDERR [tests/output/stream_isatty_out-err.phpt]
Test stream_isatty with redirected STDOUT [tests/output/stream_isatty_out.phpt]

これらの項目は,標準入出力に対するテストであり,make test実行時に標準入力を使用しているためにテストに失敗している。

このテスト失敗を回避するには,以下のように環境変数NO_INTERACTION=1を指定して質問を省略する (参考: PHP extensionのmake testに関するTIPS – QiitaRunning the test suite — PHP Internals Book)。

make -j $J NO_INTERACTION=1 test

あるいは,expectコマンドを使い,標準入力を使わずに自動入力することで対応できる。例えば,以下のコマンドを実行すれば,自動入力できる。

expect -c "set timeout 999; spawn make -j $J test; "'expect "\r\nFAILED TEST" {expect Yns; send s\n; expect " "; exit 1} Yns {send s\n; expect " "; exit 0}'

expectコマンドを使う方法は複雑なので,NO_INTERACTION=1を指定すればよいだろう。

なお,インストール手順でビルド環境を分離するためにsh -eux <<-"EOT"のように,shコマンドの標準入力にコマンドを渡している。ここでも標準入力を使っているため,そのままsh -eux <<-"EOT"からまるごと実行すると,やはり確実にmake testが失敗する。これを回避するには,sh -eux <<-"EOT"は飛ばして実行する。あるいは,expectコマンドをインストールしておいて,標準入力を使わずにmake testを実行することで対応する。

インストール手順では,以下のようにexpectコマンドが存在する場合はexpectコマンドでmake testを実行し,存在しなければ,NO_INTERACTION=1を指定してmake testを実行する (この場合,sh -eux <<-"EOT"から実行すると失敗するので,この行は省いて実行する)。

if command -v expect >/dev/null; then
  expect -c "set timeout 999; spawn make -j $J test; "'expect "\r\nFAILED TEST" {expect Yns; send s\n; expect " "; exit 1} Yns {send s\n; expect " "; exit 0}'
else
  make -j $J NO_INTERACTION=1 test
fi

--with-apxs2指定時のmake test失敗

PHPのインストールでは,よくApache HTTP Serverのモジュールを有効にしてインストールする。

その場合,./configureのオプションに--with-apxs2を指定する。このオプションを指定すると,make install時に,ApacheでPHPのモジュールをインストールでき,自動的にhttpd.confに以下の行を追加してくれる。

LoadModule php7_module        modules/libphp7.so

--with-apxs2を指定してmakeを実行すると,libs配下にlibphp7.soが生成される。万が一,Apache HTTP Serverにlibphp7.soがインストールされていなければ,このlibphp7.soを手動でApacheのmodulesディレクトリー (例: ~/.local/apache2/modules) に格納して,上記設定をhttpd.confに記入すれば,ApacheのPHPモジュールが有効になる。PHPモジュールの有無は以下のコマンドで,Apacheで有効なモジュールの一覧から確認できる。

apachectl -M

ただし,--with-apxs2を単体で有効にすると,make testで以下のテストに失敗する (PHP 7.3.3で再現)。

=====================================================================
FAILED TEST SUMMARY --------------------------------------------------------------------- Fundamental breakpoints functionality [sapi/phpdbg/tests/breakpoints_001.phpt] Preserve breakpoints on restart [sapi/phpdbg/tests/breakpoints_002.phpt] Test deleting breakpoints [sapi/phpdbg/tests/breakpoints_003.phpt] Test opcode breakpoints [sapi/phpdbg/tests/breakpoints_004.phpt] Test breakpoint into function context [sapi/phpdbg/tests/breakpoints_005.phpt] Basic function breakpoints [sapi/phpdbg/tests/breakpoints_006.phpt] Test namespaced and non-lowercase breakpoint names [sapi/phpdbg/tests/breakpoints_008.phpt] Bug #73704 (phpdbg shows the wrong line in files with shebang) [sapi/phpdbg/tests/bug73704.phpt] Cleaning must preserve breakpoints [sapi/phpdbg/tests/clean_001.phpt] Test clearing breakpoints [sapi/phpdbg/tests/clear_001.phpt] Properly handle exceptions going to be uncaught [sapi/phpdbg/tests/exceptions_001.phpt] Test exceptions in eval during exception [sapi/phpdbg/tests/exceptions_002.phpt] Ensure proper saving of EX(opline) [sapi/phpdbg/tests/generator_run.phpt] include_once must include only once [sapi/phpdbg/tests/include_once.phpt] Test basic info functionality [sapi/phpdbg/tests/info_001.phpt] A script with die() must end "normally" [sapi/phpdbg/tests/normal_exit.phpt] Test phpdbg_break_next() function [sapi/phpdbg/tests/phpdbg_break_next.phpt] Getting executable lines from custom wrappers [sapi/phpdbg/tests/phpdbg_get_executable_stream_wrapper.phpt] Test phpdbg_*_oplog() functions [sapi/phpdbg/tests/phpdbg_oplog_001.phpt] phpdbg_end_oplog() alone must not crash [sapi/phpdbg/tests/phpdbg_oplog_002.phpt] Test argv passing [sapi/phpdbg/tests/run_001.phpt] Stdin and escaped args being passed to run command [sapi/phpdbg/tests/run_002.phpt] set_exception_handler() in phpdbg [sapi/phpdbg/tests/set_exception_handler.phpt] Test stdin input with breakpoints [sapi/phpdbg/tests/stdin_001.phpt] Test simple recursive watchpoint [sapi/phpdbg/tests/watch_001.phpt] Test simple array watchpoint with replace [sapi/phpdbg/tests/watch_002.phpt] Test simple watchpoint with replace [sapi/phpdbg/tests/watch_003.phpt] Test detection of inline string manipulations on zval watch [sapi/phpdbg/tests/watch_004.phpt] Test proper watch comparisons when having multiple levels of indirection from a zval to its value [sapi/phpdbg/tests/watch_005.phpt] Test multiple watch elements pointing to the same watchpoint [sapi/phpdbg/tests/watch_006.phpt] =====================================================================

内容はphpdbgに関するものだ。試しに,sapi/phpdbg/tests/breakpoints_001.logを確認すると,テストの最後でSegmentation fault (core dumped) が起きていた。実際に,以下のコマンドで,breakpoints_001.phptに記載されているデバッグコマンドを入力してみる。

cd ~/.local/src/php/sapi/phpdbg/tests/
./breakpoints_001.sh <<-EOT
b 3 r b 4 c q
EOT
[Successful compilation of /home/senooken/.local/src/php/sapi/phpdbg/tests/breakpoints_001.php]
prompt> [Breakpoint #0 added at /home/senooken/.local/src/php/sapi/phpdbg/tests/breakpoints_001.php:3]
prompt> [Breakpoint #0 at /home/senooken/.local/src/php/sapi/phpdbg/tests/breakpoints_001.php:3, hits: 1]
>00003: echo $i++;
 00004: echo $i++;
 00005: echo $i++;
prompt> [Breakpoint #1 added at /home/senooken/.local/src/php/sapi/phpdbg/tests/breakpoints_001.php:4]
prompt> 1
[Breakpoint #1 at /home/senooken/.local/src/php/sapi/phpdbg/tests/breakpoints_001.php:4, hits: 1]
>00004: echo $i++;
 00005: echo $i++;
 00006: echo $i++;
prompt> 234
[Script ended normally]
Segmentation fault (core dumped)

たしかに失敗している。この問題の解決のポイントは以下2点だ。

  1. configureのオプションに--enable-debugを指定。
  2. GNU Readlineをインストール

この問題に関しては,「phpdbgでコアダンプ – michihide’s blog」で報告されている通り,GNU Readlineの不足による問題ではないかという話がある。そこで,GNU Readlineをインストールすると解決した。

ただし,理由は不明だが,--enable-debugオプションの指定も必要だった。phpdbgコマンドはデバッガーであり,テストでデバッグの機能を使っているからだと思われる。

なお,--with-apxs2を指定しない場合,このテストはスキップされるようで,テストが失敗することはなく,--enable-debugも指定する必要はない。

--with-apxs2指定時のmake test失敗の問題解決は厄介だったが,なんとか解決できてよかった。

Ubuntu 14.04でのテスト失敗

Ubuntu 14.04でのPHP 7.3.3のビルド時に,make testで以下の項目が失敗していた。

FAILED TEST SUMMARY
---------------------------------------------------------------------
Test setlocale() function : usage variations - Setting all available locales in the platform [ext/standard/tests/strings/setlocale_variation2.phpt]

失敗したテスト (setlocale_variation2) を再度実行して原因を調査する。

cd ~/.local/src/src/php-7.3.3/ext/standard/tests/strings
./setlocale_variation2.sh
*** Testing setlocale() : usage variations ***
-- Test setlocale() with all available locale in the system --
No of locales found on the machine = 36
No of setlocale() success = 35
Expected no of failures = 0
Test FAILED
Names of locale() for which setlocale() failed ...
array(1) {
  [0]=>
  string(10) "es_CU.utf8"
}
Done

どうやら,Ubuntu 14.04でes_CU.utf8のロケールを認識できていないのが原因のようだ。

たしかに,以下のコマンドでロケールをes_CU.utf8に変更しようとするとエラーが出た。

export LC_ALL=es_CU.utf8
bash: warning: setlocale: LC_ALL: cannot change locale (es_CU.utf8): No such file or directory

language support – warning: setlocale: LC_ALL: cannot change locale – Ask Ubuntu」で回答があるように,以下のコマンドでロケールを更新することで,es_CU.utf8が認識できるようになる。

sudo locale-gen es_CU
sudo update-locale LANG=es_CU

これにより,Ubuntu 14.04でもPHP 7.3.3のビルドのmake testが通るようになった。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です