FrankenPHP をソースコードからビルドする完全ガイド — 動的 libphp 方式でカスタムバイナリを作る
【免费下载链接】frankenphp🧟 The modern PHP app server项目地址: https://gitcode.com/GitHub_Trending/fr/frankenphp
本ガイドは、PHP を動的ライブラリ(libphp)としてロードする FrankenPHP バイナリの作成手順を解説します。公式ドキュメント docs/ja/compile.md を骨格に、リポジトリ内のビルドスクリプト(go.sh、build-static.sh)や Docker ビルド定義(Dockerfile、docker-bake.hcl)の実装を照合しながら、Homebrew による PHP の導入、PHP 本体のソースコンパイル、xcaddy を使った最終バイナリの組み立てまでを順を追って説明します。読み終えると、任意の Caddy モジュールと FrankenPHP 拡張を組み込んだ独自バイナリを、自分の開発環境向けに再現できるようになります。
ビルド方式の全体像
FrankenPHP のバイナリを作る方法は大きく 2 つに分かれます。
- PHP を動的ライブラリとしてロードする方式(推奨):システムにインストールした PHP(ZTS ビルドの
libphp)を、Go で書かれた FrankenPHP 本体から cgo 経由でリンク・ロードします。本ドキュメントの主題です。 - 完全静的・ほぼ静的なビルド:static-php-cli を利用し、PHP インタープリター・Caddy・FrankenPHP を 1 つのポータブルなバイナリにまとめる方式。詳細は docs/ja/static.md を参照してください。
前者が推奨される理由は、システムの PHP バージョンや拡張をそのまま活かせること、ビルドが比較的シンプルであることです。互換性の要件として、FrankenPHP は PHP 8.2 以上に対応しています(docs/ja/compile.md)。実際、docker-bake.hcl のPHP_VERSION変数のデフォルト値は8.2,8.3,8.4,8.5となっており、このバージョン帯がビルドマトリクスとして維持されていることが確認できます。
PHP のインストール
Homebrew を使う場合(Linux と Mac)
FrankenPHP と互換性のあるlibphpを最も簡単に入手する方法は、Homebrew PHP が提供するZTS パッケージを使うことです。FrankenPHP は PHP をスレッド内で実行するため、Zend Thread Safety(ZTS)が有効な PHP が必要です。
まず Homebrew をインストールしていない場合は導入し、続けて PHP の ZTS バリアント、Brotli(オプション、圧縮サポート用)、watcher(オプション、ファイル変更検出用)をインストールします:
brew install shivammathur/php/php-zts brotli watcher brew link --overwrite --force shivammathur/php/php-ztsbrew link --overwrite --forceによって、シェルからphp-configコマンドが確実に参照できるようになります。php-configは後述のCGO_CFLAGS/CGO_LDFLAGSの解決に必須のコマンドです。
PHP をソースからコンパイルする場合
もう 1 つの方法は、FrankenPHP が必要とするオプションを明示して PHP をソースからビルドすることです。まず PHP のソース を取得して展開します:
tar xf php-* cd php-*/次に、プラットフォームに応じてconfigureスクリプトを実行します。以下のフラグは必須ですが、拡張モジュールや追加機能のために他のフラグを併記することも可能です。
Linux
./configure \ --enable-embed \ --enable-zts \ --disable-zend-signals \ --enable-zend-max-execution-timers各フラグの意味は次のとおりです:
| フラグ | 役割 |
|---|---|
--enable-embed | PHP を組み込み用途の共有ライブラリ(libphp)としてビルドするために必須 |
--enable-zts | スレッドセーフな PHP を有効化。FrankenPHP はリクエストを複数スレッドで処理するため必須 |
--disable-zend-signals | PHP 側のシグナル処理を無効化。Go ランタイムがシグナルを管理する構成との整合のため |
--enable-zend-max-execution-timers | リクエストの実行時間上限(タイマー)を Zend エンジンに持たせるために推奨・必須 |
Mac
Homebrew パッケージマネージャーで必須およびオプションの依存関係をインストールします:
brew install libiconv bison brotli re2c pkg-config watcher echo 'export PATH="/opt/homebrew/opt/bison/bin:$PATH"' >> ~/.zshrcbisonとre2cは PHP のパーサー生成に、pkg-configは依存ライブラリの解決に使われるビルドツールチェーンです。Apple 標準のbisonはバージョンが古いことがあるため、Homebrew 版のbisonをPATHの先頭に置く必要があります。libiconvは文字コード変換のため、明示的にパスを渡します。
その後、以下のように configure スクリプトを実行します:
./configure \ --enable-embed \ --enable-zts \ --disable-zend-signals \ --with-iconv=/opt/homebrew/opt/libiconv/Linux でも同様に、ディストリビューションのパッケージマネージャーでbison・re2c・pkg-configに相当するビルドツールチェーンを揃えておくと、PHP 本体のソースコンパイルがスムーズに進みます。
PHP のコンパイル
最後に、コア数の分だけ並列ビルドしてシステムへインストールします:
make -j"$(getconf _NPROCESSORS_ONLN)" sudo make install$(getconf _NPROCESSORS_ONLN)は利用可能な CPU コア数を返すため、-jで最大限の並列度が得られます。インストール後、php-config --includes/--ldflags/--libsが正しい値を返せば、次のステップに進めます。
オプション依存関係のインストール
FrankenPHP の一部機能は、システムにインストールされているオプションの依存パッケージに依存します。依存関係を用意しない場合、またはビルド時に明示的に無効化したい場合は、Go コンパイラにビルドタグを渡します:
| 機能 | 依存関係 | 無効化するためのビルドタグ |
|---|---|---|
| Brotli 圧縮 | Brotli | nobrotli |
| ファイル変更時のワーカー再起動 | Watcher C | nowatcher |
- Brotli:HTTP レスポンスの圧縮コーデックの 1 つ。有効時は Caddy の
encodeディレクティブでbrを利用できます。 - Watcher C:ファイル変更を検知してワーカーモードの PHP プロセスを自動再起動する機能(開発時のホットリロード)を担います。リポジトリでは internal/watcher/ と watcher.go にその実装があり、caddy/go.mod にも
github.com/e-dant/watcherが依存として宣言されています。
なお、リポジトリ内の Dockerfile では watcher をcmakeでビルドして/usr/local/libにインストールし、生成バイナリにlibwatcherを同梱する構成になっています。機能を無効化したくない場合は、両ライブラリを導入した上でタグを付けずにビルドしてください。
Go アプリのコンパイル
PHP の準備が整ったら、いよいよ最終バイナリをビルドします。
xcaddy を使う場合(推奨)
推奨される方法は、xcaddy を使って FrankenPHP をコンパイルすることです。xcaddyを使うと、Caddy のカスタムモジュールや FrankenPHP 拡張を--withで簡単に追加できます:
CGO_ENABLED=1 \ XCADDY_GO_BUILD_FLAGS="-ldflags='-w -s' -tags=nobadger,nomysql,nopgx" \ CGO_CFLAGS=$(php-config --includes) \ CGO_LDFLAGS="$(php-config --ldflags) $(php-config --libs)" \ xcaddy build \ --output frankenphp \ --with github.com/dunglas/frankenphp/caddy \ --with github.com/dunglas/mercure/caddy \ --with github.com/dunglas/vulcain/caddy # 追加のCaddyモジュールとFrankenPHP拡張をここに追加各環境変数の役割を整理します:
| 環境変数 | 意味 |
|---|---|
CGO_ENABLED=1 | cgo を有効化。libphpをリンクするために必須 |
XCADDY_GO_BUILD_FLAGS | Go ビルドに渡す追加フラグ。-ldflags='-w -s'でデバッグ情報を削ってバイナリを縮小し、-tags=nobadger,nomysql,nopgxで Caddy の不要なストレージモジュール(Badger・MySQL・pgx)を無効化 |
CGO_CFLAGS | PHP のヘッダー探索パス。php-config --includesの出力を利用 |
CGO_LDFLAGS | リンク時のライブラリ指定。php-config --ldflagsとphp-config --libsの出力を利用 |
--withで指定しているのは以下のモジュール群です:
github.com/dunglas/frankenphp/caddy:FrankenPHP 本体の Caddy モジュール(caddy/frankenphp/main.go でも標準・frankenphp・mercure・vulcain が blank import されています)github.com/dunglas/mercure/caddy:リアルタイム通信プロトコル Mercure の統合github.com/dunglas/vulcain/caddy:HTTP/2 Server Push を代替する Vulcain の統合
caddy/go.mod を見ると、Caddy v2.11.4・frankenphp v1.12.7 をはじめ、mercure・vulcain・caddy-cbrotli・e-dant/watcher などが依存として宣言されており、--withで追加するモジュール群と整合しています。独自の Caddy モジュールや FrankenPHP 拡張を追加する場合は、この行の後ろに--with <モジュールパス>を追記するだけです。
musl libc(Alpine Linux)で Symfony を使う場合の注意
[!TIP] musl libc(Alpine Linux のデフォルト)と Symfony を使用している場合、デフォルトのスタックサイズを増やす必要がある場合があります。そうしないと、
PHP Fatal error: Maximum call stack size of 83360 bytes reached during compilation. Try splitting expressionのようなエラーが発生する可能性があります。これを行うには、
XCADDY_GO_BUILD_FLAGS環境変数をXCADDY_GO_BUILD_FLAGS=$'-ldflags "-w -s -extldflags \'-Wl,-z,stack-size=0x80000\'"'のように変更してください (アプリの要件に応じてスタックサイズの値を変更してください)。
-extldflags '-Wl,-z,stack-size=0x80000'はリンカ(ld)に対してスレッドのスタックサイズを 0x80000(512 KiB)に引き上げる指示です。エラー文言の「during compilation」は、Symfony のコンパイルキャッシュ生成時に式が深すぎてスタックを消費することを示しており、値を0x100000などへ増やすことで回避できます。
xcaddy を使用しない場合
代替として、xcaddyを使わずにgoコマンドを直接使って FrankenPHP をコンパイルすることも可能です:
curl -L https://github.com/php/frankenphp/archive/refs/heads/main.tar.gz | tar xz cd frankenphp-main/caddy/frankenphp CGO_CFLAGS=$(php-config --includes) CGO_LDFLAGS="$(php-config --ldflags) $(php-config --libs)" go build -tags=nobadger,nomysql,nopgxこの方法では、caddy/frankenphp/main.go にあるとおり、github.com/caddyserver/caddy/v2/modules/standard、github.com/dunglas/frankenphp/caddy、mercure、vulcain がデフォルトで組み込まれます。拡張モジュールを足したい場合はmain.goへの import 追加が別途必要になるため、通常は xcaddy の方が便利です。
リポジトリ内のビルド補助スクリプト(go.sh)
リポジトリには、公式ビルドでも使われている補助スクリプト go.sh が同梱されています。内容を確認すると、次のことを自動化しているのが分かります:
GOFLAGSに-tags=nobadger,nomysql,nopgxを付与(Caddy の不要なストレージバックエンドを除外)CGO_CFLAGSにphp-config --includesと mtls-cflags.sh の出力(AArch64 向け TLS モデル最適化フラグ)を連結CGO_LDFLAGSにphp-config --ldflagsとphp-config --libsを連結
公式 Dockerfile でも../../go.sh install -ldflags "-w -s -X 'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP ...'"という形でこのスクリプトを利用し、さらにsetcap cap_net_bind_service=+ep /usr/local/bin/frankenphpで 80/443 ポートへのバインド権限を付与しています。手動ビルドで同様のバージョン情報を埋め込みたい場合は、この-ldflagsのパターンを参考にするとよいでしょう。
静的ビルドへの切り替え
配布やコンテナ化を重視する場合は、PHP・Caddy・FrankenPHP を 1 つのバイナリにまとめる静的ビルドも選択肢です。詳細は docs/ja/static.md を参照してください。リポジトリには static-builder-musl.Dockerfile(完全静的、musl ベース)と static-builder-gnu.Dockerfile(ほぼ静的、glibc ベース、動的拡張ロード可)が用意され、docker-bake.hcl のstatic-builder-musl/static-builder-gnuターゲットからdocker buildx bake --load static-builder-muslのように起動できます。
このときXCADDY_ARGSをカスタマイズしない場合、デフォルトで cbrotli・mercure・vulcain の 3 モジュールが含まれます(両 Dockerfile のARG XCADDY_ARGSのデフォルト値)。値を上書きする際は、必要なモジュールを明示的に列挙してください。また、build-static.shはPHP_VERSION・PHP_EXTENSIONS・PHP_EXTENSION_LIBS・FRANKENPHP_VERSION・EMBED・DEBUG_SYMBOLS・COMPRESS(UPX)・MIMALLOC・RELEASEなどの環境変数によるカスタマイズに対応しています。
ビルド結果の検証
ビルドが完了したら、生成されたバイナリが正しく構成されているか確認しましょう。公式 Docker イメージのビルド工程では、以下のコマンドで検証しています(Dockerfile):
frankenphp version frankenphp build-infofrankenphp versionで FrankenPHP・PHP・Caddy の各バージョンが、frankenphp build-infoでビルド時に埋め込まれた拡張・モジュール情報が確認できます。ローカルで動作確認する場合は、package/Caddyfileや caddy/frankenphp/Caddyfile を参考に Caddyfile を用意し、./frankenphp run --config /path/to/Caddyfile --adapter caddyfileで起動してください。
まとめ
本記事では、FrankenPHP をソースからビルドする手順を、PHP の導入(Homebrew / ソースコンパイル)→ オプション依存関係の確認 → xcaddy(またはgo build)による最終バイナリの組み立てという流れで解説しました。ポイントを整理すると:
- PHP 8.2 以上かつ ZTS ビルドの
libphpが必須。--enable-embed・--enable-zts・--disable-zend-signalsの 3 フラグは外せません。 CGO_CFLAGS/CGO_LDFLAGSはphp-configから導出します。CGO_ENABLED=1を忘れないこと。- xcaddy が推奨。
--withで frankenphp/caddy・mercure・vulcain に加えて任意のモジュールを追加できます。 - 不要な機能(Brotli・watcher)はビルドタグ
nobrotli/nowatcherで無効化可能です。 - 完全な移植性が必要なら docs/ja/static.md の静的ビルドを検討してください。
配布用のバージョン情報を埋め込む場合は、Dockerfile の-ldflags "-X 'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP ...'"パターンをそのまま流用できます。自分の拡張セットに合わせて、FrankenPHP バイナリを自在にカスタマイズしてみてください。
【免费下载链接】frankenphp🧟 The modern PHP app server项目地址: https://gitcode.com/GitHub_Trending/fr/frankenphp
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考