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

Sign up to get free protection for your applications and to get access to all the features.
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