$30 off During Our Annual Pro Sale. View Details »

RubyGems on ruby.wasm

RubyGems on ruby.wasm

Yuta Saito

May 16, 2024
Tweet

More Decks by Yuta Saito

Other Decks in Programming

Transcript

  1. 2

  2. About me • Yuta Saito / @kateinoigakukun • Master's student

    at Waseda University • Newbie commi>er of CRuby and SwiB • Creator of ruby.wasm 3
  3. Overview 1. Introduc+on to ruby.wasm 2. Challenges of RubyGems support

    3. Demo 4. Technical details 5. Future vision 4
  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
  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
  6. 2. Challenges of RubyGems support RubyGems has two main components:

    1. Installer: gem install 2. Run:me loader: require 'gem_name' 9
  7. 2. Challenges of RubyGems support Run$me loader ✅ • Supported

    from early versions • require 'gem_name' works as expected 10
  8. 2. Challenges of RubyGems support Gem installer ! When to

    install gems? • On-the-fly installa/on • Pre-installa/on 11
  9. 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
  10. 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
  11. 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
  12. 18

  13. 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
  14. 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
  15. 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
  16. 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
  17. 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
  18. # 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
  19. 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
  20. 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
  21. 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
  22. 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
  23. 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
  24. 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
  25. 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
  26. 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
  27. 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