aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.dockerignore0
-rw-r--r--.editorconfig8
-rw-r--r--.gitignore1
-rw-r--r--Dockerfile75
-rw-r--r--README.md22
-rw-r--r--index.mjs12
-rw-r--r--php-wasm.c24
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;
+}