phpbrewで現時点で少し古めのphp7.3.33をインストールした際に、たくさんのエラーが出てそれを乗り越えたのでお伝えします。一つエラーを消すと、新たなエラーが出て、それに対処していくと、結果的にオプションをたくさん付けることになりました。
もくじ
使用した環境
この記事は以下の記事でMac上にWordPress環境を構築する中で、PHPをインストールする際に試行錯誤したものです。
端末 | M2 MacBook Air(2022) |
---|---|
Mac OS | 13.2.1(22D68) |
homebrew | 4.0.20 |
phpbrew | 2.1.0 |
インストールするPHP | 7.3.33 |
必要なライブラリがなくて怒られる
最初はシンプルに以下のようにしてみました。
1 |
$ phpbrew install 7.3.33 +default |
しかし色々エラーが出て失敗しました。
以下のようなエラーに注目しました。
1 2 3 4 5 |
Homebrew prefix "/opt/homebrew/opt/libxml2" does not exist. Homebrew prefix "/opt/homebrew/opt/bzip2" does not exist. Homebrew prefix "/opt/homebrew/opt/mhash" does not exist. Homebrew prefix "/opt/homebrew/opt/pcre" does not exist. Homebrew prefix "/opt/homebrew/opt/openssl@3" does not exist. |
openssl@1.1やpcre2はphpbrew(PHP8.1)をインストールする時にインストールされていましたが、7.3.33とは使うバージョンが違うようですね。
なので、素直に上記で表示されたものHomebrewでインストールします。以下を参考にしました。
1 |
$ brew install libxml2 bzip2 mhash pcre openssl@3 |
zlibの指定をする
再度実行します。
1 |
$ phpbrew install 7.3.33 +default |
先ほどのエラーは消えましたが、以下のようなエラーが出ました。
1 |
checking for the location of zlib... configure: error: zip support requires ZLIB. Use --with-zlib-dir=<DIR> to specify prefix where ZLIB include and library are located |
なので、以下を参考に
PHPBrewでPHPをインストールするときにzlibでエラーが出る場合
1 |
$ phpbrew install 7.3.33 +default +zlib="$(brew --prefix zlib)" |
としたところ、
1 2 3 |
checking if the location of ZLIB install directory is defined... no configure: error: Cannot find zlib |
というようなエラーが出ました。
1 2 |
$ brew --prefix zlib /opt/homebrew/opt/zlib |
とパスは表示されるのでzlibはインストールされていると思っていたのですが、インストールされていなかったようです。
1 2 |
$ zlib zsh: command not found: zlib |
なので、
1 |
$ brew install zlib |
でインストールします。
改めて以下をするとこのエラーは無くなりました。
1 |
$ phpbrew install 7.3.33 +default +zlib="$(brew --prefix zlib)" |
でも、zlibをインストール後も、以下となるのが不思議です。
1 2 |
$ zlib zsh: command not found: zlib |
openssl@1.1の指定
しかし今度は以下のエラーが出ます。
1 2 3 4 5 6 7 8 9 10 11 |
Error: Make failed: The last 5 lines in the log file: /opt/homebrew/opt/openssl@3/include/openssl/rsa.h:295:29: note: passing argument to parameter 'rsa' here RSA *rsa, int padding); ^ 107 warnings and 1 error generated. make: *** [ext/openssl/openssl.lo] Error 1 |
なので、今度は以下の記事に従って次のようにします。
phpbrew で PHP 7.1 / 8.0 をインストールした( + openssl / + gd )
1 |
$ phpbrew install 7.3.33 +default +zlib="$(brew --prefix zlib)" +openssl=/opt/homebrew/opt/openssl@1.1 |
これでこのエラーは消えました。opensslは上記記事や以下によると、バージョンは3ではなくて良さそうす。というか3だとダメというように読めます。
1.1はphpbrewをインストールした時に一緒にインストールされました。3は先ほどの手順で無いと怒られたので入れました。なぜ使わないのに入れさせられたかがわかりません。
あと、パスの指定の仕方はもしかしたら、zlibと同じく "$(brew --prefix openssl@1.1)"でも良いかもしれませんが、試していません。参考にした記事のままやっているから、この辺りの統一感は無いかもしれません。
pcre2の指定
次も、長いエラーが出ますが、ポイントとなるのは以下の部分です。
1 2 3 4 5 6 7 |
Generating phar.php Generating phar.phar PEAR package PHP_Archive not installed: generated phar will require PHP's phar extension be enabled. make: *** [ext/phar/phar.phar] Bus error: 10 |
以下に従って次のようにしてみます。
M1 Macでarm64のHomebrewとPHPBrewでPHP8.0の環境作ってベンチながす
1 |
$ phpbrew install 7.3.33 +default +zlib="$(brew --prefix zlib)" +openssl=/opt/homebrew/opt/openssl@1.1 -- --with-external-pcre=$(brew --prefix pcre2) |
しかし、エラーは変わりません。
どうやら
や
によると、PHP7.3だと--with-external-pcre ではなく、--with-pcre-regexを使うようです。そして7.3以降はPCRE2が必須とのことです。でも、PCREの2がつかない方は、先ほど怒られたので入れました。opensslの3と同じく使わないのになぜ入れさせるのか不思議です。
以下のようにすると
1 |
$ phpbrew install 7.3.33 +default +zlib="$(brew --prefix zlib)" +openssl=/opt/homebrew/opt/openssl@1.1 -- --with-pcre-regex=$(brew --prefix pcre2) |
インストールできました。出力の最下部に以下のように表示されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Congratulations! Now you have PHP with 7.3.33 as php-7.3.33 * To configure your installed PHP further, you can edit the config file(s) at /Users/xxxx/.phpbrew/php/php-7.3.33/etc/cli/php.ini To use the newly built PHP, try the line(s) below: $ phpbrew use php-7.3.33 Or you can use switch command to switch your default php to php-7.3.33: $ phpbrew switch php-7.3.33 Enjoy! |
ただ、以下のようなWarning?は残ったままなのが少し気持ち悪いです。
1 |
Patch failed |
1 |
sh: pear: command not found |
apxs2の指定
参考にしていたページで、Apacheとの連携で、libphp.soという名前(バージョン番号が入る場合もある)のファイルを読み込む部分を、Apacheの設定ファイル、httpd.confに記述する手順があったのですが、そのファイルがどこにあるのかどうしてもわかりません。
色々調べてわかったことなのですが、libphp.soはphpのビルド時にあるオプションを指定しないと生成されないようです。
apxs2というオプションを指定する必要があるそうです。
仕方ないので、一度アンインストールしてインストールしなおします。以下でアンインストールします。
1 |
$ phpbrew purge php-7.3.33 |
この際、確実に使うであろう、MySQLやXdebugに関わるオプションも指定して、再インストールしました。
1 |
$ phpbrew install 7.3.33 +default +zlib="$(brew --prefix zlib)" +openssl=/opt/homebrew/opt/openssl@1.1 -- --with-pcre-regex=$(brew --prefix pcre2) +mysql +debug +apxs2 |
後で分かったことですが、 +debug をつけてもXdebugは使えるようにはならならないということがわかりました。それについては以下に記載しています。
そして、以下で、このオプションはXdebugとは無関係で、このオプション無しでもXdebugは正常に使えることがわかりました。
すると、以下のようなエラーが出ました。
1 2 3 4 5 |
Homebrew formula "libxml2" not found. shell-init: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory shell-init: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory shell-init: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory Error: The current working directory doesn't exist, cannot proceed. |
これはlibxml2以外のイブラリについても出たので、かなりたくさん出ました。
以下によるとHomebrew関連のエラーのようです。カレントディレクトリが存在しない場合は発生するそうです。
というのは、先ほどphpをアンインストールしましたが、その時削除されたディレクトリがカレントになっていたからです。なので、ホームディレクトリに戻って同じコマンドを実行するとこのエラーは消えます。
もう一種類出たエラーがこちらです。
1 2 3 |
checking build system type... Invalid configuration `+mysql': machine `+mysql' not recognized configure: error: /bin/sh ./config.sub +mysql failed |
+mysql +debug +apxs2 などのオプションは -with-pcre-regex より前にないとダメっぽいです。もしかしたら、 -- より前にしないとダメなのかもしれません。なのでこうします。
1 |
$ phpbrew install 7.3.33 +default +mysql +debug +apxs2 +zlib="$(brew --prefix zlib)" +openssl=/opt/homebrew/opt/openssl@1.1 -- --with-pcre-regex=$(brew --prefix pcre2) |
するとまた違ったエラーが出ました。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Exception: apxs binary is not executable: Trace: 0) PhpBrew\Tasks\Apxs2CheckTask->check(PhpBrew\ConfigureParameters) 1) PhpBrew\Tasks\BeforeConfigureTask->run(PhpBrew\Build, PhpBrew\ConfigureParameters) 2) PhpBrew\Command\InstallCommand->build(PhpBrew\Build, PhpBrew\ConfigureParameters) 3) PhpBrew\Command\InstallCommand->execute('7.3.33', '+default', '+mysql', '+debug', '+apxs2', '+zlib=/opt/homebrew/opt/zlib', '+openssl=/opt/homebrew/opt/openssl@1.1', '--', '--with-pcre-regex=/opt/homebrew/opt/pcre2') 4) call_user_func_array([PhpBrew\Command\InstallCommand, 'execute'], ['7.3.33', '+default', '+mysql', '+debug', '+apxs2', '+zlib=/opt/homebrew/opt/zlib', '+openssl=/opt/homebrew/opt/openssl@1.1', '--', '--with-pcre-regex=/opt/homebrew/opt/pcre2']) 5) CLIFramework\CommandBase->executeWrapper(['7.3.33', '+default', '+mysql', '+debug', '+apxs2', '+zlib=/opt/homebrew/opt/zlib', '+openssl=/opt/homebrew/opt/openssl@1.1', '--', '--with-pcre-regex=/opt/homebrew/opt/pcre2']) 6) CLIFramework\Application->run(['/opt/homebrew/bin/phpbrew', 'install', '7.3.33', '+default', '+mysql', '+debug', '+apxs2', '+zlib=/opt/homebrew/opt/zlib', '+openssl=/opt/homebrew/opt/openssl@1.1', '--', '--with-pcre-regex=/opt/homebrew/opt/pcre2']) 7) PhpBrew\Console->runWithTry(['/opt/homebrew/bin/phpbrew', 'install', '7.3.33', '+default', '+mysql', '+debug', '+apxs2', '+zlib=/opt/homebrew/opt/zlib', '+openssl=/opt/homebrew/opt/openssl@1.1', '--', '--with-pcre-regex=/opt/homebrew/opt/pcre2']) 8) require('phar:///opt/homebrew/Cellar/phpbrew/2.1.0/libexec/phpbrew.phar/bin/phpbrew') 9) require('/opt/homebrew/Cellar/phpbrew/2.1.0/libexec/phpbrew.phar') |
apxsのパスが通ってないのかな、と思って確認しました。
1 2 3 4 5 6 7 8 |
$ apxs Usage: apxs -g [-S <var>=<val>] -n <modname> apxs -q [-v] [-S <var>=<val>] [<query> ...] apxs -c [-S <var>=<val>] [-o <dsofile>] [-D <name>[=<value>]] [-I <incdir>] [-L <libdir>] [-l <libname>] [-Wc,<flags>] [-Wl,<flags>] [-p] <files> ... apxs -i [-S <var>=<val>] [-a] [-A] [-n <modname>] <dsofile> ... apxs -e [-S <var>=<val>] [-a] [-A] [-n <modname>] <dsofile> ... |
どこにあるapxsかも調べたら、ちゃんとHomebrewによってインストールされたものでした。
1 2 |
$ which apxs /opt/homebrew/bin/apxs |
しかも、
1 2 |
$ ls -la /opt/homebrew/bin/apxs lrwxr-xr-x@ 1 xxxx admin 31 6 2 16:28 /opt/homebrew/bin/apxs -> ../Cellar/httpd/2.4.57/bin/apxs |
httpdというディレクトリの配下にあるということは、Apacheと一緒にHomebrewでインストールされたということです。というかApacheの一部なのでしょう。
よくわからないですが、明示的にapxsをフルパスで指定してみました。
1 |
$ phpbrew install 7.3.33 +default +mysql +debug +apxs2=/opt/homebrew/bin/apxs +zlib="$(brew --prefix zlib)" +openssl=/opt/homebrew/opt/openssl@1.1 -- --with-pcre-regex=$(brew --prefix pcre2) |
これでようやくインストール成功しました。
後で分かったことですが、ここでのパスの指定もフルパスでなくて "$(which apxs)" でよいことがわかりました。それについては、先程紹介した、8.2.8をインストールした際の記事に記載しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
Congratulations! Now you have PHP with 7.3.33 as php-7.3.33 * We found that you enabled 'mysql' variant, you might need to setup your 'pdo_mysql.default_socket' or 'mysqli.default_socket' in your php.ini file. * To configure your installed PHP further, you can edit the config file(s) at /Users/araky/.phpbrew/php/php-7.3.33/etc/cli/php.ini /Users/araky/.phpbrew/php/php-7.3.33/etc/apache2/php.ini To use the newly built PHP, try the line(s) below: $ phpbrew use php-7.3.33 Or you can use switch command to switch your default php to php-7.3.33: $ phpbrew switch php-7.3.33 888 ; extension=mysqli 889 ; 890 ; When the extension library to load is not located in the default extension 891 ; directory, You may specify an absolute path to the library file: 892 ; 893 ; extension=/path/to/extension/mysqli.so Enjoy! |
MySQLのオプションをつけたから、それ関連の表示が出ています。
ただ相変わらず以下のWarning?は表示されます。
1 |
Patch failed |
1 |
sh: pear: command not found |
httpd.confが勝手に修正されてる
さて、httpd.confにlibphp.soを読み込む設定を書き込むぞと思って、httpd.confを開いてみました。すると、なんとその設定が書き込まれていることを発見しました。
1 |
LoadModule php7_module /opt/homebrew/lib/httpd/modules/libphp7.3.33.so |
httpd.confのタイムスタンプはちょうどインストールが完了したくらいの時刻でした。さらに、同じディレクトリに、httpd.conf.bakというファイルがありました。
diffをとってみたら、
1 2 3 4 5 |
$ diff /opt/homebrew/etc/httpd/httpd.conf /opt/homebrew/etc/httpd/original/httpd.conf 182d181 < LoadModule php7_module /opt/homebrew/lib/httpd/modules/libphp7.3.33.so 533a533 > |
この部分だけ追記されていました。
libphp7.3.33.soのタイムスタンプもインストール完了時の時刻でした。これもそのタイミングで生成されたということです。
これらの自動処理が、phpbrewによってなされたものなのか、phpbrewを使わなくても、PHPをビルドしたらなされるものなのかはわかりません。
とはいえ、これはそのまま使わせてもらうことにします。
ApacheをPHPより先にインストールするべきということ
PHPのインストール時にhttpd.confが書き換わるということは、つまり、PHPより先にApacheをインストールしておく必要があるということです。
もし、Apacheをインストールする前に、phpbrewをインストールしたら、もしかしたら、MacにプリインストールされているApacheのhttpd.confが書き換わるのかもしれません。やってないのでわからないですが。
ApecheとPHPの連携の仕方は3種類ある
apxs2のオプションについて調べている時に学んだのですが、ApacheとPHPの連携の仕方は3種類あります。
- モジュール方式(静的)
- モジュール方式(動的)
- CGI方式
3のCGI方式は、ApacheとPHPが別プロセスとして起動し、互いにやりとりをして動きます。それに対し、1、2のモジュール方式はApacheのプロセスの中でPHPが動きます。なので、一つのプロセスとして動きます。したがって、CGIよりもモジュールの方が速いと思われます。少し古いですが以下の記事にデータがあります。実際は負荷が高い状況でないとモジュール方式の真価は発揮されないようですが。また、細かい話をするとFactCGIというCGIを軽快にしたものもあります。
PHPモジュールモードとCGIモードの違いとパフォーマンスの差を検証
1の静的の方は、Apacheのコンパイル時にPHPのプログラムが、Apacheのバイナリーであるhttpdの中に埋め込まれるそうです。それに対し、2の動的の方はhttpdのバイナリーにはPHPは含まれず、外部から起動時に読み込まれます。当然、一つのバイナリーになっている静的の方が高速だと言われていますが、ベンチマークのデータは見当たりませんでした。
Shared Apache 2.0 Module vs Static Apache Module
モジュール方式(静的)にもデメリットはあります。PHPのバージョンを変える時に、Apacheもビルドしなおす必要があります。モジュール方式(動的)であれば、httpd.confで指定するファイルを変えるだけで切り替えることが可能です。
私は開発環境でPHPのバージョンは頻繁に切り替える可能性があるので、当記事の手順ではモジュール方式(動的)を採用しました。本番環境で大規模なサイトを運営する場合は、モジュール方式(静的)を採用してパフォーマンスの恩恵を受けてもいいかもしれませんね。
apxsというのはモジュール方式(動的)で使うための拡張モジュールをビルドしてインストールするためのツールだそうです。
ちなみに、phpbrewでモジュール方式(静的)で使うための手順は見つけられませんでした。できるのかな。
実際の環境のApacheが、PHPを静的に取り込んでいるか、動的に取り込んでいるか確認するコマンドがあります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
$ httpd -M AH00112: Warning: DocumentRoot [/opt/homebrew/opt/httpd/docs/dummy-host.example.com] does not exist AH00112: Warning: DocumentRoot [/opt/homebrew/opt/httpd/docs/dummy-host2.example.com] does not exist AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using TaisukenoMacBook-Air.local. Set the 'ServerName' directive globally to suppress this message Loaded Modules: core_module (static) so_module (static) http_module (static) mpm_prefork_module (shared) authn_file_module (shared) authn_core_module (shared) authz_host_module (shared) authz_groupfile_module (shared) authz_user_module (shared) authz_core_module (shared) access_compat_module (shared) auth_basic_module (shared) reqtimeout_module (shared) filter_module (shared) mime_module (shared) log_config_module (shared) env_module (shared) headers_module (shared) setenvif_module (shared) version_module (shared) unixd_module (shared) status_module (shared) autoindex_module (shared) dir_module (shared) alias_module (shared) php7_module (shared) |
staticは静的、sharedは動的ということです。31行目でPHPは動的ということがわかります。以下を参考にしました。
Apacheに組み込まれているモジュールの一覧を取得する(httpd -l,httpd -M)
拡張機能でインストールできるもの、できないもの
最初、mysql、xdebug、apxs2のオプションを指定せずにphpをインストールしました。というのは、公式の以下の記載から後からいくらでも追加で入れられるだろうと考えていました。
Installing Extension - The Most Simple Way
まずxdebugで試してみました。
インストールする前に対象のPHPにセットしておく必要があります。というのは
1 |
$ phpbrew switch 7.3.33 |
後で分かったことですが、PHPがバージョンごとにインストールされているディレクトリ配下に拡張機能も配置されるので、どのPHPのバージョンに対してインストールするか指定する必要があるためです。
/Users/xxxxx/.phpbrew/build/php-7.3.33/ext/xdebug/
なので、複数のPHPのバージョンがあってそれぞれでXdebugを使いたいなら、それぞれに対してインストールする必要があるということです。
早速インストールしてみます。以下で詳しく書きましたが、無事この方法でインストールできました。
この流れでapxs2やmysqlについてもインストールできるかやってみました。
1 2 3 |
$ phpbrew ext install apxs2 Downloading https://pecl.php.net/rest/r/apxs2/stable.txt via curl extension [ ] 0.00/3.96KB 0%CurlKit\CurlException: (22) The requested URL returned error: 404 at [https://pecl.php.net/rest/r/apxs2/stable.txt:The requested URL returned error: 404] |
1 2 3 4 |
% phpbrew ext install mysql Downloading https://pecl.php.net/rest/r/mysql/stable.txt via curl extension [ ] 0.00/3.96KB 0%CurlKit\CurlException: (22) The requested URL returned error: 404 at [https://pecl.php.net/rest/r/mysql/stable.txt:The requested URL returned error: 404] |
しかし、上記のようにエラーが出てインストールできませんでした。
apxs2はおそらく、PHPの拡張機能というわけではなく、Apache側の持ち物だからでしょう。mysqlについてはよくわかりませんが、PHPの拡張機能という位置付けではないのでしょう。
この辺りはやはり、PHPのインストール時にオプションで指定しておくべきということでしょう。結局PHPをインストールし直したので、オプションで指定してインストールすることになりました。
Rubyに比べてPHPってやっぱりごちゃごちゃしてる
phpbrewに相当するRubyのrbenvでRubyをインストールする時って、こんなにハマった経験はありません。トリッキーなオプションを設定したこともなく、何事もスマートに済む印象があります。
phpbrewの問題かなと最初思ったのですが、これってPHPという言語のエコシステム全体の問題なのではないかなと思います。