Share
Embed
RubyGems on ruby.wasm
Yuta Saito
May 16, 2024
Transcript
46 slides
-
About me • Yuta Saito / @kateinoigakukun • Master's student
at Waseda University • Newbie commi>er of CRuby and SwiB • Creator of ruby.wasm 3 -
Overview 1. Introduc+on to ruby.wasm 2. Challenges of RubyGems support
3. Demo 4. Technical details 5. Future vision 4 -
1. Introduc,on: ruby.wasm • Introduced in RubyKaigi 2022 • Enables
running Ruby on everywhere by WebAssembly • This project consists of: 1. CRuby interpreter compiled to WebAssembly 2. Packaging system for interpreter + .rb files 3. JS interop library ( require 'js') 5 -
<html> <script src="https://cdn.jsdelivr.net/.../dist/browser.script.iife.js"></script> <script type="text/ruby" data-eval="async"> require 'js' button =
JS.global[:document].createElement("button") button[:textContent] = "Click me!" button.addEventListener("click") do puts "Hello~" end response = JS.global.fetch("https://example.com/data.json").await puts response.json.await </script> </html> 6 -
2. Challenges of RubyGems support RubyGems has two main components:
1. Installer: gem install 2. Run:me loader: require 'gem_name' 9 -
2. Challenges of RubyGems support Run$me loader ✅ • Supported
from early versions • require 'gem_name' works as expected 10 -
2. Challenges of RubyGems support Gem installer ! When to
install gems? • On-the-fly installa/on • Pre-installa/on 11 -
2. Challenges of RubyGems support On-the-fly installa.on Install Gems at
run-.me • Convenient way for daily scrip4ng • Run gem install on Wasm • Requires network access at 12 -
2. Challenges of RubyGems support On-the-fly installa.on • I showed
on-the-fly installa2on demo at RubyKaigi 2022. • Network access is passed through the browser's fetch API. • You can try it now on runruby.dev by Svyatoslav • No built-in support 13 -
2. Challenges of RubyGems support Pre-installa+on Install Gems in advance
before running the Ruby program. • No network access at Run- 1me • "build" step before running the Ruby program. 14 -
Today's focus Pure-Ruby Gems C-Extension Gems On-the-fly installa.on ⚠ ❌
Pre-installa.on ❌ ❌ 15 -
Today's focus Pure-Ruby Gems C-Extension Gems On-the-fly installa.on ⚠ ❌
Pre-installa6on # # 16 -
Possible use case? "Serverless Staging": Host Rails app as a
sta3c site • Low-cost • Low security risk • e.g. Preview environments for Pull Requests 21 -
4. Technical details 1. Package Gems 2. Cross-compile C-Extensions 3.
Pre-link C-Extension shared libraries 23 -
4.1. Package Gems Package gem source files into the WebAssembly
binary by VFS # WARNING: Still Experimental $ bundle add ruby_wasm --group=development $ bundle add rainbow $ bundle exec rbwasm build -o ruby.wasm (snip) INFO: Packaging gem: rainbow-3.1.1 INFO: Size: 51.17 MB 24 -
4.2. Cross-compile C-Extensions Cross-compila,on support in mkmf • mkmf is
the core of the C-extension build system in Ruby • 3 major mkmf users (extconf.rb consumers in in other words): • CRuby build system • rake-compiler • RubyGems 26 -
4.2. Cross-compile C-Extensions Cross-compila,on support status in major mkmf users
• CRuby build system & rake-compiler: • Fake rbconfig.rb trick • RubyGems: " • Does not support cross-compila<on at all 27 -
4.2. Cross-compile C-Extensions Exis%ng rbconfig.rb trick • Overwrite top-level RbConfig
constants • Does not work for some corner cases $ ruby -rrbconfig -rwasm32-wasi-fake extconf.rb # ./rbconfig.rb module RbConfig # For target platform ... end # ./wasm32-wasi-fake.rb class Object remove_const :CROSS_COMPILING if defined?(CROSS_COMPILING) CROSS_COMPILING = RUBY_PLATFORM constants.grep(/^RUBY_/) {|n| remove_const n} RUBY_VERSION = "3.4.0" RUBY_RELEASE_DATE = "2024-05-11" RUBY_PLATFORM = "wasm32-wasi" ... end 28 -
# From https://github.com/rake-compiler/rake-compiler/blob/v1.2.7/lib/rake/extensiontask.rb # Pre-load resolver library before faking, in
order to avoid error # "cannot load such file -- win32/resolv" when it is required later on. # See also: https://github.com/tjschuck/rake-compiler-dev-box/issues/5 require 'resolv' require 'rbconfig' ... 29 -
4.2. Cross-compile C-Extensions Cross-compila,on support without trick ✅ Feature #20345:
Add --target-rbconfig op3on to mkmf2 h9ps:/ /bugs.ruby-lang.org/issues/20345 $ ruby extconf.rb --target-rbconfig=path/to/rbconfig.rb creating Makefile $ make $ file nokogiri.so nokogiri.so: WebAssembly (wasm) binary module version 0x1 (MVP) 2 Will be available in Ruby 3.4 and later 30 -
4.2. Cross-compile C-Extensions Cross-compila,on support in RubyGems ! PR #7628:
Add --target-rbconfig op.on to gem install h"ps:/ /github.com/rubygems/rubygems/pull/7628 $ gem install nokogiri --target-rbconfig=path/to/rbconfig.rb $ bundle install --target-rbconfig=path/to/rbconfig.rb 31 -
4.3. Pre-link C-Extension shared libraries Why not sta*c linking? •
We already support sta/cally-linked C-extensions • But, the build model is not suitable for the RubyGems ecosystem • Take a long linking /me (especially due to Asyncify) • Need to /ghtly integrate with the CRuby build system 33 -
4.3. Pre-link C-Extension shared libraries Why not dynamic linking so
far? • WebAssembly does not have a standard dynamic linking ABI • If we do our bespoke dynamic linking3, the binary will be incompa?ble with standard WebAssembly run?mes 3 Emscripten does dynamic linking by its own loader 35 -
4.3. Pre-link C-Extension shared libraries Breakthrough: Component Model • A
new layer of WebAssembly standard • Consists of: • WIT (WebAssembly Interface Types) IDL • Module linking • ... and more 36 -
4.3. Pre-link C-Extension shared libraries Dynamic Linking upon Component Model
• Each module has its metadata for dynamic linking • "AOT" linker encapsulates "how to link modules" into Component 38 -
4.3. Pre-link C-Extension shared libraries AOT dynamic linking A new
concept of dynamic linking in WebAssembly • Done at the build /me • The final binary is a Component • The linker is originally developed by Joel Dice in wit-component • Adjusted for Ruby use case 39 -
4.3. Pre-link C-Extension shared libraries Difference from the tradi0onal dynamic
linking • The final binary, a Component, contains all the dependencies • No file-based shared library search at run:me • dlopen is available only for libraries known at build-:me 40 -
Current status Pure-Ruby Gems C-Extension Gems On-the-fly installa.on ⚠ ❌
Pre-installa6on ✅ ✅ (soon) 41 -
Summary • RubyGems support will be available soon on ruby.wasm
• Ruby is leveraging the state-of-the-art WebAssembly technology including the Component Model 45 -
Acknowledgements • Supported by the Ruby Associa4on Grant Program •
Advised by @mame and @ko1 46