Skip to content

Commit 5c43ef8

Browse files
authored
[CLI] Load custom PHP.wasm extensions (#3616)
## What it does Adds Playground CLI support for loading custom PHP.wasm extensions before PHP starts: ```bash wp-playground server \ --php=8.4 \ --php-extension=./dist/wp_mysql_parser/manifest.json ``` `--php-extension` is repeatable and accepts a local path, `file:` URL, or `http(s):` URL to a PHP extension manifest. Manifests can now describe both the artifact matrix and startup settings in one JSON file: ```json { "name": "spx", "version": "0.1.0", "artifacts": [ { "phpVersion": "8.4", "sourcePath": "spx-php8.4-jspi.so" } ], "iniEntries": { "spx.http_enabled": "1" }, "env": { "SPX_DATA_DIR": "/internal/shared/spx/data" } } ``` ## Rationale The PHP.wasm runtime can load externally built JSPI side modules, and `@php-wasm/compile-extension` emits manifests for those builds. CLI users still had no direct way to pass those manifests through to the Node runtime. Custom extensions must be declared at startup because PHP reads extension `.ini` files while booting. Passing manifests through the existing runtime `extensions` array keeps CLI behavior aligned with `loadNodeRuntime()`. The user-facing format is intentionally one manifest file rather than separate manifest and loader-config files. Runtime settings such as `iniEntries`, `env`, `loadWithIniDirective`, and `extensionDir` live directly in the manifest. ## Implementation - Renames the CLI extension adapter to `cliExtensionArgsToExtensionsArray()`. - Combines built-in extension flags (`intl`, `redis`, `memcached`, `xdebug`) with custom `--php-extension=<manifest>` entries. - Threads the combined `PHPExtension[]` into both Blueprint v1 and v2 CLI workers. - Extends the PHP extension manifest type and generated schema/validator to allow runtime startup settings. - Applies manifest-declared runtime settings in `resolvePHPExtension()`. - Documents the single manifest-based CLI path in the CLI and `@php-wasm/compile-extension` READMEs. ## Testing instructions ```bash npm exec -- nx run playground-cli:test-playground-cli --testFiles=tests/php-extensions.spec.ts npm exec -- nx run php-wasm-universal:test:vite --testFile=load-extension.spec.ts npm exec -- nx run playground-cli:typecheck npm exec -- nx run php-wasm-universal:typecheck npm exec -- nx run playground-cli:lint npm exec -- nx run php-wasm-universal:lint npm exec -- nx run php-wasm-compile-extension:typecheck npm exec -- nx run php-wasm-compile-extension:lint git diff --check ```
1 parent 90be6be commit 5c43ef8

12 files changed

Lines changed: 1810 additions & 684 deletions

File tree

packages/php-wasm/compile-extension/README.md

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,27 @@ npx @php-wasm/compile-extension \
4444
Empty directories are recorded as `type: "directory"` nodes so the loader
4545
creates them before PHP starts.
4646

47+
If an extension needs startup settings, add them to the manifest:
48+
49+
```json
50+
{
51+
"name": "spx",
52+
"version": "0.1.0",
53+
"artifacts": [
54+
{
55+
"phpVersion": "8.4",
56+
"sourcePath": "spx-php8.4-jspi.so"
57+
}
58+
],
59+
"iniEntries": {
60+
"spx.http_enabled": "1"
61+
},
62+
"env": {
63+
"SPX_DATA_DIR": "/internal/shared/spx/data"
64+
}
65+
}
66+
```
67+
4768
The supported `--php-versions` are `7.4` and `8.0` through `8.5`.
4869

4970
Docker is required. The CLI lazily fetches the small PHP.wasm Docker asset set
@@ -60,14 +81,14 @@ The package only needs Docker and Node. It does not require a checkout of
6081

6182
- uses: actions/setup-node@v4
6283
with:
63-
node-version: '24'
84+
node-version: '24'
6485

6586
- run: |
66-
npx --yes @php-wasm/compile-extension \
67-
--source ./my-extension \
68-
--name my_extension \
69-
--php-versions 8.0,8.1,8.2,8.3,8.4,8.5 \
70-
--out ./dist/my-extension
87+
npx --yes @php-wasm/compile-extension \
88+
--source ./my-extension \
89+
--name my_extension \
90+
--php-versions 8.0,8.1,8.2,8.3,8.4,8.5 \
91+
--out ./dist/my-extension
7192
```
7293
7394
In a matrix workflow, set `strategy.max-parallel: 1` on the WASM job —

packages/php-wasm/compile-extension/src/manifest.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,20 @@ export interface ExtensionArtifact {
3535
export interface ExtensionManifest {
3636
name: string;
3737
version: string;
38+
/**
39+
* The first directive of the generated startup `.ini` file. Defaults to
40+
* `extension`; use `zend_extension` for Zend extensions like Xdebug.
41+
*/
42+
loadWithIniDirective?: 'extension' | 'zend_extension';
43+
/** Additional `key=value` lines for the generated startup `.ini` file. */
44+
iniEntries?: Record<string, string>;
45+
/** Environment variables added before the extension is loaded. */
46+
env?: Record<string, string>;
47+
/**
48+
* VFS directory where PHP.wasm writes the extension `.so` file and its
49+
* per-extension ini file.
50+
*/
51+
extensionDir?: string;
3852
artifacts: ExtensionArtifact[];
3953
/** URL-backed files shared by every artifact in this manifest. */
4054
extraFiles?: ExtensionManifestExtraFiles;

0 commit comments

Comments
 (0)