Apache+mod_phpをOSXで野良ビルドし、phpenvでPHPを入れるのに挫折しかけたが諦めなかった話
一つ前のエントリの話から繋がるんですが、OSXにApache+phpの環境を用意したいんですよ。
三行で
さておき
OSXでApache+phpの環境を用意するには色々な方法がありますが、
- XAMPPで入れる
- 最初からはいってるやつをつかう
- Homebrewをつかう
ここらへんが普通でしょう。
どれが良いか一長一短ありますが…
- XAMPPは入れるの楽だが切り替えが面倒ですし
- 最初から入ってるやつは構成やバージョンの変更はできませんし
- Homebrewは提供版だけ使うならよさそうだけど、マルチバージョン等、構成を色々変えるのは難しい
ということで
今回それらは無視して、以下で行きました。
本来tar ballからのビルドで育った人間としては難しい所はないんですが、今回はphpenvをつかいたい。Apache自体はそんなにバージョンアップしなくてもいい。
うまくいけば、OSXネイティブのApache+mod_phpで複数の環境をうまくきりかえて使えるハズ…(続編で紹介)!という感じです。
最初にオチをいいますが、El capitanだとmod_phpのビルドが大変なので、Apache+CGIでPHP、あるいはApache+mod_fcgi+php-fpmの構成を検討した方が良いです。
今回なかば意地になっているのを最初にお伝えしておきます。
(開発環境ではmod_phpほどの速度は必要ないし、cgiのphpで十分でしょう)
したごしらえ
phpenvとhomebrewをセットアップし(省略します)、まずはphpenvでPHPがビルド出来る程度の用意をします。
$ phpenv install 7.0.0
これが通るくらいにはインストールマラソンをこなしておきましょう。まあここらへんはネットでググればすぐ解決します。
後、以下を実行しておきます。多分必要です。*1
$ brew link libxml2 --force $ brew link libressl --force
まずはApacheのビルド
本家からtar.gzなsourceを落としてきて、configure、make all、make allでビルド&インストールします。
先に書きますがコンパイラがみつからない場合があります。ググれば解決策もみつかりますけど以下みたいにすれば解決できます。(Makefileを直してもよい)
sudo ln -s /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/ /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.11.xctoolchain # 10.11はElcapitanなので、Mavericksだと10.10かも
そしてconfigureは注意が必要です。
$ ./configure --prefix /Users/uzulla/bin/apache --enable-load-all-modules --with-libxml2=/usr/local/Cellar/libxml2/2.9.2 --with-ssl=/usr/local/Cellar/libressl/2.3.0/ $ make all $ make install
キモはlibxml2とopensslをHomeBrewのものを指定し、with-ssl
にはLibreSSLを設定していることです。
普通はOpenSSLでいいんですが、homebrewのlibはLibreSSLを前提にしているっぽいので今回はLibreSSLに寄せました。OpenSSLとLibreSSLをまぜるとこの後のPHPのビルドで大変になる様です(後述します)。
prefix
*2については、システム(/usr/local以下)にいれる意味がないので*3自分のhome以下に変えています*4、ここは各自適当に。あとは開発環境なんでモジュールは全入れです。
ビルドとインストールが成功し、エラーなくApacheがあがればとりあえずOKです。*5
$ sudo ~/bin/apache/bin/httpd -DFOREGROUND
(一つ前のエントリで説明していますが、上はデーモン化しない起動方法で、^C
で終了できます)
PHPのビルド
phpのビルドには今回phpenvをつかいます、やっぱりphpenv以下にまとまってると楽ですからね。しかし、冒頭にも書きましたが結構大変ですし成功しませんでした。
この後は闇あふれる手パッチです。どうしてもmod_phpをいれたい人以外はcgiでPHPを動かすといいんじゃないですかね…(私も次はそうするかもしれません)。
本来、以下一発でできるはず…だと思います。(もしこれでビルド一発通ったら教えて下さい、なんか私のHomeBrewがおかしいのかもしれない)
重要なのはwith-apxs2
を指定していることで、この指定でmod_phpが作成できます。当然ですがこのapxsには先程インストールしたApacheのものをつかいます。
ライブラリのopensslとlibxmlの指定はシステムではなく、Homebrewのライブラリをつかうように指定しています。
$ PHP_BUILD_CONFIGURE_OPTS='--with-apxs2=/Users/uzulla/bin/apache/bin/apxs --with-openssl=/usr/local/Cellar/libressl/2.3.0 --with-libxml-dir=/usr/local/Cellar/libxml2/2.9.2/bin/xml2-config' phpenv install 7.0.0
あるいは、~/.phpenv/plugins/php-build/share/php-build/default_configure_options
に以下のような定義を追加することでもかまいません。こっちのほうが確実かもしれません。
# with-opensslとかは元々があるとおもうので、その行を書き換えて下さい。 --with-openssl=/usr/local/Cellar/libressl/2.3.0 --with-curl=/usr/local/Cellar/curl/7.45.0 --with-apxs2=/Users/uzulla/bin/apache/bin/apxs
さて、これでビルドしてみると…?うまくいきました?私は次のエラーメッセージがでて、これに苦しめられました。
Undefined symbols for architecture x86_64: "_PKCS5_PBKDF2_HMAC", referenced from: _zif_openssl_pbkdf2 in openssl.o "_SSL_CTX_set_alpn_protos", referenced from: _php_openssl_setup_crypto in xp_ssl.o "_SSL_CTX_set_alpn_select_cb", referenced from: _php_openssl_setup_crypto in xp_ssl.o "_SSL_get0_alpn_selected", referenced from: _php_openssl_sockop_set_option in xp_ssl.o "_SSL_select_next_proto", referenced from: _server_alpn_callback in xp_ssl.o "_TLSv1_1_client_method", referenced from: _php_openssl_setup_crypto in xp_ssl.o "_TLSv1_1_server_method", referenced from: _php_openssl_setup_crypto in xp_ssl.o "_TLSv1_2_client_method", referenced from: _php_openssl_setup_crypto in xp_ssl.o "_TLSv1_2_server_method", referenced from: _php_openssl_setup_crypto in xp_ssl.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [libs/libphp7.bundle] Error 1
これはsslのライブラリのリンクがうまくいってないってことですね。私はこれにめっちゃハマりました。というのも、このエラーってapxsを抜くと出ないんですよ、めっちゃ罠じゃん。
さて、これの原因は、OpenSSLとLibreSSL(あるいはそれらのバージョン差異)の食い合わせが悪くてリンクに失敗してしまうという事なんですが(だとおもいますが)、この処理って最後のリンクなので、ここに到達するのにすげー時間がかかるので、試行がめっちゃ大変でしたね…。
さておき、解決策なんですが、これ本当にきびしい手パッチです。
phpenv install 7.0.0
の裏でうごくphp-build
は/var/tmp/php-build/source/7.0.0
ここらへんにtarを展開して、そこでbuildとかしています。なのでそこに移動してMakefileを編集します。
EXTRA_LIBS
の行に-lssl
がいくつか(複数はいっている可能性が高いです)あるのですが、それを全部消して、そこに直接Homebrewでいれたlibresslのdylibを指定してしまいます。
EXTRA_LIBS = -lz -lexslt -ltidy -lresolv -ledit -lncurses -lmcrypt -lltdl -liconv -liconv -lpng -lz -ljpeg -lcurl -lz /usr/local/Cellar/libressl/2.3.0/lib/libssl.dylib /usr/local/Cellar/libressl/2.3.0/lib/libcrypto.dylib -lm -lxml2 -lz -liconv -lm -lkrb5 -lcurl -lldap -lz -lxml2 -lz -liconv -lm -lxml2 -lz -liconv -lm -lxml2 -lz -liconv -lm -lxml2 -lz -liconv -lm -lxml2 -lz -liconv -lm -lxml2 -lz -liconv -lm -lxml2 -lz -liconv -lm -lxml2 -lxslt
たとえばこんな感じになりますね。この修正をしたらmake allが通るはず…です。
私がなんかミスってるのかもしれないのですが、特にEl capitanになってからOpenSSL、LibreSSLまわりが一筋縄でいかなくて本当にきびしいですね。かといってOpenSSLを野良で入れるのもビミョウ。
さておき、makeが成功したら、make installしましょう。
(追記:後述しますが、一度でもapxs抜きでphpenv installを行っていて、既存のバージョンを上書きするなら、.phpenv/versions/7.0.0
以下のファイルを一回消してからやらないとハマります)
すると、いつも通りのphpenvのinstallのようにPHPが~/.phpenv/versions以下にはいりつつ、Apacheのbin/apache/modules/
以下にlibphp7.so
がコピーされ、設定ファイルが自動的に修正されてインストールされるはず、です。
ただ、ここもうまくいきませんでした(sedがエラーを吐いた)。なのでhttpdのconfを修正する必要があります。(勿論エラーなくうまくいったらこの作業は不要です)
apache/conf/extra
にhttpd-php7.conf
というファイルを以下の内容でつくり、以下のように記述します。
LoadModule php7_module modules/libphp70.so AddType text/html .php <FilesMatch \.php$> SetHandler application/x-httpd-php </FilesMatch>
(そういえば、SetHandlerまわり、セキュリティのアレでファイル名マッチからデフォルトがこの記法にかわりましたね。)
その上で、httpd.confの方に以下のように追記して、コンフィグをロードします。(あるいは、直接httpd.confに上のconfをかいてしまってもよいですけど)
include conf/extra/httpd-php7.conf
あとは、必要に応じて以下を書いたりしてもよいでしょう。
DirectoryIndex index.php
これでPHPがうごくはずです!多分!
まあ、Linuxで野良ビルドやってきた人にはなれたもんですね。
余談:途中でとまるので、xdebugがはいらない
phpenv installは最後まで通らないので、xdebugがはいりません(opcacheまでは入るけど)。なので手でいれましょう。
$ cd /tmp $ git clone git://github.com/xdebug/xdebug.git $ cd xdebug $ phpize $ make all $ make install $ rm -r xdebug
# .phpenv/versions/7.0.0/etc/conf.d/xdebug.ini を作成 zend_extension="/Users/uzulla/.phpenv/versions/7.0.0/lib/php/extensions/no-debug-zts-20151012/xdebug.so" html_errors=on
php -i |grep xdebug
でエラーなくロードできていればOKです
ここで一個注意があるんですが、試行錯誤してると以下みたいなエラーがでることがあります。
$ php -v Failed loading /Users/uzulla/.phpenv/versions/7.0.0/lib/php/extensions/no-debug-non-zts-20151012/opcache.so: dlopen(/Users/uzulla/.phpenv/versions/7.0.0/lib/php/extensions/no-debug-non-zts-20151012/opcache.so, 9): Symbol not found: _compiler_globals Referenced from: /Users/uzulla/.phpenv/versions/7.0.0/lib/php/extensions/no-debug-non-zts-20151012/opcache.so Expected in: flat namespace in /Users/uzulla/.phpenv/versions/7.0.0/lib/php/extensions/no-debug-non-zts-20151012/opcache.so Failed loading /Users/uzulla/.phpenv/versions/7.0.0/lib/php/extensions/no-debug-non-zts-20151012/xdebug.so: dlopen(/Users/uzulla/.phpenv/versions/7.0.0/lib/php/extensions/no-debug-non-zts-20151012/xdebug.so, 9): Symbol not found: _basic_globals Referenced from: /Users/uzulla/.phpenv/versions/7.0.0/lib/php/extensions/no-debug-non-zts-20151012/xdebug.so Expected in: flat namespace in /Users/uzulla/.phpenv/versions/7.0.0/lib/php/extensions/no-debug-non-zts-20151012/xdebug.so PHP 7.0.0 (cli) (built: Dec 15 2015 14:27:15) ( ZTS ) Copyright (c) 1997-2015 The PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2015 Zend Technologies
こちら、opcacheやxdebugなどのextentionがうまくうごいてないのは一目瞭然なのですが、ちょっとハマりました。
原因はphpenv install
をつかってすでにあるバージョンのphpを再度インストールしたら、既存のファイルとの競合が発生しました。
具体的には、過去にapxs抜きでビルドするとnon-ztsなファイル群ができますが、その後でapxs入りでビルドするとztsのファイル群ができてきて、既存のファイルは削除されずにマージされる格好となります。
その時、既存の設定ファイルは「上書きされない」ので、「過去のapxs抜きのnon-ztsの拡張をつかいつづけようとする設定」になり、ビルドしたPHPとマッチしない拡張をロードしようとしてしまいます。
後でphp.ini
やxdebug.ini
などを書き換える。あるいは、apxs付きでビルドする前に既存の.phpenv/versions/7.0.0
をどけましょう。(あるいは、7.0.0_apacheとか別名を)
余談:apxsがうまくうごかない
これは一部の人だけになりますが、plenv環境でApacheをビルドするとこんな感じのエラーが出るかもしれません。
/Users/uzulla/bin/apache/bin/apxs: line 18: require: command not found /Users/uzulla/bin/apache/bin/apxs: line 19: use: command not found
これはapxsはPerlでかかれているんですが、うまくそれがうごいてない場合になります。(ShebangにかかれているPerlをうまく認識できず、シェルスクリプトとして実行してしまっている)
手パッチ面倒くさいですけど、/Users/uzulla/bin/apache/bin/apxs
の一行目を修正し、たとえば以下のように書き直せば動くはずです。
#!/usr/bin/env perl -w
これ、どうにかならんのですかね?(plenvつかってると、希によくある)
未完!
ここからがやりたい事なんですけど(PHPのBuiltin ServerみたいにApache+mod_php環境をシュッ起動できるように用意し、プロジェクト毎に設定を別ける)、PHPのビルド一回に10分くらいかかるので、大分HPをけずられました。今日はここまでです。
次回につづく。