RubyがWebAssemblyのWASI対応へ前進。ブラウザでもサーバでもエッジでもどこでもWebAssembly版Rubyが動くように - Publickey という記事で紹介されている WASI 対応がマージされたので試してみました。
動作確認環境
- Ubuntu 21.10 (amd64)
wasi-sdk-14.0-linux.tar.gz
binaryen-version_91-x86_64-linux.tar.gz
- wasmtime 0.33.0
wasm/README.md に従って WASI SDK の 14.0 と Binaryen version 91 をダウンロードしました。 WASI SDK や Binaryen のバイナリリリースが Linux は x86-64 しかないので、 aarch64 で試すのは自前でビルドが必要そうで大変そうなので避けました。
準備
WASI SDK をダウンロードして展開して、 export WASI_SDK_PATH=$HOME/wasi-sdk-14.0
を .bashrc
に設定しました。 WASI SDK は PATH
には追加しません。
Binaryen もダウンロードして展開して、 export PATH="$HOME/binaryen-version_91:$PATH"
を .bashrc
に設定しました。
Configure
クロスコンパイルには同じバージョンの host ruby を使う必要があるので、README の例に --with-baseruby
を追加して configure
を実行しました。 コマンドライン全体は /path/to/github.com/ruby/ruby/configure LDFLAGS="-Xlinker -zstack-size=16777216" --host wasm32-unknown-wasi --with-destdir=./ruby-wasm32-wasi --with-static-linked-ext --with-ext=ripper,monitor --with-baseruby=$(RBENV_VERSION=master rbenv which ruby)
のように指定しました。
Make
make install
を実行すると --with-destdir
で指定した ./ruby-wasm32-wasi
にインストールされました。
wasmtime のインストール
実行環境として wasmtime をインストールしました。
curl https://wasmtime.dev/install.sh -sSLO
bash ./install.sh
.bashrc
に以下の内容が追加されていました。
export WASMTIME_HOME="$HOME/.wasmtime"
export PATH="$WASMTIME_HOME/bin:$PATH"
実行確認
README に書いてある例などが実行できることを確認できました。
$ wasmtime ruby-wasm32-wasi/usr/local/bin/ruby --mapdir /::./ruby-wasm32-wasi/ -- -e 'puts RUBY_DESCRIPTION'
ruby 3.2.0dev (2022-01-19T21:45:28Z master 2b7025e680) [wasm32-wasi]
昨日の時点は wasmtime ruby-wasm32-wasi/usr/local/bin/ruby --mapdir /::./ruby-wasm32-wasi/ -- --disable-gems -e 'puts RUBY_DESCRIPTION'
のように --disable-gems
を付ける必要がありましたが、 2b7025e680eb29f936538c07f057f590003e45bf がマージされて不要になりました。
irb は wasmtime ruby-wasm32-wasi/usr/local/bin/ruby --mapdir /::./ruby-wasm32-wasi/ -- -e binding.irb
で試そうとしても io-console
がなくて使えなかったので、手軽に色々試すのに sample/eval.rb
を使ってみました。ファイルの読み書きも問題なくできるようです。
$ cp ..../sample/eval.rb ruby-wasm32-wasi/
$ wasmtime ruby-wasm32-wasi/usr/local/bin/ruby --mapdir /::./ruby-wasm32-wasi/ -- /eval.rb
ruby> RUBY_DESCRIPTION
"ruby 3.2.0dev (2022-01-19T21:45:28Z master 2b7025e680) [wasm32-wasi]"
ruby> 2**128
340282366920938463463374607431768211456
ruby> Dir.children '.'
["eval.rb", "usr"]
ruby> File.write 'foo', 'bar'
3
ruby> File.read 'foo'
"bar"
ruby> Dir.children '.'
["foo", "eval.rb", "usr"]
ruby> File.unlink 'foo'
1
ruby> Dir.children '.'
["eval.rb", "usr"]
感想
バイナリリリースのアーキテクチャ依存が想定外でしたが、そこ以外は比較的スムーズに試すことができました。 まだ制限も色々ありますが、 3.2 の preview1 がリリースされたり、色々な使い方がされたりすると、広く使われるようになるかもしれません。