Skip to content

Commit 16f20d9

Browse files
committed
Stabilize WASM Rust build across PHP versions
1 parent 55c8ee0 commit 16f20d9

2 files changed

Lines changed: 76 additions & 33 deletions

File tree

packages/php-ext-wp-mysql-parser/wasm-spike/Dockerfile.rust

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,56 +12,59 @@
1212
# docker build \
1313
# --build-arg BASE_IMAGE=playground-php-wasm:compile-extension-php8-4-jspi \
1414
# --build-arg HOST_PHP_VERSION=8.4 \
15+
# --build-arg HOST_PHP_API_VERSION=20240924 \
1516
# -t playground-php-wasm-ext-rust:8.4-jspi \
1617
# -f Dockerfile.rust .
1718

1819
ARG BASE_IMAGE=playground-php-wasm:compile-extension-php8-4-jspi
1920
ARG HOST_PHP_VERSION=8.4
20-
21-
# Stage providing a host PHP CLI binary. ext-php-rs's build.rs shells
22-
# out to `php` to detect the PHP version (PHP_VERSION_ID drives the cfg
23-
# flags such as php74, php80, and php85). The wasm-targeted PHP install in
24-
# /usr/local has no CLI binary (--disable-cli), so copy a matching CLI from
25-
# the official PHP image for the target version.
26-
FROM php:${HOST_PHP_VERSION}-cli AS host-php-cli
27-
28-
RUN set -eux; \
29-
mkdir -p /opt/host-php/libdeps; \
30-
ldd /usr/local/bin/php \
31-
| awk '($2 == "=>") { print $3 } ($1 ~ /^\//) { print $1 }' \
32-
| grep -v '^$' \
33-
| sort -u \
34-
| while read -r lib; do cp -L "$lib" /opt/host-php/libdeps/; done
21+
ARG HOST_PHP_API_VERSION=20240924
3522

3623
FROM ${BASE_IMAGE}
37-
38-
COPY --from=host-php-cli /usr/local/bin/php /opt/host-php/bin/php
39-
COPY --from=host-php-cli /usr/local/lib/php /opt/host-php/lib/php
40-
COPY --from=host-php-cli /usr/local/etc/php /opt/host-php/etc/php
41-
COPY --from=host-php-cli /usr/local/include/php /opt/host-php/include/php
42-
COPY --from=host-php-cli /opt/host-php/libdeps /opt/host-php/libdeps
24+
ARG HOST_PHP_VERSION=8.4
25+
ARG HOST_PHP_API_VERSION=20240924
4326

4427
ENV RUSTUP_HOME=/root/rustup \
4528
CARGO_HOME=/root/cargo \
4629
PATH=/root/cargo/bin:/root/rustup/bin:/usr/local/bin:/usr/bin:/bin \
47-
LD_LIBRARY_PATH=/opt/host-php/libdeps:/opt/host-php/lib
30+
HOST_PHP_VERSION=${HOST_PHP_VERSION} \
31+
HOST_PHP_API_VERSION=${HOST_PHP_API_VERSION}
4832

4933
RUN apt-get update && apt-get install -y --no-install-recommends \
5034
curl ca-certificates build-essential \
5135
libclang-dev clang llvm-dev pkg-config libxml2 libonig5 libsqlite3-0 \
5236
libargon2-1 libssl3 zlib1g libreadline8 \
53-
&& rm -rf /var/lib/apt/lists/* \
54-
&& /opt/host-php/bin/php -v \
55-
&& ln -sf /opt/host-php/bin/php /usr/local/bin/php-host
37+
&& rm -rf /var/lib/apt/lists/*
38+
39+
# ext-php-rs shells out to `php -i` for version, debug, and ZTS metadata. The
40+
# wasm-targeted PHP install in /usr/local has no CLI binary (--disable-cli), and
41+
# copying a host PHP binary across Debian generations makes this layer depend on
42+
# incompatible shared libraries. Keep the build contract narrow: report only the
43+
# phpinfo keys ext-php-rs reads, while `PHP_CONFIG` continues to point at the
44+
# wasm PHP install for headers and include paths.
45+
RUN set -eux; \
46+
printf '%s\n' \
47+
'#!/usr/bin/env bash' \
48+
'set -euo pipefail' \
49+
'if [ "${1:-}" != "-i" ]; then' \
50+
' echo "php-host-info only supports php -i for ext-php-rs build metadata" >&2' \
51+
' exit 1' \
52+
'fi' \
53+
'cat <<INFO' \
54+
'PHP Version => ${HOST_PHP_VERSION}' \
55+
'PHP API => ${HOST_PHP_API_VERSION}' \
56+
'Debug Build => no' \
57+
'Thread Safety => disabled' \
58+
'INFO' \
59+
> /usr/local/bin/php-host-info; \
60+
chmod +x /usr/local/bin/php-host-info; \
61+
/usr/local/bin/php-host-info -i | grep -q "PHP API => ${HOST_PHP_API_VERSION}"
5662

57-
# ext-php-rs's build.rs needs a host `php` executable to query include paths
58-
# from `php-config`. The wasm-targeted PHP install in /usr/local does not ship
59-
# a CLI binary (--disable-cli). We install Debian's host php-cli purely so the
60-
# build script's PHP shells out can run; bindgen still uses
61-
# /usr/local/bin/php-config (from PATH order) for headers — which IS the wasm
62-
# PHP install. Set PHP_CONFIG explicitly to make this contract obvious.
63+
# Set PHP_CONFIG explicitly so bindgen uses the wasm PHP headers from the
64+
# Playground compile-extension image, not any host PHP package that apt may
65+
# provide as a transitive dependency.
6366
ENV PHP_CONFIG=/usr/local/bin/php-config \
64-
PHP=/opt/host-php/bin/php
67+
PHP=/usr/local/bin/php-host-info
6568

6669
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
6770
| sh -s -- -y --default-toolchain stable --profile minimal \

packages/php-ext-wp-mysql-parser/wasm-spike/build-in-docker-rust.sh

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#
55
# 1. cargo build --release --target wasm32-unknown-emscripten
66
# inside playground-php-wasm-ext-rust:<PHP_VERSION>-<ASYNC>, which
7-
# layers rustup + a host PHP 8.4 CLI on top of the Playground
7+
# layers rustup + ext-php-rs build metadata on top of the Playground
88
# compile-extension image.
99
# 2. Hand the resulting libwp_mysql_parser.a + C shim + config.m4 to
1010
# `@php-wasm/compile-extension`, which owns phpize, emconfigure,
@@ -29,6 +29,20 @@ if [ "$ASYNC_MODE" != "jspi" ]; then
2929
exit 1
3030
fi
3131

32+
case "$PHP_VERSION" in
33+
7.4) PHP_API_VERSION=20190902 ;;
34+
8.0) PHP_API_VERSION=20200930 ;;
35+
8.1) PHP_API_VERSION=20210902 ;;
36+
8.2) PHP_API_VERSION=20220829 ;;
37+
8.3) PHP_API_VERSION=20230831 ;;
38+
8.4) PHP_API_VERSION=20240924 ;;
39+
8.5) PHP_API_VERSION=20250925 ;;
40+
*)
41+
echo "Unsupported PHP_VERSION: $PHP_VERSION" >&2
42+
exit 1
43+
;;
44+
esac
45+
3246
if [ -z "$PLAYGROUND_REPO" ] || [ ! -f "$PLAYGROUND_REPO/packages/php-wasm/compile-extension/src/cli.ts" ]; then
3347
echo "PLAYGROUND_REPO must point at a wordpress-playground checkout with packages/php-wasm/compile-extension." >&2
3448
exit 1
@@ -70,6 +84,7 @@ echo "==> Stage 0: building $RUST_IMAGE"
7084
docker build \
7185
--build-arg "BASE_IMAGE=$BASE_IMAGE" \
7286
--build-arg "HOST_PHP_VERSION=$PHP_VERSION" \
87+
--build-arg "HOST_PHP_API_VERSION=$PHP_API_VERSION" \
7388
-t "$RUST_IMAGE" \
7489
-f "$SPIKE_DIR/Dockerfile.rust" \
7590
"$SPIKE_DIR"
@@ -78,6 +93,8 @@ echo "==> Stage 1: cargo build --target wasm32-unknown-emscripten"
7893
# Feed the container script through stdin so Docker-side comments and strings
7994
# cannot break host-shell quoting.
8095
docker run --rm -i \
96+
-e "PHP_VERSION=$PHP_VERSION" \
97+
-e "PHP_API_VERSION=$PHP_API_VERSION" \
8198
-v "$CRATE_DIR":/src:ro \
8299
-v "$OUT_DIR":/out \
83100
--entrypoint bash \
@@ -124,6 +141,29 @@ docker run --rm -i \
124141
cargo fetch >/dev/null 2>&1 || true
125142
REG=$(find /root/cargo/registry/src -maxdepth 1 -type d -name "index.crates.io-*" | head -1)
126143
chmod -R u+w "$REG"
144+
145+
if [ "${PHP_VERSION:-}" = "7.4" ]; then
146+
# ext-php-rs 0.15's runtime APIs still cover the pieces this extension
147+
# uses, but its build-time version table starts at PHP 8.0. Add the
148+
# PHP 7.4 Zend API so bindgen can run against Playground's 7.4 headers.
149+
perl -0pi -e 's|pub enum ApiVersion \{\n|pub enum ApiVersion {\n /// PHP 7.4\n Php74 = 2019_09_02,\n|' \
150+
"$REG/ext-php-rs-build-0.1.1/src/lib.rs"
151+
sed -i 's/ApiVersion::Php80,/ApiVersion::Php74,/' \
152+
"$REG/ext-php-rs-0.15.12/build.rs"
153+
sed -i '/vec!\[/a \ ApiVersion::Php74,' \
154+
"$REG/ext-php-rs-build-0.1.1/src/lib.rs"
155+
perl -0pi -e 's/(pub fn cfg_name\(self\).*?match self \{\n)/$1 ApiVersion::Php74 => "php74",\n/s' \
156+
"$REG/ext-php-rs-build-0.1.1/src/lib.rs"
157+
perl -0pi -e 's/(pub fn define_name\(self\).*?match self \{\n)/$1 ApiVersion::Php74 => "EXT_PHP_RS_PHP_74",\n/s' \
158+
"$REG/ext-php-rs-build-0.1.1/src/lib.rs"
159+
sed -i '/match version {/a \ x if ((ApiVersion::Php74 as u32)..(ApiVersion::Php80 as u32)).contains(&x) => Ok(ApiVersion::Php74),' \
160+
"$REG/ext-php-rs-build-0.1.1/src/lib.rs"
161+
sed -i 's/cfg(php80, php81/cfg(php74, php80, php81/' \
162+
"$REG/ext-php-rs-build-0.1.1/src/lib.rs"
163+
grep -q 'Php74 = 2019_09_02' "$REG/ext-php-rs-build-0.1.1/src/lib.rs"
164+
grep -q 'ApiVersion::Php74,' "$REG/ext-php-rs-0.15.12/build.rs"
165+
fi
166+
127167
sed -i "s/12 \* std::mem::size_of::<usize>/24 * std::mem::size_of::<usize>/" \
128168
"$REG/ext-php-rs-0.15.12/src/internal/property.rs"
129169

0 commit comments

Comments
 (0)