2018-02-15
■[Ruby] emruby: emscripten でブラウザで動く MRI
(この記事は Ruby 25th anniversary のための寄稿になる予定です)
Ruby をブラウザで動かすというと Opal ですが、他の選択肢として、C で書かれた Ruby 処理系を emscripten で JS に変換するという選択肢もあります。
しかし調べてみたところ、mruby を WebAssembly に変換した記録は見つかりましたが、MRI でやった例が見つけられなかったので、やってみました。
デモ
https://mame.github.io/emruby/
手順
https://github.com/mame/emruby/ に書いてあるとおりです。
ビルドコマンドは次の通り。
$ emconfigure ./configure CFLAGS="-m32 -s EMULATE_FUNCTION_POINTER_CASTS=1" $ emmake make V=1 miniruby.js EXEEXT=.js
emconfigure は emscripten をコンパイラとして使う前提で configure を動かすためのラッパ。しかしあまり出来はよくなくて、64 bit 環境で動かすと SIZEOF_LONG が 8 と推定されてしまった(JS 上で sizeof(long) は 4 になるので食い違う)ので、手動で "-m32" を与えています。そのため -m32 でコンパイルできる環境が必要で、ubuntu なら apt-get install libc6-dev-i386 などする必要があります。
また、MRI は関数ポインタについてあまり行儀がよくない(3 引数の関数に 4 つの引数を渡すとかがそこらじゅうにある)ので、"-s EMULATE_FUNCTION_POINTER_CASTS=1" を与える必要があります(参考:emscripten の Function Pointer Issues)。
emmake は make のラッパ。単に miniruby.js を生成するだけです。
所感など
- 動作するまでに細かい問題がいくつかありましたが、Ruby 側を少しだけいじって対応しました(変更 1、変更 2、変更 3)。Ruby が公式に emscripten に対応するのは難しそうな印象ですが、本体に無害なパッチならこっそり取り込めると思うので、プルリクお願いします。
- Kernel#emscripten_run_script を生やしています。(パッチ)
- miniruby ではなく ruby が動かしたい。(プルリクウェルカム)
- ファイルシステムを調べて irb くらい動くようにしたい。(プルリクウェルカム)
- Run ボタンが一回しか押せない。プロセス再実行する方法が見つけられなかった。
- miniruby.js が 29 MB もある。WebAssembly だと 5 MB くらいになるようですが、Chrome で素直に動かなかったのでよく見ていません。
- WebAssembly で Ruby が Web フロントエンド市場に(今度こそ)進出できるといいなあ。Opal は JS に合わせて Ruby の仕様を歪めてるのがあんまり好きじゃなくて、emscripten/WebAssembly なら幸せになるかと思ったけど、まだよくわかりません。
- 78 https://t.co/ps8CggBI8I
- 26 https://t.co/UvrjMkldUm
- 14 http://b.hatena.ne.jp/
- 6 http://www.google.co.uk/url?sa=t&source=web&cd=1
- 6 https://t.co/2QsND3NOJd
- 4 http://b.hatena.ne.jp/entrylist
- 4 http://b.hatena.ne.jp/entrylist?sort=hot
- 4 http://hatebu.straightline.jp/
- 4 http://htn.to/FujT2u
- 4 https://t.co/ps8CggBI8I?amp=1
- 2018-02-14 PB memo 4/41 9%