Skip to content

PHP: add libcurl wiring + --with-curl so curl_init() works #551

Description

@mho22

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):

  1. 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"]
  2. 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.
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions