Summary
The Kandelo PHP package (packages/registry/php/) builds PHP 8.3.15 without the curl extension, so curl_init() and the rest of ext/curl are unavailable at runtime:
Fatal error: Uncaught Error: Call to undefined function curl_init() in /var/www/html/curl-test.php:2
packages/registry/libcurl/ (libcurl 8.11.1, depends on zlib@1.3.1 + openssl@3.3.2) already exists and ships a static libcurl.a with pkg-config metadata. The gap is purely PHP-build-side wiring: build-php.sh does not resolve libcurl and does not pass --with-curl to ./configure.
Why this matters
The headline integration target on the roadmap (#382, Layer 0) is WordPress Playground with --experimental-posix-kernel. Beyond Playground's own HTTPS via curl tests, the wider ecosystem consumes ext/curl extensively — every PHP HTTP client (Guzzle, Symfony HttpClient, WordPress' own WP_Http_Curl transport), every wp.org plugin install / update that goes through a curl handle, every WordPress.org REST API caller. Without ext/curl, kernel-mode parity with the classic Emscripten PHP build (which configures --with-curl=/root/lib — see packages/php-wasm/compile/php/Dockerfile:255-258) is incomplete.
This is a sibling gap to #550 (libzip / --with-zip). Closing both lands installPlugin, setSiteLanguage, and HTTPS curl networking in the same kernel-mode parity wave.
Reproducer
Against any current Kandelo PHP CLI binary:
echo '<?php var_dump(function_exists("curl_init"));' | <run-php-via-kernel> -r -
# Expected: bool(true)
# Actual: bool(false)
Or, more directly, attempting any HTTP fetch:
echo '<?php $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://example.com/"); var_dump(curl_exec($ch));' | <run-php-via-kernel> -r -
# Fatal error: Uncaught Error: Call to undefined function curl_init()
Root cause
packages/registry/php/build-php.sh runs wasm32posix-configure --disable-all followed by an explicit allowlist of --enable-* / --with-* flags (build-php.sh:189-220). The list configures --with-openssl, --with-zlib, --with-libxml, --with-sqlite3 etc., but --with-curl is absent and there is no LIBCURL_PREFIX="$(resolve_dep libcurl)" resolve step.
$ grep -i 'curl' packages/registry/php/build-php.sh
$ # (no output)
packages/registry/libcurl/package.toml already declares the right shape (kind = "library", outputs.libs = ["lib/libcurl.a"], outputs.pkgconfig = ["lib/pkgconfig/libcurl.pc"], kernel_abi = 7, depends_on = ["zlib@1.3.1", "openssl@3.3.2"]) — i.e. PHP can consume it the same way it already consumes zlib, openssl, sqlite, libxml2. PHP's own ext/curl ./configure checks (CURL_CFLAGS / CURL_LIBS) match what libcurl.pc exposes, so no autoconf patching should be required.
Proposed fix
Three small pieces (mirrors #550 but smaller — no new package to add):
- Declare the dep in
packages/registry/php/package.toml:
depends_on = ["zlib@1.3.1", "openssl@3.3.2", "sqlite@3.49.1", "libxml2@2.13.8", "libcurl@8.11.1"]
- Wire it into PHP in
packages/registry/php/build-php.sh: add a LIBCURL_PREFIX="$(resolve_dep libcurl)" block alongside the existing resolves, append -I$LIBCURL_PREFIX/include / -L$LIBCURL_PREFIX/lib to DEP_CPPFLAGS / DEP_LDFLAGS, and add --with-curl="$LIBCURL_PREFIX" to the wasm32posix-configure invocation.
- Bump
packages/registry/php/build.toml revision from 2 to 3 so the content-addressed cache rebuilds rather than serving the pre-curl archive.
No ABI_VERSION bump required (this is an ext/curl capability change, not a kernel ABI change). Both libcurl@8.11.1 and PHP currently target kernel_abi = 7, so they're already on the same ABI plane.
Acceptance
function_exists('curl_init') is true; a basic curl_exec() against an HTTPS URL with CURLOPT_RETURNTRANSFER=1 returns the body bytes.
- The published
binaries-abi-v<N> index entry for php on wasm32 references the new revision.
- WordPress Playground's HTTPS-via-
curl_exec() and CURLFile-upload blueprint tests pass in kernel mode (see references below).
References
Summary
The Kandelo PHP package (
packages/registry/php/) builds PHP 8.3.15 without thecurlextension, socurl_init()and the rest ofext/curlare unavailable at runtime:packages/registry/libcurl/(libcurl 8.11.1, depends onzlib@1.3.1+openssl@3.3.2) already exists and ships a staticlibcurl.awith pkg-config metadata. The gap is purely PHP-build-side wiring:build-php.shdoes not resolvelibcurland does not pass--with-curlto./configure.Why this matters
The headline integration target on the roadmap (#382, Layer 0) is WordPress Playground with
--experimental-posix-kernel. Beyond Playground's own HTTPS via curl tests, the wider ecosystem consumesext/curlextensively — every PHP HTTP client (Guzzle, Symfony HttpClient, WordPress' ownWP_Http_Curltransport), every wp.org plugin install / update that goes through a curl handle, every WordPress.org REST API caller. Withoutext/curl, kernel-mode parity with the classic Emscripten PHP build (which configures--with-curl=/root/lib— seepackages/php-wasm/compile/php/Dockerfile:255-258) is incomplete.This is a sibling gap to #550 (libzip /
--with-zip). Closing both landsinstallPlugin,setSiteLanguage, and HTTPS curl networking in the same kernel-mode parity wave.Reproducer
Against any current Kandelo PHP CLI binary:
Or, more directly, attempting any HTTP fetch:
Root cause
packages/registry/php/build-php.shrunswasm32posix-configure --disable-allfollowed by an explicit allowlist of--enable-*/--with-*flags (build-php.sh:189-220). The list configures--with-openssl,--with-zlib,--with-libxml,--with-sqlite3etc., but--with-curlis absent and there is noLIBCURL_PREFIX="$(resolve_dep libcurl)"resolve step.packages/registry/libcurl/package.tomlalready declares the right shape (kind = "library",outputs.libs = ["lib/libcurl.a"],outputs.pkgconfig = ["lib/pkgconfig/libcurl.pc"],kernel_abi = 7,depends_on = ["zlib@1.3.1", "openssl@3.3.2"]) — i.e. PHP can consume it the same way it already consumeszlib,openssl,sqlite,libxml2. PHP's ownext/curl./configurechecks (CURL_CFLAGS/CURL_LIBS) match whatlibcurl.pcexposes, so no autoconf patching should be required.Proposed fix
Three small pieces (mirrors #550 but smaller — no new package to add):
packages/registry/php/package.toml:packages/registry/php/build-php.sh: add aLIBCURL_PREFIX="$(resolve_dep libcurl)"block alongside the existing resolves, append-I$LIBCURL_PREFIX/include/-L$LIBCURL_PREFIX/libtoDEP_CPPFLAGS/DEP_LDFLAGS, and add--with-curl="$LIBCURL_PREFIX"to thewasm32posix-configureinvocation.packages/registry/php/build.tomlrevision from2to3so the content-addressed cache rebuilds rather than serving the pre-curl archive.No
ABI_VERSIONbump required (this is anext/curlcapability change, not a kernel ABI change). Bothlibcurl@8.11.1and PHP currently targetkernel_abi = 7, so they're already on the same ABI plane.Acceptance
function_exists('curl_init')istrue; a basiccurl_exec()against an HTTPS URL withCURLOPT_RETURNTRANSFER=1returns the body bytes.binaries-abi-v<N>index entry for php onwasm32references the new revision.curl_exec()and CURLFile-upload blueprint tests pass in kernel mode (see references below).References
test.skip()'d citing this issue):blueprints.spec.ts:433(HTTPS via curl_exec),:480(CURLFile upload),:563(CURLFile via CORS proxy),:623(curl_exec with networking disabled) underpackages/playground/website/playwright/e2e/posix-kernel/--with-curl=/root/lib):packages/php-wasm/compile/php/Dockerfile:255-258packages/registry/php/build-php.sh:189-220--with-zip)