[php-src] PR #23558: Add `--enable-cli-fpm` to link the FPM SAPI into the CLI binary (`php --fpm`)
| From: | mnapoli | Date: | Thu, 03 Sep 2026 15:17:00 +0000 |
| Subject: | [php-src] PR #23558: Add `--enable-cli-fpm` to link the FPM SAPI into the CLI binary (`php --fpm`) | ||
| Groups: | php.git-pulls | ||
| Request: | Send a blank email to git-pulls+get-38285@lists.php.net to get a copy of this message | ||
Pull Request: https://github.com/php/php-src/pull/23558
Author: mnapoli
This adds an opt-in configure option,
--enable-cli-fpm, that links the FPM SAPI into
the php binary.
The binary behaves exactly like the CLI unless its first argument is --fpm, in which
case it runs the php-fpm master with the remaining arguments:
```sh
php -v # PHP 8.6.0-dev (cli)
php --fpm -v # PHP 8.6.0-dev (fpm-fcgi)
php --fpm --nodaemonize -y /etc/php-fpm.conf
php script.php --fpm # "--fpm" is a script argument here (i.e. no
changes)
```
The default build is unchanged: without the flag, php and php-fpm are
built exactly as before.
### Goal
In some environments, the size of the runtime matters. Having php and
php-fpm binaries when they are ~99% the same code can be wasteful.
That's the case for example on AWS Lambda with [Bref](https://bref.sh), where a second ~24 MB
binary on disk increases the cold start duration (because that's more data to load in the
container/micro-VM when it starts).
### Design
This follows the shape of #21385 (do_php_cli() / PHP_CLI_SHARED_OBJS for
embed):
- sapi/fpm/fpm/fpm_main.c: main() becomes do_php_fpm(),
declared in fpm.h. A new sapi/fpm/php_fpm_main.c holds the one-line
main() for the standalone php-fpm binary.
- sapi/fpm/config.m4: PHP_SELECT_SAPI now only takes
php_fpm_main.c; all other FPM sources go through PHP_ADD_SOURCES_X into
PHP_FPM_SHARED_OBJS, which is appended to PHP_FPM_OBJS. The
BUILD_FPM link lines are untouched.
- sapi/fpm/config0.m4 (new): PHP_ARG_ENABLE([fpm]) moves here so
$PHP_FPM is set before sapi/cli/config.m4 runs (same reason embed has a
config0.m4).
- sapi/cli/config.m4: PHP_ARG_ENABLE([cli-fpm]), default off; errors out
unless both the CLI and FPM SAPIs are enabled; defines PHP_CLI_WITH_FPM and appends
$(PHP_FASTCGI_OBJS) $(PHP_FPM_SHARED_OBJS) to PHP_CLI_OBJS. The
BUILD_CLI lines are untouched. FPM_EXTRA_LIBS (systemd, acl, apparmor,
selinux) is appended to EXTRA_LIBS when the flag is on.
- sapi/cli/php_cli_main.c: under #ifdef PHP_CLI_WITH_FPM, dispatch to
do_php_fpm(argc, argv) when argv[1] is --fpm.
- FPM's option table accepts and ignores --fpm, so argv is passed through
unchanged. Shifting argv instead breaks FPM's process titles (fpm_env_init_main
requires the argv strings to be contiguous), which I verified on Linux. Side effect: php-fpm
--fpm is silently accepted.
- Both SAPIs define PHP_FUNCTION(apache_request_headers), which is a duplicate-symbol
link error when linked together. FPM's C symbol is renamed to
fpm_apache_request_headers; the stub uses @implementation-alias on both
apache_request_headers() and getallheaders() and the arginfo header is
regenerated. Userland names and behaviour are unchanged.
- php --help, php.1, NEWS, UPGRADING and UPGRADING.INTERNALS are updated.
A new sapi/cli/tests/cli_fpm.phpt skips unless the flag is built in.
### Backward compatibility
- Default builds: same binaries. The FPM objects are simply listed in two make variables.
- Internals: main() of php-fpm is now do_php_fpm();
--enable-fpm is declared in config0.m4. Both noted in UPGRADING.INTERNALS.
- Windows: untouched (FPM does not build there).
Note: I am new here, so please let me know if I've got things backwards, I've made
mistakes, I haven't followed the right workflow, etc. I'm opening this tentatively to get
the discussion started.
And the main question I see: does this require a RFC or not?