From 9d5ec5e3bc01c6174dea048e118edee579c36565 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sat, 7 Feb 2026 23:06:23 +0900 Subject: fix(style): fix codeblock style for rouge --- .../compile-php-runtime-to-wasm/index.html | 252 ++++++++++----------- 1 file changed, 121 insertions(+), 131 deletions(-) (limited to 'services/nuldoc/public/blog/posts/2023-10-02/compile-php-runtime-to-wasm/index.html') diff --git a/services/nuldoc/public/blog/posts/2023-10-02/compile-php-runtime-to-wasm/index.html b/services/nuldoc/public/blog/posts/2023-10-02/compile-php-runtime-to-wasm/index.html index 7879f5df..33ad3d2b 100644 --- a/services/nuldoc/public/blog/posts/2023-10-02/compile-php-runtime-to-wasm/index.html +++ b/services/nuldoc/public/blog/posts/2023-10-02/compile-php-runtime-to-wasm/index.html @@ -15,7 +15,7 @@ PHP の処理系を Emscripten で WebAssembly にコンパイルする|REPL: Rest-Eat-Program Loop - +
@@ -142,19 +142,18 @@
index.mjs
-
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(`exit code: ${result}`);
-
+
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(`exit code: ${result}`);

標準入力から与えたコードを WebAssembly にコンパイルされた PHP 処理系の上で実行している。このような php-wasm.mjs (とそこから呼び出される php-wasm.wasm) を作成する。 @@ -168,31 +167,30 @@ 先ほどのコードでも使っていたエントリポイントである php_wasm_run を用意する。

-
#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;
-}
-
+
#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; +
}

ほとんどはただの PHP の公開 API を使ったコードだが、Emscripten 向けの注意点が 2点ある。 @@ -215,16 +213,15 @@ デフォルトの出力方法は index.mjs の中で PHPWasm() を呼ぶとき、stdoutstderr というオプションを渡せば変更できる。

-
const { ccall } = await PHPWasm({
-  stdout: (c) => {
-    if (c === null) {
-      // flush the standard output.
-    } else {
-      // output c to the standard output.
-    }
-  },
-});
-
+
const { ccall } = await PHPWasm({ +
stdout: (c) => { +
if (c === null) { +
// flush the standard output. +
} else { +
// output c to the standard output. +
} +
}, +
});

cnull か 1バイト符号つき整数を取り、null が flush 要求を意味する。 @@ -244,52 +241,49 @@ まずは Emscripten 公式が提供している Docker イメージ を使って、PHP 処理系と先ほど示した C 言語のソースコードを WebAssembly にコンパイルする。

-
FROM emscripten/emsdk:3.1.46 AS wasm-builder
-
+
FROM emscripten/emsdk:3.1.46 AS wasm-builder

次に、 php/php-src から PHP 処理系のソースコードを取得し、ビルドに必要な apt パッケージを取ってくる。有効にする拡張を増やしたいなら、ここでインストールするパッケージも増やすことになるだろう。

-
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 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 \ +
&& \ +
:

続けて、Emscripten のツールチェインを用いて PHP 処理系をビルドする。

-
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 && \
-    :
-
+
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 && \ +
:

ここまでと比べると少し複雑なので、それぞれ詳しく見ていこう。 @@ -313,23 +307,22 @@ さて、PHP 処理系をライブラリ化できたので、次に先ほど載せた C のソースコードをビルドしていこう。Dockerfile と同じ場所に php-wasm.c という名前で保存し、次のようにする。

-
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 && \
-    :
-
+
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 && \ +
:

emcccc (C コンパイラ/リンカ) の Emscripten 版で、-c は「コンパイル」の意。-o-I は普通の C コンパイラと同様、出力ファイルの指定とインクルードパスの指定である。 @@ -338,19 +331,18 @@ libphp.aphp-wasm.o が手に入ったので、これらをリンクして WebAssembly のバイナリとそのラッパである JavaScript ファイルを生成する。これにも emcc コマンドを使う。

-
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 \
-    ;
-
+
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 \ +
;

それぞれのフラグについて解説する。 @@ -383,15 +375,14 @@ といっても、Node.js はビルトインで WebAssembly をサポートしているので、ほとんどやることはない。先ほど掲載した JavaScript のコードは、Dockerfile と同じディレクトリに index.mjs で配置すること。

-
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"]
-
+
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"]
@@ -401,13 +392,12 @@ Dockerfilephp-wasm.cindex.mjs を用意したら、Docker コンテナをビルドして実行する。

-
$ docker build -t php-wasm .
-$ echo 'echo "Hello, World!", PHP_EOL;' | docker run --rm -i php-wasm
-Hello, World!
-
-
-exit code: 0
-
+
$ docker build -t php-wasm . +
$ echo 'echo "Hello, World!", PHP_EOL;' | docker run --rm -i php-wasm +
Hello, World! +
+
+
exit code: 0
-- cgit v1.3-1-g0d28