Yuta Saito eac35edfd1 [wasm] Stop using mprotect(PROT_NONE) on WASI
we had been using a stub weak definition of `mprotect` in wasm/missing.c
so far, but wasi-sdk 23 added mprotect emulation to wasi-libc[^1], so the
emulation is now linked instead. However, the emulation doesn't support
PROT_NONE and fails with ENOSYS, so we need to avoid calling mprotect
completely on WASI.

[^1]: 7528b13170
2025-02-19 11:46:12 +09:00
..

WebAssembly / WASI port of Ruby

How to cross-build

Requirement

  • Ruby (the same version as the building target version) (baseruby)
  • GNU make
  • WASI SDK 14.0 or later
  • Binaryen version 106 or later
  • Linux or macOS build machine

Steps

  1. Download a prebuilt WASI SDK package from WASI SDK release page.

  2. Set WASI_SDK_PATH environment variable to the root directory of the WASI SDK package.

    $ export WASI_SDK_PATH=/path/to/wasi-sdk-X.Y
    
  3. Download a prebuilt binaryen from Binaryen release page

  4. Set PATH environment variable to lookup binaryen tools

    $ export PATH=path/to/binaryen:$PATH
    
  5. Download the latest config.guess with WASI support, and run ./autogen.sh to generate configure when you are building from the source checked out from Git repository

    $ ruby tool/downloader.rb -d tool -e gnu config.guess config.sub
    $ ./autogen.sh
    
  6. Configure

    • You can select which extensions you want to build.

    • If you got Out of bounds memory access while running the produced ruby, you may need to increase the maximum size of stack.

      $ ./configure LDFLAGS="-Xlinker -zstack-size=16777216" \
        --host wasm32-unknown-wasi \
        --with-destdir=./ruby-wasm32-wasi \
        --with-static-linked-ext \
        --with-ext=ripper,monitor
      
  7. Make

    $ make install
    

Now you have a WASI compatible ruby binary. You can run it by any WebAssembly runtime like wasmtime, wasmer, Node.js, or browser with WASI polyfill.

Note: it may take a long time (~20 sec) for the first time for JIT compilation

$ wasmtime ruby-wasm32-wasi/usr/local/bin/ruby --mapdir /::./ruby-wasm32-wasi/ -- -e 'puts RUBY_PLATFORM'
wasm32-wasi

Note: you cannot run the built ruby without a WebAssembly runtime, because of the difference of the binary file type.

$ ruby-wasm32-wasi/usr/local/bin/ruby -e 'puts "a"'
bash: ruby-wasm32-wasi/usr/local/bin/ruby: cannot execute binary file: Exec format error

$ file ruby-wasm32-wasi/usr/local/bin/ruby
ruby-wasm32-wasi/usr/local/bin/ruby: WebAssembly (wasm) binary module version 0x1 (MVP)

Current Limitation

  • No Thread support for now.
  • Spawning a new process is not supported. e.g. Kernel.spawn and Kernel.system