あまり公式にアナウンスされていない気がするが*1、 ruby.wasm は実はComponent Model対応が済んでいる。
多分この辺から。なので、RubyKaigi 2024の段階ではComponent Model対応したものを動かせていた。スライドで言うとこの辺 *2。
この記事では簡単にビルドの仕方をまとめておく。
command でビルドする
以下の内容の Gemfile
を使って:
source "https://rubygems.org" gem "ruby_wasm", "~> 2.7"
以下のコマンドでビルドすればOK*3。
$ RUBY_WASM_EXPERIMENTAL_DYNAMIC_LINKING=1 bundle exec rbwasm build -o rubyp2.wasm --target wasm32-unknown-wasip2
witを見ると以下の感じになっている(抜粋)。
package root:component; world root { import wasi:cli/exit@0.2.0; import wasi:clocks/wall-clock@0.2.0; import wasi:random/random@0.2.0; import wasi:cli/environment@0.2.0; import wasi:io/error@0.2.0; import wasi:io/poll@0.2.0; import wasi:io/streams@0.2.0; import wasi:clocks/monotonic-clock@0.2.0; import wasi:cli/stdin@0.2.0; import wasi:cli/stdout@0.2.0; import wasi:cli/stderr@0.2.0; import wasi:cli/terminal-input@0.2.0; import wasi:cli/terminal-output@0.2.0; import wasi:cli/terminal-stdin@0.2.0; import wasi:cli/terminal-stdout@0.2.0; import wasi:cli/terminal-stderr@0.2.0; import wasi:filesystem/types@0.2.0; import wasi:filesystem/preopens@0.2.0; export wasi:cli/run@0.2.0; }
こうなので、成果物は wasmtime
でそのまま実行できる。
$ wasmtime rubyp2.wasm --version ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [wasm32-wasi]
reactor でビルドする
Gemfile
に js
gemを含む必要があるらしい。参照
source "https://rubygems.org" gem "ruby_wasm", "~> 2.7" gem "js"
コマンドは同じでOK。
$ RUBY_WASM_EXPERIMENTAL_DYNAMIC_LINKING=1 bundle exec rbwasm build -o rubyp2-reactor.wasm --target wasm32-unknown-wasip2
wit が結構変わっていて、 ruby:js/js-runtime
を必要とし、 ruby:js/ruby-runtime
を export している。
package root:component; world root { import wasi:cli/exit@0.2.0; import wasi:clocks/wall-clock@0.2.0; import wasi:random/random@0.2.0; import ruby:js/js-runtime; import wasi:cli/environment@0.2.0; import wasi:io/error@0.2.0; import wasi:io/poll@0.2.0; import wasi:io/streams@0.2.0; import wasi:clocks/monotonic-clock@0.2.0; import wasi:cli/stdin@0.2.0; import wasi:cli/stdout@0.2.0; import wasi:cli/stderr@0.2.0; import wasi:cli/terminal-input@0.2.0; import wasi:cli/terminal-output@0.2.0; import wasi:cli/terminal-stdin@0.2.0; import wasi:cli/terminal-stdout@0.2.0; import wasi:cli/terminal-stderr@0.2.0; import wasi:filesystem/types@0.2.0; import wasi:filesystem/preopens@0.2.0; export ruby:js/ruby-runtime; }
これらは js.gem の方でwitを置いている 。したがって、JS側でどういう関数を用意して、Rubyの機能としてはどういうものが使えるのかが大変わかりやすくなっている。
僕はこう思ったっス
すでにComponent化して import/export で何を切り出すか調整できる状態になってそうだし、そもそもComponentなので薄いアダプターComponentをいい感じに作れば、 componetize-rb は普通にできるっぽい。wasmcloudで頑張って動かすというのをやるとかはいいと思った。Go、Rust、TypeScriptしかない ので、Pythonが追加される前に...。
で、そうすると、純粋にjsじゃないreactor版が欲しい感じがする。