ruby_wasm 2.6.0-aarch64-linux-musl → 2.6.2-aarch64-linux-musl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 354d4924454fa7c7db9de3c15de9942a1ddb9dd3a548637dae92f25f4df47fbd
4
- data.tar.gz: 7c760f0cca8d31bb4d4f55fd713e7b69480276e553be975b998c400aef94062c
3
+ metadata.gz: 8c8b19c5e7ab21f74c0ac7dc813cfe2e8df84542925d7411811fa96a3469100a
4
+ data.tar.gz: 2a61d70d37a302aa8ad81988eb66ba8249a71e2749ae64bae3eab4f833ea9956
5
5
  SHA512:
6
- metadata.gz: f0d8f692a1bc1264f191ae88bd0812bb00a845de0909c0c0cf9241b8e197b50b9f473beff5db2d3a297172744791d026d5b5e4ec2e2b1eb9721b33f5fc60781c
7
- data.tar.gz: f29b5f0f93000733ab7d9e594b70540ff2c6eb77d7c0bd10a6e38dcec61528a55a4f6e4e7121ee36523353a6fec4a5cf50db17c265ef5696b115eff2b369a456
6
+ metadata.gz: 32e5805301cc736df5fb09d347861a9143f3071034b7d69e02311dc08a915b1706413e30b60929409a29c8808e7f12d9386af20ac5b5ccfe3c153a0ca4e9ccfb
7
+ data.tar.gz: d6cd799bd1d44d80b4e057f09764669efb88f84b375109f2d193802a0fd067e083fd5f0da2f2fadf919d903af8dd42110a3971a2a578141a5fa208f2d61541f2
data/CONTRIBUTING.md CHANGED
@@ -6,9 +6,11 @@ This document describes development setup and pointers for diving into this proj
6
6
  ## Install dependencies
7
7
 
8
8
  ```console
9
- $ git clone https://github.com/ruby/ruby.wasm
9
+ $ git clone https://github.com/ruby/ruby.wasm --recursive
10
10
  $ cd ruby.wasm
11
11
  $ ./bin/setup
12
+ # Just for building vendor/jco (will be removed soon)
13
+ $ rustup target add wasm32-wasi
12
14
  # Compile extension library
13
15
  $ bundle exec rake compile
14
16
  $ rake --tasks
@@ -125,5 +127,5 @@ $ npm install --save @ruby/wasm-wasi@latest
125
127
  # or if you want the nightly snapshot
126
128
  $ npm install --save @ruby/wasm-wasi@next
127
129
  # or you can specify the exact snapshot version
128
- $ npm install --save @ruby/wasm-wasi@2.6.0-2024-05-05-a
130
+ $ npm install --save @ruby/wasm-wasi@2.6.2-2024-06-29-a
129
131
  ```
data/README.md CHANGED
@@ -23,7 +23,7 @@ Create and save `index.html` page with the following contents:
23
23
 
24
24
  ```html
25
25
  <html>
26
- <script src="https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.6.0/dist/browser.script.iife.js"></script>
26
+ <script src="https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.6.2/dist/browser.script.iife.js"></script>
27
27
  <script type="text/ruby">
28
28
  require "js"
29
29
 
data/Rakefile CHANGED
@@ -68,10 +68,11 @@ class BuildTask < Struct.new(:name, :target, :build_command)
68
68
  def ruby_cache_key
69
69
  return @key if @key
70
70
  require "open3"
71
+ env = { "RUBY_WASM_ROOT" => LIB_ROOT }
71
72
  cmd = build_command + ["--print-ruby-cache-key"]
72
- stdout, status = Open3.capture2(*cmd)
73
+ stdout, status = Open3.capture2(env, *cmd)
73
74
  unless status.success?
74
- raise "Command failed with status (#{status.exitstatus}): #{cmd.join ""}"
75
+ raise "Command failed with status (#{status.exitstatus}): #{cmd.join " "}"
75
76
  end
76
77
  require "json"
77
78
  @key = JSON.parse(stdout)
data/docs/cheat_sheet.md CHANGED
@@ -38,7 +38,7 @@ The easiest way to run Ruby on browser is to use `browser.script.iife.js` script
38
38
 
39
39
  ```html
40
40
  <html>
41
- <script src="https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.6.0/dist/browser.script.iife.js"></script>
41
+ <script src="https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.6.2/dist/browser.script.iife.js"></script>
42
42
  <script type="text/ruby">
43
43
  require "js"
44
44
  JS.global[:document].write "Hello, world!"
@@ -51,8 +51,8 @@ If you want to control Ruby VM from JavaScript, you can use `@ruby/wasm-wasi` pa
51
51
  ```html
52
52
  <html>
53
53
  <script type="module">
54
- import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.6.0/dist/browser/+esm";
55
- const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.6.0/dist/ruby+stdlib.wasm");
54
+ import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.6.2/dist/browser/+esm";
55
+ const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.6.2/dist/ruby+stdlib.wasm");
56
56
  const module = await WebAssembly.compileStreaming(response);
57
57
  const { vm } = await DefaultRubyVM(module);
58
58
 
@@ -69,11 +69,11 @@ If you want to control Ruby VM from JavaScript, you can use `@ruby/wasm-wasi` pa
69
69
 
70
70
  ```html
71
71
  <html>
72
- <script src="https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.6.0/dist/browser.umd.js"></script>
72
+ <script src="https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.6.2/dist/browser.umd.js"></script>
73
73
  <script>
74
74
  const main = async () => {
75
75
  const { DefaultRubyVM } = window["ruby-wasm-wasi"];
76
- const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.6.0/dist/ruby+stdlib.wasm");
76
+ const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.6.2/dist/ruby+stdlib.wasm");
77
77
  const module = await WebAssembly.compileStreaming(response);
78
78
  const { vm } = await DefaultRubyVM(module);
79
79
 
@@ -128,7 +128,7 @@ end
128
128
 
129
129
  ```html
130
130
  <html>
131
- <script src="https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.6.0/dist/browser.script.iife.js"></script>
131
+ <script src="https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.6.2/dist/browser.script.iife.js"></script>
132
132
  <script type="text/ruby" data-eval="async">
133
133
  require "js"
134
134
 
@@ -143,8 +143,8 @@ Or using `@ruby/wasm-wasi` package API `RubyVM#evalAsync`:
143
143
  ```html
144
144
  <html>
145
145
  <script type="module">
146
- import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.6.0/dist/browser/+esm";
147
- const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.6.0/dist/ruby+stdlib.wasm");
146
+ import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.6.2/dist/browser/+esm";
147
+ const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.6.2/dist/ruby+stdlib.wasm");
148
148
  const module = await WebAssembly.compileStreaming(response);
149
149
  const { vm } = await DefaultRubyVM(module);
150
150
 
@@ -0,0 +1,3 @@
1
+ ## Extension library for `ruby_wasm` gem
2
+
3
+ This library exposes WebAssembly tools and utilities from Rust ecosystem as Ruby API.
Binary file
Binary file
Binary file
@@ -42,7 +42,7 @@ module RubyWasm
42
42
  make_args
43
43
  end
44
44
 
45
- def build(executor, crossruby)
45
+ def build(executor, crossruby, extra_mkargs = [])
46
46
  objdir = product_build_dir crossruby
47
47
  executor.mkdir_p objdir
48
48
  do_extconf executor, crossruby
@@ -54,7 +54,8 @@ module RubyWasm
54
54
  "-C",
55
55
  "#{objdir}",
56
56
  *make_args(crossruby),
57
- build_target
57
+ build_target,
58
+ *extra_mkargs
58
59
  # A ext can provide link args by link.filelist. It contains only built archive file by default.
59
60
  unless File.exist?(linklist(crossruby))
60
61
  executor.write(
@@ -70,7 +71,6 @@ module RubyWasm
70
71
  return
71
72
  end
72
73
  objdir = product_build_dir crossruby
73
- source = crossruby.source
74
74
  rbconfig_rb = Dir.glob(File.join(crossruby.dest_dir, "usr/local/lib/ruby/*/wasm32-wasi/rbconfig.rb")).first
75
75
  raise "rbconfig.rb not found" unless rbconfig_rb
76
76
  extconf_args = [
@@ -79,7 +79,7 @@ module RubyWasm
79
79
  "--target-rbconfig=#{rbconfig_rb}",
80
80
  ]
81
81
  extconf_args << "--enable-component-model" if @features.support_component_model?
82
- executor.system Gem.ruby, *extconf_args
82
+ executor.system crossruby.baseruby_path, *extconf_args
83
83
  end
84
84
 
85
85
  def do_legacy_extconf(executor, crossruby)
@@ -187,7 +187,7 @@ module RubyWasm
187
187
  def build_exts(executor)
188
188
  @user_exts.each do |prod|
189
189
  executor.begin_section prod.class, prod.name, "Building"
190
- prod.build(executor, self)
190
+ prod.build(executor, self, [])
191
191
  executor.end_section prod.class, prod.name
192
192
  end
193
193
  end
@@ -298,8 +298,7 @@ module RubyWasm
298
298
  end
299
299
 
300
300
  def extinit_c_erb
301
- lib_root = File.expand_path("../../../../..", __FILE__)
302
- File.join(lib_root, "ext", "extinit.c.erb")
301
+ File.expand_path("../crossruby/extinit.c.erb", __FILE__)
303
302
  end
304
303
 
305
304
  def baseruby_path
@@ -359,6 +358,10 @@ module RubyWasm
359
358
  args << %Q(wasmoptflags=#{@wasmoptflags.join(" ")})
360
359
  end
361
360
  args << "--disable-install-doc"
361
+ unless @params.target.pic?
362
+ # TODO: Remove this hack after dropping Ruby 3.2 support
363
+ args << "ac_cv_func_dlopen=no"
364
+ end
362
365
  args
363
366
  end
364
367
  end
@@ -4,7 +4,7 @@ module RubyWasm
4
4
 
5
5
  def initialize(
6
6
  build_dir:,
7
- revision: "v0.24.0"
7
+ revision: "67e17745a417d07852cc283d1399d210d4d659cc"
8
8
  )
9
9
  @build_dir = build_dir
10
10
  @tool_dir = File.join(@build_dir, "toolchain", "wit-bindgen-#{revision}")
@@ -56,7 +56,7 @@ module RubyWasm
56
56
  def initialize(
57
57
  wasi_sdk_path = ENV["WASI_SDK_PATH"],
58
58
  build_dir: nil,
59
- version_major: 20,
59
+ version_major: 21,
60
60
  version_minor: 0,
61
61
  binaryen_version: 108
62
62
  )
data/lib/ruby_wasm/cli.rb CHANGED
@@ -53,6 +53,8 @@ module RubyWasm
53
53
  target_triplet: "wasm32-unknown-wasip1",
54
54
  profile: "full",
55
55
  stdlib: true,
56
+ without_stdlib_components: [],
57
+ dest_dir: nil,
56
58
  disable_gems: false,
57
59
  gemfile: nil,
58
60
  patches: [],
@@ -104,10 +106,18 @@ module RubyWasm
104
106
  options[:stdlib] = stdlib
105
107
  end
106
108
 
109
+ opts.on("--without-stdlib COMPONENT", "Exclude stdlib component") do |component|
110
+ options[:without_stdlib_components] << component
111
+ end
112
+
107
113
  opts.on("--disable-gems", "Disable gems") do
108
114
  options[:disable_gems] = true
109
115
  end
110
116
 
117
+ opts.on("--dest-dir PATH", "(Experimental) Destination directory") do |path|
118
+ options[:dest_dir] = path
119
+ end
120
+
111
121
  opts.on("-p", "--patch PATCH", "Apply a patch") do |patch|
112
122
  options[:patches] << patch
113
123
  end
@@ -149,7 +159,9 @@ module RubyWasm
149
159
 
150
160
  require "tmpdir"
151
161
 
152
- if options[:save_temps]
162
+ if dest_dir = options[:dest_dir]
163
+ self.do_build(executor, dest_dir, packager, options)
164
+ elsif options[:save_temps]
153
165
  tmpdir = Dir.mktmpdir
154
166
  self.do_build(executor, tmpdir, packager, options)
155
167
  @stderr.puts "Temporary files are saved to #{tmpdir}"
@@ -204,7 +216,9 @@ module RubyWasm
204
216
  local_source = { type: "local", path: src_name }
205
217
  # @type var local_source: RubyWasm::Packager::build_source
206
218
  local_source = local_source.merge(name: "local", patches: [])
207
- return [local_source, nil]
219
+ # FIXME: We should have a way to specify extensions to be included by users.
220
+ # For now, assume all default extensions available in the head revision are available.
221
+ return [local_source, RubyWasm::Packager::ALL_DEFAULT_EXTS]
208
222
  end
209
223
  # Otherwise, it's an unknown source.
210
224
  raise(
@@ -230,7 +244,7 @@ module RubyWasm
230
244
  },
231
245
  "3.3" => {
232
246
  type: "tarball",
233
- url: "https://cache.ruby-lang.org/pub/ruby/3.3/ruby-3.3.1.tar.gz",
247
+ url: "https://cache.ruby-lang.org/pub/ruby/3.3/ruby-3.3.3.tar.gz",
234
248
  all_default_exts: "bigdecimal,cgi/escape,continuation,coverage,date,dbm,digest/bubblebabble,digest,digest/md5,digest/rmd160,digest/sha1,digest/sha2,etc,fcntl,fiber,gdbm,json,json/generator,json/parser,nkf,objspace,pathname,psych,racc/cparse,rbconfig/sizeof,ripper,stringio,strscan,monitor,zlib,openssl",
235
249
  },
236
250
  "3.2" => {
@@ -12,7 +12,7 @@ class RubyWasm::Packager::Core
12
12
 
13
13
  extend Forwardable
14
14
 
15
- def_delegators :build_strategy, :cache_key, :artifact, :build_and_link_exts
15
+ def_delegators :build_strategy, :cache_key, :artifact, :build_gem_exts, :link_gem_exts
16
16
 
17
17
  private
18
18
 
@@ -37,7 +37,11 @@ class RubyWasm::Packager::Core
37
37
  raise NotImplementedError
38
38
  end
39
39
 
40
- def build_and_link_exts(executor, module_bytes)
40
+ def build_gem_exts(executor, gem_home)
41
+ raise NotImplementedError
42
+ end
43
+
44
+ def link_gem_exts(executor, ruby_root, gem_home, module_bytes)
41
45
  raise NotImplementedError
42
46
  end
43
47
 
@@ -55,6 +59,22 @@ class RubyWasm::Packager::Core
55
59
  end
56
60
  end
57
61
 
62
+ def wasi_exec_model
63
+ # TODO: Detect WASI exec-model from binary exports (_start or _initialize)
64
+ use_js_gem = @packager.specs.any? do |spec|
65
+ spec.name == "js"
66
+ end
67
+ use_js_gem ? "reactor" : "command"
68
+ end
69
+
70
+ def with_unbundled_env(&block)
71
+ __skip__ = if defined?(Bundler)
72
+ Bundler.with_unbundled_env(&block)
73
+ else
74
+ block.call
75
+ end
76
+ end
77
+
58
78
  def cache_key(digest)
59
79
  raise NotImplementedError
60
80
  end
@@ -75,38 +95,37 @@ class RubyWasm::Packager::Core
75
95
  end
76
96
  build.crossruby.clean(executor) if options[:clean]
77
97
 
78
- do_build =
79
- proc do
80
- build.crossruby.build(
81
- executor,
82
- remake: options[:remake],
83
- reconfigure: options[:reconfigure]
84
- )
85
- end
98
+ self.with_unbundled_env do
99
+ build.crossruby.build(
100
+ executor,
101
+ remake: options[:remake],
102
+ reconfigure: options[:reconfigure]
103
+ )
104
+ end
86
105
 
87
- __skip__ =
88
- if defined?(Bundler)
89
- Bundler.with_unbundled_env(&do_build)
90
- else
91
- do_build.call
92
- end
93
106
  build.crossruby.artifact
94
107
  end
95
108
 
96
- def build_and_link_exts(executor, module_bytes)
109
+ def build_gem_exts(executor, gem_home)
97
110
  build = derive_build
98
- self.build_exts(executor, build)
99
- self.link_exts(executor, build)
111
+ self.with_unbundled_env do
112
+ self._build_gem_exts(executor, build, gem_home)
113
+ end
100
114
  end
101
115
 
102
- def link_exts(executor, build)
103
- ruby_root = build.crossruby.dest_dir
116
+ def link_gem_exts(executor, ruby_root, gem_home, module_bytes)
117
+ build = derive_build
118
+ self._link_gem_exts(executor, build, ruby_root, gem_home, module_bytes)
119
+ end
104
120
 
105
- libraries = [File.join(ruby_root, "usr", "local", "bin", "ruby")]
121
+ def _link_gem_exts(executor, build, ruby_root, gem_home, module_bytes)
122
+ libraries = []
106
123
 
107
124
  # TODO: Should be computed from dyinfo of ruby binary
108
125
  wasi_libc_shared_libs = [
109
126
  "libc.so",
127
+ "libc++.so",
128
+ "libc++abi.so",
110
129
  "libwasi-emulated-getpid.so",
111
130
  "libwasi-emulated-mman.so",
112
131
  "libwasi-emulated-process-clocks.so",
@@ -119,13 +138,18 @@ class RubyWasm::Packager::Core
119
138
  wasi_sdk_path = toolchain.wasi_sdk_path
120
139
  libraries << File.join(wasi_sdk_path, "share/wasi-sysroot/lib/wasm32-wasi", lib)
121
140
  end
122
- wasi_adapter = RubyWasm::Packager::ComponentAdapter.wasi_snapshot_preview1("command")
141
+ wasi_adapter = RubyWasm::Packager::ComponentAdapter.wasi_snapshot_preview1(wasi_exec_model)
123
142
  adapters = [wasi_adapter]
124
- dl_openable_libs = Dir.glob(File.join(ruby_root, "usr", "local", "lib", "ruby", "**", "*.so"))
143
+ dl_openable_libs = []
144
+ dl_openable_libs << [File.dirname(ruby_root), Dir.glob(File.join(ruby_root, "lib", "ruby", "**", "*.so"))]
145
+ dl_openable_libs << [gem_home, Dir.glob(File.join(gem_home, "**", "*.so"))]
146
+
125
147
  linker = RubyWasmExt::ComponentLink.new
126
148
  linker.use_built_in_libdl(true)
127
149
  linker.stub_missing_functions(false)
128
- linker.validate(true)
150
+ linker.validate(ENV["RUBYWASM_SKIP_LINKER_VALIDATION"] != "1")
151
+
152
+ linker.library("ruby", module_bytes, false)
129
153
 
130
154
  libraries.each do |lib|
131
155
  # Non-DL openable libraries should be referenced as base name
@@ -135,12 +159,14 @@ class RubyWasm::Packager::Core
135
159
  linker.library(lib_name, module_bytes, false)
136
160
  end
137
161
 
138
- dl_openable_libs.each do |lib|
139
- # DL openable lib_name should be a relative path from ruby_root
140
- lib_name = "/" + Pathname.new(lib).relative_path_from(Pathname.new(ruby_root)).to_s
141
- module_bytes = File.binread(lib)
142
- RubyWasm.logger.info "Linking #{lib_name} (#{module_bytes.size} bytes)"
143
- linker.library(lib_name, module_bytes, true)
162
+ dl_openable_libs.each do |root, libs|
163
+ libs.each do |lib|
164
+ # DL openable lib_name should be a relative path from ruby_root
165
+ lib_name = "/" + Pathname.new(lib).relative_path_from(Pathname.new(File.dirname(root))).to_s
166
+ module_bytes = File.binread(lib)
167
+ RubyWasm.logger.info "Linking #{lib_name} (#{module_bytes.size} bytes)"
168
+ linker.library(lib_name, module_bytes, true)
169
+ end
144
170
  end
145
171
 
146
172
  adapters.each do |adapter|
@@ -148,29 +174,42 @@ class RubyWasm::Packager::Core
148
174
  # e.g. wasi_snapshot_preview1.command.wasm -> wasi_snapshot_preview1
149
175
  adapter_name = adapter_name.split(".")[0]
150
176
  module_bytes = File.binread(adapter)
177
+ RubyWasm.logger.info "Linking adapter #{adapter_name}=#{adapter} (#{module_bytes.size} bytes)"
151
178
  linker.adapter(adapter_name, module_bytes)
152
179
  end
153
180
  return linker.encode()
154
181
  end
155
182
 
156
- def build_exts(executor, build)
183
+ def _build_gem_exts(executor, build, gem_home)
184
+ build.toolchain.install
185
+ baseruby = build.baseruby
186
+ unless Dir.exist?(baseruby.install_dir)
187
+ baseruby.build(executor)
188
+ end
189
+
157
190
  exts = specs_with_extensions.flat_map do |spec, exts|
158
191
  exts.map do |ext|
159
192
  ext_feature = File.dirname(ext) # e.g. "ext/cgi/escape"
160
193
  ext_srcdir = File.join(spec.full_gem_path, ext_feature)
161
194
  ext_relative_path = File.join(spec.full_name, ext_feature)
162
- RubyWasm::CrossRubyExtProduct.new(
195
+ prod = RubyWasm::CrossRubyExtProduct.new(
163
196
  ext_srcdir,
164
197
  build.toolchain,
165
198
  features: @packager.features,
166
199
  ext_relative_path: ext_relative_path
167
200
  )
201
+ [prod, spec]
168
202
  end
169
203
  end
170
204
 
171
- exts.each do |prod|
205
+ exts.each do |prod, spec|
206
+ libdir = File.join(gem_home, "gems", spec.full_name, spec.raw_require_paths.first)
207
+ extra_mkargs = [
208
+ "sitearchdir=#{libdir}",
209
+ "sitelibdir=#{libdir}",
210
+ ]
172
211
  executor.begin_section prod.class, prod.name, "Building"
173
- prod.build(executor, build.crossruby)
212
+ prod.build(executor, build.crossruby, extra_mkargs)
174
213
  executor.end_section prod.class, prod.name
175
214
  end
176
215
  end
@@ -239,21 +278,14 @@ class RubyWasm::Packager::Core
239
278
  end
240
279
  build.crossruby.clean(executor) if options[:clean]
241
280
 
242
- do_build =
243
- proc do
244
- build.crossruby.build(
245
- executor,
246
- remake: options[:remake],
247
- reconfigure: options[:reconfigure]
248
- )
249
- end
281
+ self.with_unbundled_env do
282
+ build.crossruby.build(
283
+ executor,
284
+ remake: options[:remake],
285
+ reconfigure: options[:reconfigure]
286
+ )
287
+ end
250
288
 
251
- __skip__ =
252
- if defined?(Bundler)
253
- Bundler.with_unbundled_env(&do_build)
254
- else
255
- do_build.call
256
- end
257
289
  build.crossruby.artifact
258
290
  end
259
291
 
@@ -301,15 +333,19 @@ class RubyWasm::Packager::Core
301
333
  build
302
334
  end
303
335
 
304
- def build_and_link_exts(executor, module_bytes)
336
+ def build_gem_exts(executor, gem_home)
337
+ # No-op because we already built extensions as part of the Ruby build
338
+ end
339
+
340
+ def link_gem_exts(executor, ruby_root, gem_home, module_bytes)
305
341
  return module_bytes unless @packager.features.support_component_model?
306
342
 
307
343
  linker = RubyWasmExt::ComponentEncode.new
308
- linker.validate(true)
344
+ linker.validate(ENV["RUBYWASM_SKIP_LINKER_VALIDATION"] != "1")
309
345
  linker.module(module_bytes)
310
346
  linker.adapter(
311
347
  "wasi_snapshot_preview1",
312
- File.binread(RubyWasm::Packager::ComponentAdapter.wasi_snapshot_preview1("reactor"))
348
+ File.binread(RubyWasm::Packager::ComponentAdapter.wasi_snapshot_preview1(wasi_exec_model))
313
349
  )
314
350
 
315
351
  linker.encode()
@@ -38,6 +38,23 @@ class RubyWasm::Packager::FileSystem
38
38
  File.write(rbconfig, rbconfig_contents)
39
39
  end
40
40
 
41
+ def remove_stdlib_component(executor, component)
42
+ RubyWasm.logger.info "Removing stdlib component: #{component}"
43
+ case component
44
+ when "enc"
45
+ # Remove all encodings except for encdb.so and transdb.so
46
+ enc_dir = File.join(@ruby_root, "lib", "ruby", ruby_version, "wasm32-wasi", "enc")
47
+ puts File.join(enc_dir, "**/*.so")
48
+ Dir.glob(File.join(enc_dir, "**/*.so")).each do |entry|
49
+ next if entry.end_with?("encdb.so", "transdb.so")
50
+ RubyWasm.logger.debug "Removing stdlib encoding: #{entry}"
51
+ executor.rm_rf entry
52
+ end
53
+ else
54
+ raise "Unknown stdlib component: #{component}"
55
+ end
56
+ end
57
+
41
58
  def package_gems
42
59
  @packager.specs.each do |spec|
43
60
  RubyWasm.logger.info "Packaging gem: #{spec.full_name}"
@@ -32,11 +32,19 @@ class RubyWasm::Packager
32
32
 
33
33
  wasm_bytes = File.binread(File.join(fs.ruby_root, "bin", "ruby"))
34
34
 
35
+ ruby_core.build_gem_exts(executor, fs.bundle_dir)
36
+
35
37
  fs.package_gems
36
38
  fs.remove_non_runtime_files(executor)
37
- fs.remove_stdlib(executor) unless options[:stdlib]
39
+ if options[:stdlib]
40
+ options[:without_stdlib_components].each do |component|
41
+ fs.remove_stdlib_component(executor, component)
42
+ end
43
+ else
44
+ fs.remove_stdlib(executor)
45
+ end
38
46
 
39
- if full_build_options[:target] == "wasm32-unknown-wasip1"
47
+ if full_build_options[:target] == "wasm32-unknown-wasip1" && !features.support_component_model?
40
48
  # wasi-vfs supports only WASI target
41
49
  wasi_vfs = RubyWasmExt::WasiVfs.new
42
50
  wasi_vfs.map_dir("/bundle", fs.bundle_dir)
@@ -44,7 +52,21 @@ class RubyWasm::Packager
44
52
 
45
53
  wasm_bytes = wasi_vfs.pack(wasm_bytes)
46
54
  end
47
- wasm_bytes = ruby_core.build_and_link_exts(executor, wasm_bytes)
55
+ wasm_bytes = ruby_core.link_gem_exts(executor, fs.ruby_root, fs.bundle_dir, wasm_bytes)
56
+
57
+ if features.support_component_model?
58
+ wasi_virt = RubyWasmExt::WasiVirt.new
59
+ wasi_virt.allow_all
60
+ [
61
+ { guest: "/bundle", host: fs.bundle_dir },
62
+ { guest: "/usr", host: File.dirname(fs.ruby_root) }
63
+ ].each do |map|
64
+ map => { guest:, host: }
65
+ RubyWasm.logger.debug "Adding files into VFS: #{host} => #{guest}"
66
+ wasi_virt.map_dir(guest, host)
67
+ end
68
+ wasm_bytes = wasi_virt.compose(wasm_bytes)
69
+ end
48
70
 
49
71
  wasm_bytes = RubyWasmExt.preinitialize(wasm_bytes) if options[:optimize]
50
72
  wasm_bytes
@@ -60,8 +82,9 @@ class RubyWasm::Packager
60
82
  # Retrieves the specs from the Bundler definition, excluding the excluded gems.
61
83
  def specs
62
84
  return [] unless @definition
63
- @specs ||= @definition.resolve.materialize(@definition.requested_dependencies)
85
+ __skip__ = @specs ||= @definition.resolve.materialize(@definition.requested_dependencies)
64
86
  .reject { |spec| EXCLUDED_GEMS.include?(spec.name) }
87
+ .reject { |spec| spec.is_a?(Bundler::LazySpecification) }
65
88
  @specs
66
89
  end
67
90
 
@@ -1,3 +1,3 @@
1
1
  module RubyWasm
2
- VERSION = "2.6.0"
2
+ VERSION = "2.6.2"
3
3
  end