ruby_wasm 2.6.1-x64-mingw-ucrt → 2.7.0-x64-mingw-ucrt

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: 0f9b2c837ea042dee0e1fcf8814f62d4c30108301b2e782e2b2e64c22d80366e
4
- data.tar.gz: 1d5d571f3a57fde8a93fe53548940fb5a930987d6636228fde258d7468c8c523
3
+ metadata.gz: 3f7a53b259e7b889e820ee28d22c074c2105295fe62323153e9d20af3de06cb1
4
+ data.tar.gz: eb1720fbdc33532afeb3a3213ccdd52e5a86e41e77031cb777c08189e8b55313
5
5
  SHA512:
6
- metadata.gz: feb32517717643d51548d6a26cccb2c5876916d8d5d09baa52b6e814a984a617859e34c1a88bc3fef931307cd48f8f124a29e663b3569c63c1ab487d81fa8d8d
7
- data.tar.gz: 2669e861a9777e0ea73576da0e9456c6aed051f793bea63141b34e7a606c872ebc8a900d00737d47a1766320f4d99e18e4ab824f21e7dac6be79cbee5196cf49
6
+ metadata.gz: bf55294e3ee5cba57ae9de0b2a34990fe3665c2dea40618abfa5a57e9a0d00f4b1fb625a15917073bf33f2a370d9c7f1b1d4a01defc2ceb6a18509fbff55eb6b
7
+ data.tar.gz: 31dbeb7f455c996e96c4d2e3757e755c92457e1863b9c2cd6bdb80068f288150e1249692be591a2ce6f3c7861c1f91eb4c12549c6a125c4e0bfe2c10c587a8e1
data/CONTRIBUTING.md CHANGED
@@ -9,8 +9,6 @@ This document describes development setup and pointers for diving into this proj
9
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
14
12
  # Compile extension library
15
13
  $ bundle exec rake compile
16
14
  $ rake --tasks
@@ -26,9 +24,9 @@ $ rake build:download_prebuilt
26
24
  $ rake build:head-wasm32-unknown-wasip1-full
27
25
 
28
26
  # Build npm package
29
- $ rake npm:ruby-head-wasm-wasi
27
+ $ rake npm:ruby-head-wasm-wasip2:build
30
28
  # Test npm package
31
- $ rake npm:ruby-head-wasm-wasi:check
29
+ $ rake npm:ruby-head-wasm-wasip2:check
32
30
  ```
33
31
 
34
32
  If you need to re-build Ruby, please clean `./rubies` directory, and run `rake npm:ruby-head-wasm-wasi` again.
@@ -111,9 +109,13 @@ $ rake 'bump_version[0.6.0]'
111
109
  $ git commit -m"Bump version to 0.6.0"
112
110
  $ git tag 0.6.0
113
111
  $ git push origin 0.6.0
114
- $ for pkg in pkg/ruby_wasm-*; do gem push $pkg; done
112
+ # After GitHub Actions "Build gems" is done
113
+ # https://github.com/ruby/ruby.wasm/actions/workflows/build-gems.yml
114
+ $ gh run download <run-id>
115
+ $ for pkg in cross-gem/pkg/ruby_wasm-*; do gem push $pkg; done
115
116
  $ gem build && gem push ruby_wasm-*.gem && rm ruby_wasm-*.gem
116
117
  $ (cd packages/gems/js/ && gem build && gem push js-*.gem && rm js-*.gem)
118
+ $ rake bump_dev_version
117
119
  ```
118
120
 
119
121
  ## Release Channels
@@ -127,5 +129,5 @@ $ npm install --save @ruby/wasm-wasi@latest
127
129
  # or if you want the nightly snapshot
128
130
  $ npm install --save @ruby/wasm-wasi@next
129
131
  # or you can specify the exact snapshot version
130
- $ npm install --save @ruby/wasm-wasi@2.6.1-2024-05-22-a
132
+ $ npm install --save @ruby/wasm-wasi@2.7.0-2024-11-11-a
131
133
  ```
data/Gemfile CHANGED
@@ -11,7 +11,8 @@ group :development do
11
11
  end
12
12
 
13
13
  group :check do
14
- gem "webrick"
14
+ # Use the latest version of webrick for URI change in Ruby 3.4
15
+ gem "webrick", "~> 1.8.2"
15
16
  gem "syntax_tree", "~> 3.5"
16
17
  gem "steep"
17
18
  end
data/NOTICE CHANGED
@@ -1264,8 +1264,7 @@ Licensed under the Apache License 2.0 https://www.openssl.org/source/license.htm
1264
1264
  https://github.com/kateinoigakukun/wasi-vfs
1265
1265
 
1266
1266
  ```
1267
- Copyright (c) 2022 Yuta Saito. All rights reserved.
1268
- Licensed under the MIT License
1267
+ Licensed under the Apache License v2.0 with LLVM Exceptions
1269
1268
  ```
1270
1269
 
1271
1270
  ---
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.1/dist/browser.script.iife.js"></script>
26
+ <script src="https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.7.0/dist/browser.script.iife.js"></script>
27
27
  <script type="text/ruby">
28
28
  require "js"
29
29
 
data/Rakefile CHANGED
@@ -28,20 +28,26 @@ NPM_PACKAGES = [
28
28
  {
29
29
  name: "ruby-head-wasm-wasi",
30
30
  ruby_version: "head",
31
- gemfile: "packages/npm-packages/ruby-wasm-wasi/Gemfile",
31
+ gemfile: "packages/npm-packages/ruby-head-wasm-wasi/Gemfile",
32
32
  target: "wasm32-unknown-wasip1",
33
+ },
34
+ {
35
+ name: "ruby-head-wasm-wasip2",
36
+ ruby_version: "head",
37
+ gemfile: "packages/npm-packages/ruby-head-wasm-wasip2/Gemfile",
38
+ target: "wasm32-unknown-wasip2",
33
39
  enable_component_model: true,
34
40
  },
35
41
  {
36
42
  name: "ruby-3.3-wasm-wasi",
37
43
  ruby_version: "3.3",
38
- gemfile: "packages/npm-packages/ruby-wasm-wasi/Gemfile",
44
+ gemfile: "packages/npm-packages/ruby-3.3-wasm-wasi/Gemfile",
39
45
  target: "wasm32-unknown-wasip1"
40
46
  },
41
47
  {
42
48
  name: "ruby-3.2-wasm-wasi",
43
49
  ruby_version: "3.2",
44
- gemfile: "packages/npm-packages/ruby-wasm-wasi/Gemfile",
50
+ gemfile: "packages/npm-packages/ruby-3.2-wasm-wasi/Gemfile",
45
51
  target: "wasm32-unknown-wasip1"
46
52
  },
47
53
  { name: "ruby-wasm-wasi", target: "wasm32-unknown-wasip1" }
@@ -68,10 +74,11 @@ class BuildTask < Struct.new(:name, :target, :build_command)
68
74
  def ruby_cache_key
69
75
  return @key if @key
70
76
  require "open3"
77
+ env = { "RUBY_WASM_ROOT" => LIB_ROOT }
71
78
  cmd = build_command + ["--print-ruby-cache-key"]
72
- stdout, status = Open3.capture2(*cmd)
79
+ stdout, status = Open3.capture2(env, *cmd)
73
80
  unless status.success?
74
- raise "Command failed with status (#{status.exitstatus}): #{cmd.join ""}"
81
+ raise "Command failed with status (#{status.exitstatus}): #{cmd.join " "}"
75
82
  end
76
83
  require "json"
77
84
  @key = JSON.parse(stdout)
data/docs/api.md CHANGED
@@ -1,2 +1,2 @@
1
1
  - [Ruby API](https://ruby.github.io/ruby.wasm/JS.html)
2
- - [JavaScript API](https://github.com/ruby/ruby.wasm/blob/main/packages/npm-packages/ruby-wasm-wasi/README.md#API)
2
+ - [JavaScript API](https://ruby.github.io/ruby.wasm/npm/@ruby/wasm-wasi/)
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.1/dist/browser.script.iife.js"></script>
41
+ <script src="https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.7.0/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.1/dist/browser/+esm";
55
- const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.6.1/dist/ruby+stdlib.wasm");
54
+ import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.7.0/dist/browser/+esm";
55
+ const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.7.0/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.1/dist/browser.umd.js"></script>
72
+ <script src="https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.7.0/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.1/dist/ruby+stdlib.wasm");
76
+ const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.7.0/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.1/dist/browser.script.iife.js"></script>
131
+ <script src="https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.7.0/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.1/dist/browser/+esm";
147
- const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.6.1/dist/ruby+stdlib.wasm");
146
+ import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.7.0/dist/browser/+esm";
147
+ const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.7.0/dist/ruby+stdlib.wasm");
148
148
  const module = await WebAssembly.compileStreaming(response);
149
149
  const { vm } = await DefaultRubyVM(module);
150
150
 
Binary file
Binary file
Binary file
@@ -71,16 +71,15 @@ module RubyWasm
71
71
  return
72
72
  end
73
73
  objdir = product_build_dir crossruby
74
- source = crossruby.source
75
- rbconfig_rb = Dir.glob(File.join(crossruby.dest_dir, "usr/local/lib/ruby/*/wasm32-wasi/rbconfig.rb")).first
74
+ rbconfig_rb = crossruby.rbconfig_rb
76
75
  raise "rbconfig.rb not found" unless rbconfig_rb
77
76
  extconf_args = [
78
77
  "-C", objdir,
79
78
  "#{@srcdir}/extconf.rb",
80
79
  "--target-rbconfig=#{rbconfig_rb}",
81
80
  ]
82
- extconf_args << "--enable-component-model" if @features.support_component_model?
83
- executor.system Gem.ruby, *extconf_args
81
+ extconf_args << "--disable-component-model" unless @features.support_component_model?
82
+ executor.system crossruby.baseruby_path, *extconf_args
84
83
  end
85
84
 
86
85
  def do_legacy_extconf(executor, crossruby)
@@ -112,7 +111,7 @@ module RubyWasm
112
111
  "-I#{crossruby.build_dir}",
113
112
  "--",
114
113
  ]
115
- extconf_args << "--enable-component-model" if @features.support_component_model?
114
+ extconf_args << "--disable-component-model" unless @features.support_component_model?
116
115
  # Clear RUBYOPT to avoid loading unrelated bundle setup
117
116
  executor.system crossruby.baseruby_path,
118
117
  *extconf_args,
@@ -223,6 +222,10 @@ module RubyWasm
223
222
  end
224
223
  install_dir = File.join(build_dir, "install")
225
224
  if !File.exist?(install_dir) || remake || reconfigure
225
+ unless target.pic?
226
+ # HACK: force static linking for non-pic target
227
+ executor.rm_f File.join(build_dir, "ruby")
228
+ end
226
229
  executor.system "make",
227
230
  "-j#{executor.process_count}",
228
231
  "install",
@@ -302,6 +305,10 @@ module RubyWasm
302
305
  File.expand_path("../crossruby/extinit.c.erb", __FILE__)
303
306
  end
304
307
 
308
+ def rbconfig_rb
309
+ Dir.glob(File.join(dest_dir, "usr/local/lib/ruby/*/wasm32-wasi/rbconfig.rb")).first
310
+ end
311
+
305
312
  def baseruby_path
306
313
  File.join(@baseruby.install_dir, "bin/ruby")
307
314
  end
@@ -359,6 +366,10 @@ module RubyWasm
359
366
  args << %Q(wasmoptflags=#{@wasmoptflags.join(" ")})
360
367
  end
361
368
  args << "--disable-install-doc"
369
+ unless @params.target.pic?
370
+ # TODO: Remove this hack after dropping Ruby 3.2 support
371
+ args << "ac_cv_func_dlopen=no"
372
+ end
362
373
  args
363
374
  end
364
375
  end
@@ -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
@@ -216,7 +216,9 @@ module RubyWasm
216
216
  local_source = { type: "local", path: src_name }
217
217
  # @type var local_source: RubyWasm::Packager::build_source
218
218
  local_source = local_source.merge(name: "local", patches: [])
219
- 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]
220
222
  end
221
223
  # Otherwise, it's an unknown source.
222
224
  raise(
@@ -242,7 +244,7 @@ module RubyWasm
242
244
  },
243
245
  "3.3" => {
244
246
  type: "tarball",
245
- 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",
246
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",
247
249
  },
248
250
  "3.2" => {
@@ -308,7 +310,10 @@ module RubyWasm
308
310
 
309
311
  def derive_packager(options)
310
312
  __skip__ = definition = nil
311
- __skip__ = if defined?(Bundler) && !options[:disable_gems]
313
+ features = RubyWasm::FeatureSet.derive_from_env
314
+ # The head ruby & dynamic linking uses "bundle" command to build gems instead of in-process integration.
315
+ use_in_process_gem_building = !(options[:ruby_version] == "head" && features.support_dynamic_linking?)
316
+ __skip__ = if defined?(Bundler) && !options[:disable_gems] && use_in_process_gem_building
312
317
  begin
313
318
  # Silence Bundler UI if --print-ruby-cache-key is specified not to bother the JSON output.
314
319
  level = options[:print_ruby_cache_key] ? :silent : Bundler.ui.level
@@ -319,10 +324,10 @@ module RubyWasm
319
324
  Bundler.ui.level = old_level
320
325
  end
321
326
  end
322
- RubyWasm.logger.info "Using Gemfile: #{definition.gemfiles}" if definition
327
+ RubyWasm.logger.info "Using Gemfile: #{definition.gemfiles.map(&:to_s).join(", ")}" if definition
323
328
  RubyWasm::Packager.new(
324
329
  root, build_config(options), definition,
325
- features: RubyWasm::FeatureSet.derive_from_env
330
+ features: features,
326
331
  )
327
332
  end
328
333
 
@@ -330,6 +335,9 @@ module RubyWasm
330
335
  ruby_core_build = packager.ruby_core_build
331
336
  require "digest"
332
337
  digest = Digest::SHA256.new
338
+ # The build system key is used to invalidate the cache when the build system is updated.
339
+ build_system_key = 1
340
+ digest.update(build_system_key.to_s)
333
341
  ruby_core_build.cache_key(digest)
334
342
  hexdigest = digest.hexdigest
335
343
  require "json"
@@ -1,4 +1,5 @@
1
1
  require "forwardable"
2
+ require "pathname"
2
3
 
3
4
  class RubyWasm::Packager::Core
4
5
  def initialize(packager)
@@ -19,7 +20,6 @@ class RubyWasm::Packager::Core
19
20
  def build_strategy
20
21
  @build_strategy ||=
21
22
  begin
22
- has_exts = @packager.specs.any? { |spec| spec.extensions.any? }
23
23
  if @packager.features.support_dynamic_linking?
24
24
  DynamicLinking.new(@packager)
25
25
  else
@@ -59,12 +59,12 @@ class RubyWasm::Packager::Core
59
59
  end
60
60
  end
61
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"
62
+ def with_unbundled_env(&block)
63
+ __skip__ = if defined?(Bundler)
64
+ Bundler.with_unbundled_env(&block)
65
+ else
66
+ block.call
66
67
  end
67
- use_js_gem ? "reactor" : "command"
68
68
  end
69
69
 
70
70
  def cache_key(digest)
@@ -87,27 +87,22 @@ class RubyWasm::Packager::Core
87
87
  end
88
88
  build.crossruby.clean(executor) if options[:clean]
89
89
 
90
- do_build =
91
- proc do
92
- build.crossruby.build(
93
- executor,
94
- remake: options[:remake],
95
- reconfigure: options[:reconfigure]
96
- )
97
- end
90
+ self.with_unbundled_env do
91
+ build.crossruby.build(
92
+ executor,
93
+ remake: options[:remake],
94
+ reconfigure: options[:reconfigure]
95
+ )
96
+ end
98
97
 
99
- __skip__ =
100
- if defined?(Bundler)
101
- Bundler.with_unbundled_env(&do_build)
102
- else
103
- do_build.call
104
- end
105
98
  build.crossruby.artifact
106
99
  end
107
100
 
108
101
  def build_gem_exts(executor, gem_home)
109
102
  build = derive_build
110
- self._build_gem_exts(executor, build, gem_home)
103
+ self.with_unbundled_env do
104
+ self._build_gem_exts(executor, build, gem_home)
105
+ end
111
106
  end
112
107
 
113
108
  def link_gem_exts(executor, ruby_root, gem_home, module_bytes)
@@ -135,12 +130,16 @@ class RubyWasm::Packager::Core
135
130
  wasi_sdk_path = toolchain.wasi_sdk_path
136
131
  libraries << File.join(wasi_sdk_path, "share/wasi-sysroot/lib/wasm32-wasi", lib)
137
132
  end
138
- wasi_adapter = RubyWasm::Packager::ComponentAdapter.wasi_snapshot_preview1(wasi_exec_model)
139
- adapters = [wasi_adapter]
140
133
  dl_openable_libs = []
141
134
  dl_openable_libs << [File.dirname(ruby_root), Dir.glob(File.join(ruby_root, "lib", "ruby", "**", "*.so"))]
142
135
  dl_openable_libs << [gem_home, Dir.glob(File.join(gem_home, "**", "*.so"))]
143
136
 
137
+ has_js_so = dl_openable_libs.any? do |root, libs|
138
+ libs.any? { |lib| lib.end_with?("/js.so") }
139
+ end
140
+ wasi_adapter = RubyWasm::Packager::ComponentAdapter.wasi_snapshot_preview1(has_js_so ? "reactor" : "command")
141
+ adapters = [wasi_adapter]
142
+
144
143
  linker = RubyWasmExt::ComponentLink.new
145
144
  linker.use_built_in_libdl(true)
146
145
  linker.stub_missing_functions(false)
@@ -148,11 +147,13 @@ class RubyWasm::Packager::Core
148
147
 
149
148
  linker.library("ruby", module_bytes, false)
150
149
 
150
+ RubyWasm.logger.info "Linking Ruby with extensions"
151
+
151
152
  libraries.each do |lib|
152
153
  # Non-DL openable libraries should be referenced as base name
153
154
  lib_name = File.basename(lib)
154
155
  module_bytes = File.binread(lib)
155
- RubyWasm.logger.info "Linking #{lib_name} (#{module_bytes.size} bytes)"
156
+ RubyWasm.logger.debug "Linking #{lib_name} (#{module_bytes.size} bytes)"
156
157
  linker.library(lib_name, module_bytes, false)
157
158
  end
158
159
 
@@ -161,7 +162,7 @@ class RubyWasm::Packager::Core
161
162
  # DL openable lib_name should be a relative path from ruby_root
162
163
  lib_name = "/" + Pathname.new(lib).relative_path_from(Pathname.new(File.dirname(root))).to_s
163
164
  module_bytes = File.binread(lib)
164
- RubyWasm.logger.info "Linking #{lib_name} (#{module_bytes.size} bytes)"
165
+ RubyWasm.logger.debug "Linking #{lib_name} (#{module_bytes.size} bytes)"
165
166
  linker.library(lib_name, module_bytes, true)
166
167
  end
167
168
  end
@@ -171,38 +172,56 @@ class RubyWasm::Packager::Core
171
172
  # e.g. wasi_snapshot_preview1.command.wasm -> wasi_snapshot_preview1
172
173
  adapter_name = adapter_name.split(".")[0]
173
174
  module_bytes = File.binread(adapter)
174
- RubyWasm.logger.info "Linking adapter #{adapter_name}=#{adapter} (#{module_bytes.size} bytes)"
175
+ RubyWasm.logger.debug "Linking adapter #{adapter_name}=#{adapter} (#{module_bytes.size} bytes)"
175
176
  linker.adapter(adapter_name, module_bytes)
176
177
  end
177
178
  return linker.encode()
178
179
  end
179
180
 
180
181
  def _build_gem_exts(executor, build, gem_home)
181
- exts = specs_with_extensions.flat_map do |spec, exts|
182
- exts.map do |ext|
183
- ext_feature = File.dirname(ext) # e.g. "ext/cgi/escape"
184
- ext_srcdir = File.join(spec.full_gem_path, ext_feature)
185
- ext_relative_path = File.join(spec.full_name, ext_feature)
186
- prod = RubyWasm::CrossRubyExtProduct.new(
187
- ext_srcdir,
188
- build.toolchain,
189
- features: @packager.features,
190
- ext_relative_path: ext_relative_path
191
- )
192
- [prod, spec]
193
- end
182
+ build.toolchain.install
183
+ baseruby = build.baseruby
184
+ unless Dir.exist?(baseruby.install_dir)
185
+ baseruby.build(executor)
194
186
  end
195
187
 
196
- exts.each do |prod, spec|
197
- libdir = File.join(gem_home, "gems", spec.full_name, spec.raw_require_paths.first)
198
- extra_mkargs = [
199
- "sitearchdir=#{libdir}",
200
- "sitelibdir=#{libdir}",
201
- ]
202
- executor.begin_section prod.class, prod.name, "Building"
203
- prod.build(executor, build.crossruby, extra_mkargs)
204
- executor.end_section prod.class, prod.name
205
- end
188
+ crossruby = build.crossruby
189
+ rbconfig_rb = crossruby.rbconfig_rb
190
+
191
+ options = @packager.full_build_options
192
+ target_triplet = options[:target]
193
+
194
+ local_path = File.join("bundle", target_triplet)
195
+ env = {
196
+ "BUNDLE_APP_CONFIG" => File.join(".bundle", target_triplet),
197
+ "BUNDLE_PATH" => local_path,
198
+ "BUNDLE_WITHOUT" => "build",
199
+ # Do not auto-switch bundler version by Gemfile.lock
200
+ "BUNDLE_VERSION" => "system",
201
+ # FIXME: BUNDLE_PATH is set as a installation destination here, but
202
+ # it is also used as a source of gems to be loaded by RubyGems itself.
203
+ # RubyGems loads "psych" gem and if Gemfile includes "psych" gem,
204
+ # RubyGems tries to load "psych" gem from BUNDLE_PATH at the second
205
+ # time of "bundle install" command. But the extension of "psych" gem
206
+ # under BUNDLE_PATH is built for Wasm target, not for host platform,
207
+ # so it fails to load the extension.
208
+ #
209
+ # Thus we preload psych from the default LOAD_PATH here to avoid
210
+ # loading Wasm version of psych.so via `Kernel#require` patched by
211
+ # RubyGems.
212
+ "RUBYOPT" => "-rpsych",
213
+ }
214
+
215
+ args = [
216
+ File.join(baseruby.install_dir, "bin", "bundle"),
217
+ "install",
218
+ "--standalone",
219
+ "--target-rbconfig",
220
+ rbconfig_rb,
221
+ ]
222
+
223
+ executor.system(*args, env: env)
224
+ executor.cp_r(local_path, gem_home)
206
225
  end
207
226
 
208
227
  def cache_key(digest)
@@ -269,21 +288,14 @@ class RubyWasm::Packager::Core
269
288
  end
270
289
  build.crossruby.clean(executor) if options[:clean]
271
290
 
272
- do_build =
273
- proc do
274
- build.crossruby.build(
275
- executor,
276
- remake: options[:remake],
277
- reconfigure: options[:reconfigure]
278
- )
279
- end
291
+ self.with_unbundled_env do
292
+ build.crossruby.build(
293
+ executor,
294
+ remake: options[:remake],
295
+ reconfigure: options[:reconfigure]
296
+ )
297
+ end
280
298
 
281
- __skip__ =
282
- if defined?(Bundler)
283
- Bundler.with_unbundled_env(&do_build)
284
- else
285
- do_build.call
286
- end
287
299
  build.crossruby.artifact
288
300
  end
289
301
 
@@ -335,6 +347,14 @@ class RubyWasm::Packager::Core
335
347
  # No-op because we already built extensions as part of the Ruby build
336
348
  end
337
349
 
350
+ def wasi_exec_model
351
+ # TODO: Detect WASI exec-model from binary exports (_start or _initialize)
352
+ use_js_gem = @packager.specs.any? do |spec|
353
+ spec.name == "js"
354
+ end
355
+ use_js_gem ? "reactor" : "command"
356
+ end
357
+
338
358
  def link_gem_exts(executor, ruby_root, gem_home, module_bytes)
339
359
  return module_bytes unless @packager.features.support_component_model?
340
360
 
@@ -44,7 +44,6 @@ class RubyWasm::Packager::FileSystem
44
44
  when "enc"
45
45
  # Remove all encodings except for encdb.so and transdb.so
46
46
  enc_dir = File.join(@ruby_root, "lib", "ruby", ruby_version, "wasm32-wasi", "enc")
47
- puts File.join(enc_dir, "**/*.so")
48
47
  Dir.glob(File.join(enc_dir, "**/*.so")).each do |entry|
49
48
  next if entry.end_with?("encdb.so", "transdb.so")
50
49
  RubyWasm.logger.debug "Removing stdlib encoding: #{entry}"
@@ -34,7 +34,7 @@ class RubyWasm::Packager
34
34
 
35
35
  ruby_core.build_gem_exts(executor, fs.bundle_dir)
36
36
 
37
- fs.package_gems
37
+ fs.package_gems unless features.support_component_model?
38
38
  fs.remove_non_runtime_files(executor)
39
39
  if options[:stdlib]
40
40
  options[:without_stdlib_components].each do |component|
@@ -44,7 +44,7 @@ class RubyWasm::Packager
44
44
  fs.remove_stdlib(executor)
45
45
  end
46
46
 
47
- if full_build_options[:target] == "wasm32-unknown-wasip1" && !features.support_dynamic_linking?
47
+ if full_build_options[:target] == "wasm32-unknown-wasip1" && !features.support_component_model?
48
48
  # wasi-vfs supports only WASI target
49
49
  wasi_vfs = RubyWasmExt::WasiVfs.new
50
50
  wasi_vfs.map_dir("/bundle", fs.bundle_dir)
@@ -54,6 +54,20 @@ class RubyWasm::Packager
54
54
  end
55
55
  wasm_bytes = ruby_core.link_gem_exts(executor, fs.ruby_root, fs.bundle_dir, wasm_bytes)
56
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
70
+
57
71
  wasm_bytes = RubyWasmExt.preinitialize(wasm_bytes) if options[:optimize]
58
72
  wasm_bytes
59
73
  end
@@ -68,8 +82,9 @@ class RubyWasm::Packager
68
82
  # Retrieves the specs from the Bundler definition, excluding the excluded gems.
69
83
  def specs
70
84
  return [] unless @definition
71
- @specs ||= @definition.resolve.materialize(@definition.requested_dependencies)
85
+ __skip__ = @specs ||= @definition.resolve.materialize(@definition.requested_dependencies)
72
86
  .reject { |spec| EXCLUDED_GEMS.include?(spec.name) }
87
+ .reject { |spec| spec.is_a?(Bundler::LazySpecification) }
73
88
  @specs
74
89
  end
75
90
 
@@ -1,3 +1,3 @@
1
1
  module RubyWasm
2
- VERSION = "2.6.1"
2
+ VERSION = "2.7.0"
3
3
  end