Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RubyGems on ruby.wasm

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

RubyGems on ruby.wasm

Avatar for Yuta Saito

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