diff options
| -rw-r--r-- | .dockerignore | 0 | ||||
| -rw-r--r-- | .editorconfig | 8 | ||||
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Dockerfile | 75 | ||||
| -rw-r--r-- | README.md | 22 | ||||
| -rw-r--r-- | index.mjs | 12 | ||||
| -rw-r--r-- | php-wasm.c | 24 |
7 files changed, 142 insertions, 0 deletions
diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/.dockerignore diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..a4b824b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,8 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c95c61 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/lib/php-wasm.* diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1ffc8d3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,75 @@ +FROM emscripten/emsdk:3.1.46 AS wasm-builder + +RUN git clone --depth=1 --branch=php-8.2.10 https://github.com/php/php-src + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + autoconf \ + bison \ + pkg-config \ + re2c \ + && \ + : + +RUN cd php-src && \ + ./buildconf --force && \ + emconfigure ./configure \ + --disable-all \ + --disable-mbregex \ + --disable-fiber-asm \ + --disable-cli \ + --disable-cgi \ + --disable-phpdbg \ + --enable-embed=static \ + --enable-mbstring \ + --without-iconv \ + --without-libxml \ + --without-pcre-jit \ + --without-pdo-sqlite \ + --without-sqlite3 \ + && \ + EMCC_CFLAGS='-s ERROR_ON_UNDEFINED_SYMBOLS=0' emmake make -j$(nproc) && \ + mv libs/libphp.a .. && \ + make clean && \ + git clean -fd && \ + : + +COPY php-wasm.c /src/ + +RUN cd php-src && \ + emcc \ + -c \ + -o php-wasm.o \ + -I . \ + -I TSRM \ + -I Zend \ + -I main \ + ../php-wasm.c \ + && \ + mv php-wasm.o .. && \ + make clean && \ + git clean -fd && \ + : + +RUN emcc \ + -s ENVIRONMENT=node \ + -s ERROR_ON_UNDEFINED_SYMBOLS=0 \ + -s EXPORTED_RUNTIME_METHODS='["ccall"]' \ + -s EXPORT_ES6=1 \ + -s INITIAL_MEMORY=16777216 \ + -s INVOKE_RUN=0 \ + -s MODULARIZE=1 \ + -o php-wasm.js \ + php-wasm.o \ + libphp.a \ + ; + + +FROM node:20.7 + +WORKDIR /app +COPY --from=wasm-builder /src/php-wasm.js /app/php-wasm.mjs +COPY --from=wasm-builder /src/php-wasm.wasm /app/php-wasm.wasm +COPY index.mjs /app/ + +ENTRYPOINT ["node", "index.mjs"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..ba182c7 --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# tiny-php.wasm + +A tiny example to compile PHP runtime ([php/php-src](https://github.com/php/php-src)) to WebAssembly. + +Article about this repo (Japanese): https://blog.nsfisis.dev/posts/2023-10-02/compile-php-runtime-to-wasm/ + + +## Build + +``` +$ docker build -t php-wasm . +``` + +## Run + +``` +$ echo 'echo "Hello, World!", PHP_EOL;' | docker run --rm -i php-wasm +``` + +## License + +Public Domain diff --git a/index.mjs b/index.mjs new file mode 100644 index 0000000..f58aa15 --- /dev/null +++ b/index.mjs @@ -0,0 +1,12 @@ +import { readFile } from 'node:fs/promises'; +import PHPWasm from './php-wasm.mjs' + +const code = await readFile('/dev/stdin', { encoding: 'utf-8' }); + +const { ccall } = await PHPWasm(); +const result = ccall( + 'php_wasm_run', + 'number', ['string'], + [code], +); +console.log(`result: ${result}`); diff --git a/php-wasm.c b/php-wasm.c new file mode 100644 index 0000000..cef661f --- /dev/null +++ b/php-wasm.c @@ -0,0 +1,24 @@ +#include <stdio.h> +#include <emscripten.h> +#include <Zend/zend_execute.h> +#include <sapi/embed/php_embed.h> + +int EMSCRIPTEN_KEEPALIVE php_wasm_run(const char* code) { + zend_result result; + + int argc = 1; + char* argv[] = { "php.wasm", NULL }; + + PHP_EMBED_START_BLOCK(argc, argv); + + result = zend_eval_string_ex(code, NULL, "php.wasm code", 1); + + PHP_EMBED_END_BLOCK(); + + fprintf(stdout, "\n"); + fflush(stdout); + fprintf(stderr, "\n"); + fflush(stderr); + + return result == SUCCESS ? 0 : 1; +} |
