phpizeによるPHP拡張機能のインストール
phpizeによるPHP拡張機能のインストール方法を記す。
3種類のPHPの拡張機能のインストール方法
PHP本体に拡張機能 (モジュール) を追加する方法が3種類ある。
それぞれの方法とその利点・欠点を以下の表に整理した。
方法 | 説明 | 利点 | 欠点 |
---|---|---|---|
組み込み | PHPのビルド時に–with-xxxで拡張機能を指定。 |
|
|
pecl | pecl installで拡張機能をインストール。 |
|
|
phpize | 拡張機能をビルド・インストール。 |
|
|
組み込みはPHPのソースコードビルド時のconfigureのオプションで–enable-xxxや–with-xxで拡張機能を有効化する方法だ。この方法は,PHPのビルド時にしか機能を有効化できないため,後で機能追加する場合に,わざわざPHP本体の再ビルドが必要になるので手間だ。PHPの拡張機能は74個もあるため,ビルド時に全機能を有効化するのは現実的ではない。
peclはパッケージマネージャーのAPTやyumと似ている。コマンドを実行することで,自動的にPECLリポジトリーからパッケージをダウンロード・ビルドしてPHPに拡張機能を追加してくれる。ただし,以下2点の欠点がある。
- 使用しているphpの
extension_dir
(例:lib/php/extensions/debug-zts-YYYYMMDD/
) にインストールするため,場合によっては管理者権限が必要。 - 拡張機能がpeclのリポジトリーに登録されていないとダメ。
1点目は設定でインストール場所を変更できそうなので問題ないかもしれない。しかし,2点目が大きい。例えば,拡張機能のzlibとmbstringはPECLリポジトリーに存在しないため,peclからインストールできない。そのため,PHPの拡張機能はpeclで全てを有効化できない。ここが非常に惜しい。
phpizeは役割としては組み込みとpeclの中間に位置しており,低レベルで柔軟な方法だ。PECLリポジトリーやPHPのソースコード内のext/ディレクトリー配下に存在する拡張機能のソースコードを自分でビルドする。
ビ ルド時にphpizeを実行することで,使用するphp用の拡張機能のライブラリー (.so) をビルドし,インストールする。インストールせずに,ビルドの段階で止めることもできる。ビルド時にphp-configコマンドを参照し,phpの設定に応じたビルドを行うため,php-configが存在しないと使えない。ただし,それ以外の場合であれば,peclと異なりPHPの全拡張機能に対応できる。そのため,phpizeはPHPの拡張機能を追加で有効化する場合の最善の方法だろう。
そこで,phpizeによるPHPの拡張機能の有効化方法を解説する。
phpizeによる手順概要
まず,phpizeによるビルド・拡張機能の有効化手順を解説する。PHPの拡張機能は共有ライブラリー (.so) 形式であるため,PHPのバージョンが違うと適用できないことに注意する。
CGI版のphpの拡張機能のビルド時など,システム標準以外のphp向けに拡張機能をビルドする時は,./configure
の--with-php-config
オプションで対象のphp向けのphp-configをフルパスで指定する (参考: PHP: Compiling shared PECL extensions with phpize – Manual)。
インストールしたくない場合,make install
を実行しなければ拡張機能はインストールはされない。その場合,modulesディレクトリーに拡張機能のライブラリーが格納されているので,必要に応じてこのファイルを参照する。
設定ファイルのextension指令は拡張機能1個につき,1回ずつ記入する。複数個の拡張機能を有効化する場合,その数だけextension =
を記入する。サンプルのphp.iniに記載がある通り,カンマ区切りで複数個指定できないので注意する。
拡張機能を標準のextension_dir (php -i grep | ^extension_dir
で確認可能) 以外に格納している場合,絶対パスで指定することもできる。
ネット上の事例では,拡張子.soや.dllを記入している例が多い。しかし,末尾の拡張子は将来の廃止事項となっているので,拡張子は省略しよう。
拡張機能の依存情報
拡張機能のビルドに外部ライブラリーが必要なことがある。必要なライブラリーは拡張機能のRequirementsのページに明記されている (例: https://www.php.net/manual/en/zip.requirements.php)。
確認できた拡張機能ごとの依存関係を以下の表に示す。
拡張機能 | 依存先 |
---|---|
cURL | libcurl 7.10.5+ |
GD | PHPに付属しているので,libgd自体は不要。ただし,実際の画像処理には対応する画像のライブラリー (gif, jpeg, png, xpm, freetype) が必要。 |
intl | ICU 50.1+ |
mbstring | なし |
MYSQL Improved Extension (mysqli) | なし |
MySQL Native Driver (mysqlnd) | OpenSSL (SHA-256認証対応) |
openssl | OpenSSL 1.0.1+ |
pdo | なし |
pdo_mysql | なし |
zend_test | |
zip | libzip |
zlib | zlib |
確認できたものがあれば,随時追記していく。
インストール手順
具体的なインストールコマンドを記す。
項目 | 説明 |
---|---|
配布元 | |
リポジトリー | |
手順 | PHP: Compiling shared PECL extensions with phpize – Manual |
依存先 (必須) | |
依存元 | Nextcloud, Tiny Tiny RSS, GNU Social, Kanboard |
日付 | 拡張機能 | OS | 依存関係 |
---|---|---|---|
2019-04-28 | cURL, GD, mbstring, OpenSSL, zip, zlib | Ubuntu 18.04 | PHP 7.3.4, GNU Make 4.2.1, GCC 7.4.0, cURL 7.64.0, OpenSSL 1.1.1a, libzip 1.5.2, zlib 1.2.11 |
2019-05-04 | zend_test | Ubuntu 18.04 | PHP 7.3.4, GNU Make 4.2.1, GCC 7.4.0 |
MOD変数にインストール対象の拡張機能名を指定して,1個ずつインストールしている。必要に応じてMOD変数を書き換えてインストールすればよいだろう。
config.m4の欠如
zlibをビルドしようとphpizeコマンドを実行すると,以下のエラーが表示された。
phpize
Cannot find config.m4. Make sure that you run '/home/senooken/.local/bin/phpize' in the top level source directory of the module
zlibや一部の拡張機能でconfig.m4が存在しないのが問題のようだ。代わりに,config.m4の代わりにはconfig0.m4がある。
他にもconfig.m4が存在しない拡張機能が存在するか以下のコマンドで確認してみた。
find . -name "config?.m4" | sort
./date/config0.m4 ./libxml/config0.m4 ./mysqlnd/config9.m4 ./openssl/config0.m4 ./pcre/config0.m4 ./recode/config9.m4 ./sqlite3/config0.m4 ./zlib/config0.m4
config0.m4の他にconfig9.m4が存在するケースがあることがわかった。また,recode拡張機能のようにconfig9.m4とconfig.m4が両方共存在するケースもあった。
ひとまず,phpize実行前に以下のコマンドでconfig.m4が存在しない場合にconfig.m4へのシンボリックリンクを貼ることで対応した。
[ -e config.m4 ] || [ -e config?.m4 ] && ln -fs config?.m4 config.m4
なぜconfig.m4が一部の拡張機能に存在しないのか調べてみた。しかし,以下で同じ質問がある程度で,はっきりとした理由はわからなかった。
PHP Install — Why does ext/zlib have config0.m4 instead of config.m4
ひとまずシンボリックリンクを貼ることで対応できたのでよしとする。
拡張機能ごとの対応
cURLのmake test失敗
PHP 7.3.4のcurl 7.64.0 (OpenSSL 1.1.1a, zlib 1.2.11) のmake testが失敗している。
===================================================================== FAILED TEST SUMMARY --------------------------------------------------------------------- Bug #76675 (Segfault with H2 server push write/writeheader handlers) [tests/bug76675.phpt] =====================================================================
サーバー関係のテストで失敗しているようだが,原因がわからなかった。
ローカル環境で検証したいだけなので,遺憾だがそのままmake installした。
OpenSSLのmake test失敗
PHP 7.3.4のOpenSSL (OpenSSL 1.1.a) の拡張機能のmake testが失敗する。
===================================================================== FAILED TEST SUMMARY --------------------------------------------------------------------- #46127 php_openssl_tcp_sockop_accept forgets to set context on accepted stream [tests/bug46127.phpt] Bug #48182: ssl handshake fails during asynchronous socket connection [tests/bug48182.phpt] Bug #54992: Stream not closed and error not returned when SSL CN_match fails [tests/bug54992.phpt] Bug #65538: SSL context "cafile" supports stream wrappers [tests/bug65538_001.phpt] Bug #65538: SSL context "cafile" supports phar wrapper [tests/bug65538_003.phpt] Bug #65729: CN_match gives false positive when wildcard is used [tests/bug65729.phpt] Bug #68265: SAN match fails with trailing DNS dot [tests/bug68265.phpt] Bug #68879: Match IP address fields in subjectAltName checks [tests/bug68879.phpt] Bug #68920: peer_fingerprint input checks should be strict [tests/bug68920.phpt] Bug #69215: Crypto servers should send client CA list [tests/bug69215.phpt] Bug #72333: fwrite() on non-blocking SSL sockets doesn't work [tests/bug72333.phpt] Bug #74159: Writing a large buffer to non-blocking encrypted streams fails [tests/bug74159.phpt] Bug #76705: unusable ssl => peer_fingerprint in stream_context_create() [tests/bug76705.phpt] Bug #76705: feof might hang on TLS streams in case of fragmented TLS records [tests/bug77390.phpt] capture_peer_cert context captures on verify failure [tests/capture_peer_cert_001.phpt] openssl_get_cert_locations() tests [tests/openssl_get_cert_locations_basic.phpt] Testing peer fingerprint on connection [tests/openssl_peer_fingerprint_basic.phpt] Peer verification enabled for client streams [tests/peer_verification.phpt] Peer verification matches SAN names [tests/san_peer_matching.phpt] Capture SSL session meta array in stream context [tests/session_meta_capture.phpt] sni_server [testsっっs/sni_server.phpt] sni_server with separate pk and cert [tests/sni_server_key_cert.phpt] Basic bitwise stream crypto context flag assignment [tests/stream_crypto_flags_001.phpt] TLSv1.1 and TLSv1.2 bitwise stream crypto flag assignment [tests/stream_crypto_flags_002.phpt] Server bitwise stream crypto flag assignment [tests/stream_crypto_flags_003.phpt] Specific protocol method specification [tests/stream_crypto_flags_004.phpt] security_level setting to prohibit cert [tests/stream_security_level.phpt] Verify host name by default in client transfers [tests/stream_verify_peer_name_001.phpt] Allow host name mismatch when "verify_host" disabled [tests/stream_verify_peer_name_002.phpt] Host name mismatch triggers error [tests/stream_verify_peer_name_003.phpt] Specific crypto method for ssl:// transports. [tests/streams_crypto_method.phpt] tls stream wrapper with min version 1.0 and max version 1.1 [tests/tls_min_v1.0_max_v1.1_wrapper.phpt] tls stream wrapper [tests/tls_wrapper.phpt] tlsv1.0 stream wrapper [tests/tlsv1.0_wrapper.phpt] tlsv1.1 stream wrapper [tests/tlsv1.1_wrapper.phpt] tlsv1.2 stream wrapper [tests/tlsv1.2_wrapper.phpt] =====================================================================
./bug46127.sh
Warning: stream_socket_client(): unable to connect to ssl://127.0.0.1:64321 (Connection refused) in /home/senooken/.local/src/php/ext/openssl/tests/ServerClientTestCase.inc(118) : eval()'d code on line 10 Warning: fgets() expects parameter 1 to be resource, bool given in /home/senooken/.local/src/php/ext/openssl/tests/ServerClientTestCase.inc(118) : eval()'d code on line 12
なんか,ssl://で接続できていない。
openssl s_client -connect localhost
139995254880064:error:0200206F:system library:connect:Connection refused:crypto/bio/b_sock2.c:110: 139995254880064:error:2008A067:BIO routines:BIO_connect:connect error:crypto/bio/b_sock2.c:111: connect:errno=111
ApacheのSSLが有効になっていないのが原因だろう。先にApacheのSSLを有効化する。
Apacheに証明書をインストールして,mod_sslを有効化すると,エラーが減る。
SSLを有効化して実行すると応答がない。
./bug46127.sh
試しに,OSにインストールされているphpで実行すると警告が出る。
/usr/bin/php bug46127.php
PHP Warning: stream_socket_server(): unable to connect to ssl://127.0.0.1:64321 (Address already in use) in /home/senooken/.local/src/php/ext/openssl/tests/ServerClientTestCase.inc(107) : eval()'d code on line 7 PHP Warning: stream_socket_accept() expects parameter 1 to be resource, boolean given in /home/senooken/.local/src/php/ext/openssl/tests/ServerClientTestCase.inc(107) : eval()'d code on line 10 PHP Warning: fwrite() expects parameter 1 to be resource, boolean given in /home/senooken/.local/src/php/ext/openssl/tests/ServerClientTestCase.inc(107) : eval()'d code on line 11
原因がわからず,どうしてもOpenSSLの拡張機能のmake testが失敗する。
やむを得ないので,make testは成功していないが,そのままmake installした。
intl
PHP 7.3.4, ICU 50.2のmake checkが失敗した。
===================================================================== FAILED TEST SUMMARY --------------------------------------------------------------------- spoofchecker with locale settings [tests/spoofchecker_003.phpt] =====================================================================
対処方法がわからないため,やむを得ずそのままインストールした。
MySQL関係
mysqlnd
./configure実行時に以下のエラーが出た。
checking for pkg-config... /usr/bin/pkg-config configure: error: Cannot find OpenSSL's <evp.h>
configureを確認したところ,PHP_OPENSSL_DIR変数でOpenSSLの配置場所を検知していた。configureでなぜ自動検知できないか不明だが,configure実行時に以下のように環境変数を指定することでこの問題に対処した。
case $mod in
mysqlnd) PHP_OPENSSL_DIR="$LOCAL" ./configure;;
*) ./configure;;
esac
テストも失敗せずに成功したのでインストールした。以下のコマンドで拡張機能が有効になっていることを確認すると,エラーが出ていた。
php -m | grep mysql
PHP Warning: PHP Startup: Unable to load dynamic library 'mysqlnd' (tried: /home/senooken/.local/stow/php-7.3.4/lib/php/extensions/debug-zts-20180731/mysqlnd (/home/senooken/.local/stow/php-7.3.4/lib/php/extensions/debug-zts-20180731/mysqlnd: cannot open shared object file: No such file or directory), /home/senooken/.local/stow/php-7.3.4/lib/php/extensions/debug-zts-20180731/mysqlnd.so (/home/senooken/.local/stow/php-7.3.4/lib/php/extensions/debug-zts-20180731/mysqlnd.so: undefined symbol: _tsrm_ls_cache)) in Unknown on line 0
mysqlndが参照している_tsrm_ls_cache関数が存在しないためエラーが出ている。TSRMはPHPのスレッド管理の機能である。
この問題の対処方法がわからない。mysqlndは依存関係がないこともあり,やむを得ずPHP本体のビルド時に有効化することで暫定的に対応する。
mysqli
インストール後,拡張機能の有効化を確認するとエラーが出ていた。
php -m | grep mysql
PHP Warning: PHP Startup: Unable to load dynamic library 'mysqli' (tried: /home/senooken/.local/stow/php-7.3.4/lib/php/extensions/debug-zts-20180731/mysqli (/home/senooken/.local/stow/php-7.3.4/lib/php/extensions/debug-zts-20180731/mysqli: cannot open shared object file: No such file or directory), /home/senooken/.local/stow/php-7.3.4/lib/php/extensions/debug-zts-20180731/mysqli.so (/home/senooken/.local/stow/php-7.3.4/lib/php/extensions/debug-zts-20180731/mysqli.so: undefined symbol: mysqlnd_global_stats)) in Unknown on line 0
参照先のmysqlndの関数が見つからないためエラーが出ている。
しかし,肝心のmysqlnd拡張機能のインストールが失敗しており,こちらも有効にできない。そのため,やむを得ずPHP本体のビルド時に有効化して暫定的に対応する。
pdo_mysql
インストール後,拡張機能の有効化を確認するとエラーが出た。
php -m | grep mysql
PHP Warning: PHP Startup: Unable to load dynamic library 'pdo_mysql' (tried: /home/senooken/.local/stow/php-7.3.4/lib/php/extensions/debug-zts-20180731/pdo_mysql (/home/senooken/.local/stow/php-7.3.4/lib/php/extensions/debug-zts-20180731/pdo_mysql: cannot open shared object file: No such file or directory), /home/senooken/.local/stow/php-7.3.4/lib/php/extensions/debug-zts-20180731/pdo_mysql.so (/home/senooken/.local/stow/php-7.3.4/lib/php/extensions/debug-zts-20180731/pdo_mysql.so: undefined symbol: mysqlnd_debug_std_no_trace_funcs)) in Unknown on line 0
参照先のmysqlndの関数が見つからないためエラーが出ている。
しかし,肝心のmysqlnd拡張機能のインストールが失敗しており,こちらも有効にできない。そのため,やむを得ずPHP本体のビルド時に有効化して暫定的に対応する。
“phpizeによるPHP拡張機能のインストール” に対して3件のコメントがあります。