Skip to content
This repository was archived by the owner on Jul 21, 2026. It is now read-only.

php: build and test the complete CLI, FPM, and extension runtime - #44

Open
brandonpayton wants to merge 3 commits into
mainfrom
migrate/php-runtime
Open

php: build and test the complete CLI, FPM, and extension runtime#44
brandonpayton wants to merge 3 commits into
mainfrom
migrate/php-runtime

Conversation

@brandonpayton

@brandonpayton brandonpayton commented Jul 11, 2026

Copy link
Copy Markdown
Member

Why

Kandelo needs a real PHP runtime from Homebrew so common web applications can be
built into images and installed inside running machines without using the older
package registry. A command-only wrapper would not prove PHP's process manager,
configuration, internationalization data, or loadable extensions. Providing the
complete PHP 8.3.15 package matters because those are the runtime surfaces that
applications actually use.

What changed

This adds PHP 8.3.15 to Kandelo's first-party Homebrew tap as a normal
source-built Formula. The keg, which is Homebrew's installed directory for one
package version, owns the PHP command-line executable, PHP-FPM process manager,
runtime configuration, International Components for Unicode (ICU) data, and
the loadable extensions needed by common PHP applications.

The Formula builds through Kandelo's SDK and declares every library it consumes as a Homebrew dependency: ICU, libcurl, libc++, GNU libiconv, libxml2, libzip, OpenSSL, SQLite, and zlib.

It installs:

  • fork-instrumented bin/php and sbin/php-fpm executables;
  • opcache.so, curl.so, phar.so, zend_test.so, zip.so, and intl.so;
  • a pinned ICU 74.2 data file whose size and SHA-256 are checked during installation and testing;
  • PHP and PHP-FPM configuration at guest-stable paths.

The build uses a private sysroot populated from the declared libc++ keg, preserves linker argument order, enables shared-module output for every generated libtool tag, and derives the complete intl object list from PHP's generated Makefile. Reproducible path mappings keep host build paths out of the resulting Wasm files.

The Formula also rejects malformed artifacts. It checks the Kandelo ABI, the VM-interrupt import, required fork exports, dynamic side-module imports and relocation exports, legacy Asyncify markers, and embedded host paths. Opcache is fork-instrumented because it can execute a fork path; the non-forking side modules are rejected if they accidentally expose executable fork instrumentation.

musl fopencookie correction

PHP's cross-compilation probe treats every Linux host as though it were glibc. For Kandelo's truthful wasm32-unknown-linux-musl target, that incorrectly defines COOKIE_SEEKER_USES_OFF64_T, even though musl's fopencookie seek callback uses off_t *, not glibc's off64_t *.

The Formula fixes the generated PHP configuration before compilation by preserving HAVE_FOPENCOOKIE and removing only the glibc-only callback-type define. Fail-closed checks ensure that fopencookie support remains enabled and that the incorrect define is gone. This correction is folded into the first PHP purpose commit rather than carried as a follow-up fix.

Runtime test contract

brew test is designed to exercise the installed Homebrew bytes through Kandelo's normal runtime path:

  • Node loads all six modules and exercises libcurl, ZipArchive, Phar, ICU collation/data, opcache file-cache mode, and an intl call after pcntl_fork() replay.
  • Chromium runs the same PHP workload and must match the Node result.
  • A compiled FastCGI client starts the real php-fpm, connects through its AF_UNIX socket, serves a staged PHP request, and checks shutdown of both the FPM master and worker.

PHP-FPM 8.3.15 can finish with a clean master and a worker terminated by SIGTERM; the test requires that exact descendant status set and separately requires the master and root test process to exit successfully.

Exact-head validation completed

The following checks were run against head bbdff0fda7213185fa026727c33014d497222094, tree 5bc77d8d8f0911b1b421642affe275c67d0df876:

  • PHP Formula Ruby syntax: passed.
  • Homebrew style: passed with no offenses.
  • Shared Formula-support Ruby suite: 48 runs, 380 assertions, 0 failures, 0 errors.
  • PHP source checksum: verified.
  • Kandelo PHP patch: applied in a clean dry run against PHP 8.3.15.
  • Generated-header fixture: verified the musl fopencookie correction and its fail-closed assertions.
  • Formula, support source, README, and commit diff checks: passed.
  • Independent review of this exact three-commit candidate: accepted.

This exact head has not yet produced the final bottle, so the validation above does not claim a final poured runtime result. Earlier development builds established the Node, Chromium, and FPM test path; those tests must run again against the final merged dependency graph and the exact bottle that will be published.

Remaining merge and publication gates

Do not merge this PR until the tap contains the exact dependency Formula sources this build requires, including ICU, libzip, libc++ PIC archives, the libcurl PIC archive, and libxml2 linked to GNU libiconv. Then restack this branch on current tap main and rerun strict audit and brew readall.

Final bottle publication also requires:

  1. the Kandelo platform stack that reports the musl target truthfully and supports this PHP build, including Automattic/kandelo#883;
  2. the trusted bottle publisher in Automattic/kandelo#936 and its tap-side caller in this repository's PR #22;
  3. bottles for every declared dependency built for the same final Kandelo ABI;
  4. an exact merged-head source build, artifact validation, bottle pour, Node test, Chromium test, and real PHP-FPM FastCGI lifecycle test.

This PR contains Formula source and tests only. It does not contain bottle bytes, bottle metadata, a binary index entry, or a change to the main Kandelo repository.

Exact candidate

  • Head: bbdff0fda7213185fa026727c33014d497222094
  • Tree: 5bc77d8d8f0911b1b421642affe275c67d0df876
  • Base used for this review: tap main da5f694d1c9c01656bfd1beeb78a710af3a25d6e
  • History: three PHP purpose commits, no merge commits

@brandonpayton brandonpayton changed the title php: preserve CLI, FPM, and opcache runtime PHP: preserve the complete CLI, FPM, and extension runtime Jul 13, 2026
@brandonpayton

Copy link
Copy Markdown
Member Author

Devil's-advocate review: ACCEPTED, BUT PREREQUISITE-GATED at exact head e3da0dbd8877a35d3c8602a7b69b8bc5ac913e68 (tree 6a5fe228f7ad84a170a4226efbc617e86c6ea530, base 0bafcc48fa941ab78ca8ef262dd354190e0d9845).

The candidate itself has no blocking correctness finding. I traced its complete declared dependency closure through exact fully-qualified versioned kegs, the private libc++ sysroot, ordered compile/link inputs, the 70-object intl closure, ICU data installation, CLI/FPM/side-module artifact guards, Node/Chromium execution, and the real AF_UNIX FastCGI teardown. The formula uses the canonical tap runner and exact descendant status multiset [0,143]; the FPM master is asserted separately to exit normally, so the intentional worker signal cannot mask a failed service.

Independent source evidence: the official PHP 8.3.15 tarball matched SHA-256 67073c3c9c56c86461e0715d9e1806af5ddffe8e6e2eb9781f7923bbb5bd67fa, and all eight patch hunks applied cleanly with patch --dry-run -p1 in the canonical ABI 39 dev shell. The candidate contains no local tap alias, registry artifact, build-only reload, or support override. The outer diff-check diagnostics are context-marker whitespace inside the deliberately stored unified patch, not whitespace introduced into patched PHP sources.

Do not merge this PR yet. Exact tap prerequisites are:

Base 0bafcc48 has no ICU or libzip Formula, lacks the libc++ and libcurl PIC archives PHP links into side modules, and still has the libc-iconv libxml2 configuration. #44 must be restacked after all five land and their audit/CI state resolves. Runtime and publication remain gated on the final ABI 39 platform (#907), ordered SDK linker argv (#913), same-ABI dependency bottles, publisher reruns, and a real guest pour. This acceptance authorizes review progress only, not merge.

Install ICU data without mutating dependency kegs, link every declared intl PIC object, and exercise extensions plus fork replay in Node and Chromium. Stage truthful FPM account/config fixtures, serve a real FastCGI request, and require the exact clean-master/terminated-worker shutdown contract.
@brandonpayton brandonpayton changed the title PHP: preserve the complete CLI, FPM, and extension runtime php: build and test the complete CLI, FPM, and extension runtime Jul 14, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant