Skip to content

Add --enable-cli-fpm to link the FPM SAPI into the CLI binary (php --fpm) - #23558

Open
mnapoli wants to merge 1 commit into
php:masterfrom
mnapoli:php-fpm-single-binary
Open

Add --enable-cli-fpm to link the FPM SAPI into the CLI binary (php --fpm)#23558
mnapoli wants to merge 1 commit into
php:masterfrom
mnapoli:php-fpm-single-binary

Conversation

@mnapoli

@mnapoli mnapoli commented Sep 3, 2026

Copy link
Copy Markdown

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:

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, 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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant