Skip to content
/ php-wasm Public template
forked from seanmorris/php-wasm

PHP WebAssembly docker image. Original Project by Oraoto and Sean Morris.

License

Notifications You must be signed in to change notification settings

soyuka/php-wasm

 
 

Repository files navigation

WASM PHP

Project based on https://github.com/seanmorris/php-wasm which was forked from https://github.com/oraoto/pib

I fixed some inconsistencies in the Makefile and removed non-essential things. This fork:

  • builds sqlite3
  • builds libxml
  • no javascript abstraction
  • exposes FS and builds with IDBFS
  • does not build https://github.com/seanmorris/vrzno which allows javascript access from PHP (TODO add this back opt-in cause it's really cool)
  • does not add preloaded data, having this separatly from php-wasm builds allows for more flexibility (see preload data section)

Build

docker buildx bake

Builded files will be located in build/php-web.js and build/php-web.wasm. The module we export in this image is called createPhpModule.

Build arguments

Use this as template to build PHP with emscripten. At build these arguments are available:

LIBXML2_TAG=v2.9.10
PHP_BRANCH=PHP-8.3.0

The next args are used for emcc options -sOPTION see settings.js. In fact it's even easier for you to set them directly in the Dockerfile.

WASM_ENVIRONMENT=web
ASSERTIONS=0
OPTIMIZE=-O2
INITIAL_MEMORY=256mb
JAVASCRIPT_EXTENSION=mjs # change by js if needed
MODULARIZE=1
EXPORT_ES6=1
EXPORT_NAME=createPhpModule

Preload data

My preferred option is to use the file_packager tool to build the preloaded data in a php-web.data.js (and php-web.data file). These are preloaded into IDBFS. That can be changed changing the -lidbfs.js argument to emcc.

This will preload SOME_DIR into the /src directory inside the WASM filesystem:

mkdir -p php-wasm
docker run -v SOME_DIR:/src -v $(pwd)/php-wasm:/dist -w /dist soyuka/php-wasm:8.2.9 python3 /emsdk/upstream/emscripten/tools/file_packager.py php-web.data --use-preload-cache --lz4 --preload "/src" --js-output=php-web.data.js --no-node --exclude '*/.*' --export-name=createPhpModule
ls php-wasm/

Note that the php-web.data.js must be either used as PRE_JS argument to emcc or it needs to be included inside the php-web.js:

sed '/--pre-js/r php-wasm/php-web.data.js' php-wasm/php-web.mjs > this-has-preloaded-data-php-web.mjs

We match the export-name with the emcc EXPORT_NAME option. Use excludes to downsize the preloaded data weight.

Usage

To execute some php, call phpw_exec using ccall, for example:

const phpBinary = require('build/php-web');

return phpBinary({
    onAbort: function(reason) {
      console.error('WASM aborted: ' + reason)
    },
    print: function (...args) {
      console.log('stdout: ', args)
    },
    printErr: function (...args) {
      console.log('stderr: ', args)
    }
})
.then(({ccall, FS}) => {
  const phpVersion = ccall(
    'phpw_exec'
    , 'string'
    , ['string']
    , [`phpversion();`]
  );
})

API

phpw_exec(string code): string
phpw_run(string code): void
phpw(string filePath): void

Example calls:

const STR = 'string';
ccall("phpw", null, [STR], ["public/index.php"]);
console.log(ccall("phpw_exec", STR, [STR], ["phpversion();"]));

More about how to call exposed functions

Demo

Before running the demo, you need to build the library.

docker buildx bake

Then you need to copy the php-web.js and php-web.wasm to the demo directory.

$ cp build/php-web.* demo/public/

Then to build the preloaded data:

docker run \
  -v $(pwd)/demo/src:/src \
  -v $(pwd)/demo/public:/dist \
  -w /dist \
  soyuka/php-wasm:8.2.9 \
  python3 \
    /emsdk/upstream/emscripten/tools/file_packager.py \
    php-web.data \
      --use-preload-cache \
      --lz4 \
      --preload "/src" \
      --js-output=php-web.data.js \
      --no-node \
      --exclude '*/.*' \
      --export-name=createPhpModule

Then attach the php-web.data.js to the demo/public/php-web.mjs:

sed '/--pre-js/r demo/public/php-web.data.js' demo/public/php-web.mjs > this-has-preloaded-data-php-web.mjs ; mv this-has-preloaded-data-php-web.mjs demo/public/php-web.mjs

And finally open a web sserver in the demo directory:

$ php -S 127.0.0.1:8000 -t demo/public

TODO

  • add opt-in / opt-out sqlite libxml vrzno and mb more

About

PHP WebAssembly docker image. Original Project by Oraoto and Sean Morris.

Topics

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Sponsor this project

 

Languages

  • Dockerfile 69.5%
  • C 29.2%
  • HCL 1.3%