ruby_wasm 2.6.2-x86_64-linux-musl → 2.7.1-x86_64-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: 600f38b1685c5427dc537c287f3fb6d17944613758b5451ea46110318d681500
4
- data.tar.gz: 880db754bb7abf5744ef2adbcfa7f4bb6af06eb8be610e7e7781a7f15a648b54
3
+ metadata.gz: 0276a0c3649ee468e43730331a014773851603bb2d9d65ad2cf9dddfb24057a8
4
+ data.tar.gz: 33c4803879470e0c90af19499481c4ba2360846799cc58840600c5327e0cfe38
5
5
  SHA512:
6
- metadata.gz: 2614e52c087fc8e9927917e40bcfce57cd2d3117ebfb8657af7e993d08084e5614e6e0d61bdc601f3a644f9ef725e79a2f44944efb1daa1431700c24f859cd59
7
- data.tar.gz: 74c712f53ed169c9173e7ffd5efd0207c6f933c82e3ceaf2b5f9a0f0d5ca0b20fa15e7584e213c319a79075de737075cefcffb7754584ad549728d216cff549f
6
+ metadata.gz: ef17a9dece48ae79a0f1c379234710e284b31ee89ec20e1dbbdfb3f9ae3691a53971beb13b2c25f7cca9f2b03e45f4a77f978c0f658338c5a11c671339702c88
7
+ data.tar.gz: a9f9236f32c6e16bf5044a6bd74942e04492eebd81151aaa64cb14ae0ba41fb4bb2e87026f597b86961f1d679109dff9dd150a54ca55e4060ffd1a69a4a455ac
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,45 @@ $ 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.2-2024-06-29-a
132
+ $ npm install --save @ruby/wasm-wasi@2.7.1-2025-01-23-a
131
133
  ```
134
+
135
+
136
+ ## Adding Support for a New Ruby Version
137
+
138
+ When a new version of Ruby is released, the following steps need to be taken to add support for it in ruby.wasm:
139
+
140
+ 1. Update `lib/ruby_wasm/cli.rb`:
141
+ - Add a new entry in the `build_source_aliases` method for the new version
142
+ - Specify the tarball URL and required default extensions
143
+
144
+ 2. Update `Rakefile`:
145
+ - Add the new version to `BUILD_SOURCES`
146
+ - Add a new entry in `NPM_PACKAGES` for the new version
147
+
148
+ 3. Create a new npm package:
149
+ ```console
150
+ # Copy from head package
151
+ $ cp -r packages/npm-packages/ruby-head-wasm-wasi packages/npm-packages/ruby-NEW.VERSION-wasm-wasi
152
+
153
+ # Update version references
154
+ # - In package.json: Update name, version, and description
155
+ # - In README.md: Update version references
156
+ ```
157
+ Note: Most of the package contents can be reused from the head package as is, since the JavaScript API and build configuration remain the same across versions.
158
+
159
+ 4. Update `package-lock.json` by `npm install`
160
+
161
+ 4. Update documentation:
162
+ - Update version references in `README.md`
163
+ - Update examples in `docs/cheat_sheet.md`
164
+ - Update the package list in `packages/npm-packages/ruby-wasm-wasi/README.md`
165
+
166
+ 5. Test the build:
167
+ ```console
168
+ $ rake build:NEW.VERSION-wasm32-unknown-wasip1-full
169
+ $ rake npm:ruby-NEW.VERSION-wasm-wasi:build
170
+ $ rake npm:ruby-NEW.VERSION-wasm-wasi:check
171
+ ```
172
+
173
+ 6. Create a pull request with all the changes
data/Gemfile CHANGED
@@ -7,11 +7,12 @@ gemspec
7
7
  group :development do
8
8
  gem "rake"
9
9
  gem "rake-compiler"
10
- gem "rb_sys", "0.9.97"
10
+ gem "rb_sys", "0.9.108"
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
- gem "steep"
17
+ gem "steep", "~> 1.9" if RUBY_VERSION >= "3.1.0"
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.2/dist/browser.script.iife.js"></script>
26
+ <script src="https://cdn.jsdelivr.net/npm/@ruby/3.4-wasm-wasi@2.7.1/dist/browser.script.iife.js"></script>
27
27
  <script type="text/ruby">
28
28
  require "js"
29
29
 
@@ -40,18 +40,18 @@ Dependencies: [wasmtime](https://github.com/bytecodealliance/wasmtime)
40
40
  ```console
41
41
  $ gem install ruby_wasm
42
42
  # Download a prebuilt Ruby release
43
- $ curl -LO https://github.com/ruby/ruby.wasm/releases/latest/download/ruby-3.3-wasm32-unknown-wasip1-full.tar.gz
44
- $ tar xfz ruby-3.3-wasm32-unknown-wasip1-full.tar.gz
43
+ $ curl -LO https://github.com/ruby/ruby.wasm/releases/latest/download/ruby-3.4-wasm32-unknown-wasip1-full.tar.gz
44
+ $ tar xfz ruby-3.4-wasm32-unknown-wasip1-full.tar.gz
45
45
 
46
46
  # Extract ruby binary not to pack itself
47
- $ mv ruby-3.3-wasm32-unknown-wasip1-full/usr/local/bin/ruby ruby.wasm
47
+ $ mv ruby-3.4-wasm32-unknown-wasip1-full/usr/local/bin/ruby ruby.wasm
48
48
 
49
49
  # Put your app code
50
50
  $ mkdir src
51
51
  $ echo "puts 'Hello'" > src/my_app.rb
52
52
 
53
53
  # Pack the whole directory under /usr and your app dir
54
- $ rbwasm pack ruby.wasm --dir ./src::/src --dir ./ruby-3.3-wasm32-unknown-wasip1-full/usr::/usr -o my-ruby-app.wasm
54
+ $ rbwasm pack ruby.wasm --dir ./src::/src --dir ./ruby-3.4-wasm32-unknown-wasip1-full/usr::/usr -o my-ruby-app.wasm
55
55
 
56
56
  # Run the packed scripts
57
57
  $ wasmtime my-ruby-app.wasm /src/my_app.rb
@@ -71,6 +71,11 @@ See the `README.md` of each package for more detail and its usage.
71
71
  </tr>
72
72
  </thead>
73
73
  <tbody>
74
+ <tr>
75
+ <td><a href="/packages/npm-packages/ruby-3.4-wasm-wasi">@ruby/3.4-wasm-wasi</a></td>
76
+ <td>CRuby 3.4 built on WASI with JS interop support</td>
77
+ <td><a href="https://www.npmjs.com/package/@ruby/3.4-wasm-wasi" rel="nofollow"><img src="https://badge.fury.io/js/@ruby%2F3.4-wasm-wasi.svg" alt="npm version" style="max-width: 100%;"></a></td>
78
+ </tr>
74
79
  <tr>
75
80
  <td><a href="/packages/npm-packages/ruby-3.3-wasm-wasi">@ruby/3.3-wasm-wasi</a></td>
76
81
  <td>CRuby 3.3 built on WASI with JS interop support</td>
data/Rakefile CHANGED
@@ -9,7 +9,7 @@ require "ruby_wasm/rake_task"
9
9
  require "ruby_wasm/packager"
10
10
  require "ruby_wasm/cli"
11
11
 
12
- BUILD_SOURCES = %w[3.3 3.2 head]
12
+ BUILD_SOURCES = %w[3.4 3.3 3.2 head]
13
13
  BUILD_PROFILES = %w[full minimal]
14
14
 
15
15
  BUILDS =
@@ -28,20 +28,32 @@ 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
  },
41
+ {
42
+ name: "ruby-3.4-wasm-wasi",
43
+ ruby_version: "3.4",
44
+ gemfile: "packages/npm-packages/ruby-3.3-wasm-wasi/Gemfile",
45
+ target: "wasm32-unknown-wasip1"
46
+ },
35
47
  {
36
48
  name: "ruby-3.3-wasm-wasi",
37
49
  ruby_version: "3.3",
38
- gemfile: "packages/npm-packages/ruby-wasm-wasi/Gemfile",
50
+ gemfile: "packages/npm-packages/ruby-3.3-wasm-wasi/Gemfile",
39
51
  target: "wasm32-unknown-wasip1"
40
52
  },
41
53
  {
42
54
  name: "ruby-3.2-wasm-wasi",
43
55
  ruby_version: "3.2",
44
- gemfile: "packages/npm-packages/ruby-wasm-wasi/Gemfile",
56
+ gemfile: "packages/npm-packages/ruby-3.2-wasm-wasi/Gemfile",
45
57
  target: "wasm32-unknown-wasip1"
46
58
  },
47
59
  { name: "ruby-wasm-wasi", target: "wasm32-unknown-wasip1" }
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
@@ -8,10 +8,10 @@
8
8
 
9
9
  ## Node.js
10
10
 
11
- To install the package, install `@ruby/3.3-wasm-wasi` and `@ruby/wasm-wasi` from npm:
11
+ To install the package, install `@ruby/3.4-wasm-wasi` and `@ruby/wasm-wasi` from npm:
12
12
 
13
13
  ```console
14
- npm install --save @ruby/3.3-wasm-wasi @ruby/wasm-wasi
14
+ npm install --save @ruby/3.4-wasm-wasi @ruby/wasm-wasi
15
15
  ```
16
16
 
17
17
  Then instantiate a Ruby VM by the following code:
@@ -20,7 +20,7 @@ Then instantiate a Ruby VM by the following code:
20
20
  import fs from "fs/promises";
21
21
  import { DefaultRubyVM } from "@ruby/wasm-wasi/dist/node";
22
22
 
23
- const binary = await fs.readFile("./node_modules/@ruby/3.3-wasm-wasi/dist/ruby.wasm");
23
+ const binary = await fs.readFile("./node_modules/@ruby/3.4-wasm-wasi/dist/ruby.wasm");
24
24
  const module = await WebAssembly.compile(binary);
25
25
  const { vm } = await DefaultRubyVM(module);
26
26
  vm.eval(`puts "hello world"`);
@@ -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.2/dist/browser.script.iife.js"></script>
41
+ <script src="https://cdn.jsdelivr.net/npm/@ruby/3.4-wasm-wasi@2.7.1/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.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");
54
+ import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.7.1/dist/browser/+esm";
55
+ const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.4-wasm-wasi@2.7.1/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.2/dist/browser.umd.js"></script>
72
+ <script src="https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.7.1/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.2/dist/ruby+stdlib.wasm");
76
+ const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.4-wasm-wasi@2.7.1/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.2/dist/browser.script.iife.js"></script>
131
+ <script src="https://cdn.jsdelivr.net/npm/@ruby/3.4-wasm-wasi@2.7.1/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.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");
146
+ import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.7.1/dist/browser/+esm";
147
+ const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.4-wasm-wasi@2.7.1/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
Binary file
@@ -32,7 +32,7 @@ module RubyWasm
32
32
  end
33
33
 
34
34
  def make_args(crossruby)
35
- make_args = []
35
+ make_args = [] #: Array[String]
36
36
  make_args << "CC=#{@toolchain.cc}"
37
37
  make_args << "CXX=#{@toolchain.cc}"
38
38
  make_args << "LD=#{@toolchain.ld}"
@@ -71,14 +71,14 @@ module RubyWasm
71
71
  return
72
72
  end
73
73
  objdir = product_build_dir crossruby
74
- rbconfig_rb = Dir.glob(File.join(crossruby.dest_dir, "usr/local/lib/ruby/*/wasm32-wasi/rbconfig.rb")).first
74
+ rbconfig_rb = crossruby.rbconfig_rb
75
75
  raise "rbconfig.rb not found" unless rbconfig_rb
76
76
  extconf_args = [
77
77
  "-C", objdir,
78
78
  "#{@srcdir}/extconf.rb",
79
79
  "--target-rbconfig=#{rbconfig_rb}",
80
80
  ]
81
- extconf_args << "--enable-component-model" if @features.support_component_model?
81
+ extconf_args << "--disable-component-model" unless @features.support_component_model?
82
82
  executor.system crossruby.baseruby_path, *extconf_args
83
83
  end
84
84
 
@@ -90,10 +90,19 @@ module RubyWasm
90
90
  "--disable=gems",
91
91
  # HACK: top_srcdir is required to find ruby headers
92
92
  "-e",
93
- %Q($top_srcdir="#{source.src_dir}"),
93
+ %Q($top_srcdir=ENV["top_srcdir"]="#{source.src_dir}"),
94
94
  # HACK: extout is required to find config.h
95
95
  "-e",
96
- %Q($extout="#{crossruby.build_dir}/.ext"),
96
+ %Q($extout=ENV["extout"]="#{crossruby.build_dir}/.ext"),
97
+ ]
98
+ unless @features.support_component_model?
99
+ extconf_args.concat([
100
+ # HACK: skip have_devel check since ruby is not installed yet
101
+ "-e",
102
+ "$have_devel = true",
103
+ ])
104
+ end
105
+ extconf_args.concat([
97
106
  # HACK: force static ext build by imitating extmk
98
107
  "-e",
99
108
  "$static = true; trace_var(:$static) {|v| $static = true }",
@@ -110,8 +119,8 @@ module RubyWasm
110
119
  %Q(require "json"; File.write("#{metadata_json(crossruby)}", JSON.dump({target: $target}))),
111
120
  "-I#{crossruby.build_dir}",
112
121
  "--",
113
- ]
114
- extconf_args << "--enable-component-model" if @features.support_component_model?
122
+ ])
123
+ extconf_args << "--disable-component-model" unless @features.support_component_model?
115
124
  # Clear RUBYOPT to avoid loading unrelated bundle setup
116
125
  executor.system crossruby.baseruby_path,
117
126
  *extconf_args,
@@ -222,6 +231,10 @@ module RubyWasm
222
231
  end
223
232
  install_dir = File.join(build_dir, "install")
224
233
  if !File.exist?(install_dir) || remake || reconfigure
234
+ unless target.pic?
235
+ # HACK: force static linking for non-pic target
236
+ executor.rm_f File.join(build_dir, "ruby")
237
+ end
225
238
  executor.system "make",
226
239
  "-j#{executor.process_count}",
227
240
  "install",
@@ -301,6 +314,10 @@ module RubyWasm
301
314
  File.expand_path("../crossruby/extinit.c.erb", __FILE__)
302
315
  end
303
316
 
317
+ def rbconfig_rb
318
+ Dir.glob(File.join(dest_dir, "usr/local/lib/ruby/*/wasm32-wasi/rbconfig.rb")).first
319
+ end
320
+
304
321
  def baseruby_path
305
322
  File.join(@baseruby.install_dir, "bin/ruby")
306
323
  end
@@ -11,7 +11,7 @@ module RubyWasm
11
11
  @toolchain = toolchain
12
12
  end
13
13
  def system_triplet_args
14
- args = []
14
+ args = [] #: Array[String]
15
15
  case @target.triple
16
16
  when /^wasm32-unknown-wasi/
17
17
  args.concat(%W[--host wasm32-wasi])
@@ -24,7 +24,7 @@ module RubyWasm
24
24
  end
25
25
 
26
26
  def tools_args
27
- args = []
27
+ args = [] #: Array[String]
28
28
  args << "CC=#{@toolchain.cc}"
29
29
  args << "CXX=#{@toolchain.cxx}"
30
30
  args << "LD=#{@toolchain.ld}"
@@ -45,7 +45,7 @@ module RubyWasm
45
45
 
46
46
  %i[cc cxx ranlib ld ar].each do |name|
47
47
  define_method(name) do
48
- @tools_cache ||= {}
48
+ @tools_cache ||= {} #: Hash[String, String]
49
49
  @tools_cache[name] ||= find_tool(name)
50
50
  @tools_cache[name]
51
51
  end
data/lib/ruby_wasm/cli.rb CHANGED
@@ -242,6 +242,11 @@ module RubyWasm
242
242
  rev: "master",
243
243
  all_default_exts: RubyWasm::Packager::ALL_DEFAULT_EXTS,
244
244
  },
245
+ "3.4" => {
246
+ type: "tarball",
247
+ url: "https://cache.ruby-lang.org/pub/ruby/3.4/ruby-3.4.1.tar.gz",
248
+ all_default_exts: "cgi/escape,continuation,coverage,date,digest/bubblebabble,digest,digest/md5,digest/rmd160,digest/sha1,digest/sha2,etc,fcntl,json,json/generator,json/parser,objspace,pathname,psych,rbconfig/sizeof,ripper,stringio,strscan,monitor,zlib,openssl",
249
+ },
245
250
  "3.3" => {
246
251
  type: "tarball",
247
252
  url: "https://cache.ruby-lang.org/pub/ruby/3.3/ruby-3.3.3.tar.gz",
@@ -310,7 +315,10 @@ module RubyWasm
310
315
 
311
316
  def derive_packager(options)
312
317
  __skip__ = definition = nil
313
- __skip__ = if defined?(Bundler) && !options[:disable_gems]
318
+ features = RubyWasm::FeatureSet.derive_from_env
319
+ # The head ruby & dynamic linking uses "bundle" command to build gems instead of in-process integration.
320
+ use_in_process_gem_building = !(options[:ruby_version] == "head" && features.support_dynamic_linking?)
321
+ __skip__ = if defined?(Bundler) && !options[:disable_gems] && use_in_process_gem_building
314
322
  begin
315
323
  # Silence Bundler UI if --print-ruby-cache-key is specified not to bother the JSON output.
316
324
  level = options[:print_ruby_cache_key] ? :silent : Bundler.ui.level
@@ -321,10 +329,10 @@ module RubyWasm
321
329
  Bundler.ui.level = old_level
322
330
  end
323
331
  end
324
- RubyWasm.logger.info "Using Gemfile: #{definition.gemfiles}" if definition
332
+ RubyWasm.logger.info "Using Gemfile: #{definition.gemfiles.map(&:to_s).join(", ")}" if definition
325
333
  RubyWasm::Packager.new(
326
334
  root, build_config(options), definition,
327
- features: RubyWasm::FeatureSet.derive_from_env
335
+ features: features,
328
336
  )
329
337
  end
330
338
 
@@ -332,6 +340,9 @@ module RubyWasm
332
340
  ruby_core_build = packager.ruby_core_build
333
341
  require "digest"
334
342
  digest = Digest::SHA256.new
343
+ # The build system key is used to invalidate the cache when the build system is updated.
344
+ build_system_key = 1
345
+ digest.update(build_system_key.to_s)
335
346
  ruby_core_build.cache_key(digest)
336
347
  hexdigest = digest.hexdigest
337
348
  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,14 +59,6 @@ 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"
66
- end
67
- use_js_gem ? "reactor" : "command"
68
- end
69
-
70
62
  def with_unbundled_env(&block)
71
63
  __skip__ = if defined?(Bundler)
72
64
  Bundler.with_unbundled_env(&block)
@@ -119,7 +111,7 @@ class RubyWasm::Packager::Core
119
111
  end
120
112
 
121
113
  def _link_gem_exts(executor, build, ruby_root, gem_home, module_bytes)
122
- libraries = []
114
+ libraries = [] #: Array[String]
123
115
 
124
116
  # TODO: Should be computed from dyinfo of ruby binary
125
117
  wasi_libc_shared_libs = [
@@ -138,12 +130,16 @@ class RubyWasm::Packager::Core
138
130
  wasi_sdk_path = toolchain.wasi_sdk_path
139
131
  libraries << File.join(wasi_sdk_path, "share/wasi-sysroot/lib/wasm32-wasi", lib)
140
132
  end
141
- wasi_adapter = RubyWasm::Packager::ComponentAdapter.wasi_snapshot_preview1(wasi_exec_model)
142
- adapters = [wasi_adapter]
143
- dl_openable_libs = []
133
+ dl_openable_libs = [] #: Array[[string, Array[String]]]
144
134
  dl_openable_libs << [File.dirname(ruby_root), Dir.glob(File.join(ruby_root, "lib", "ruby", "**", "*.so"))]
145
135
  dl_openable_libs << [gem_home, Dir.glob(File.join(gem_home, "**", "*.so"))]
146
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
+
147
143
  linker = RubyWasmExt::ComponentLink.new
148
144
  linker.use_built_in_libdl(true)
149
145
  linker.stub_missing_functions(false)
@@ -151,11 +147,13 @@ class RubyWasm::Packager::Core
151
147
 
152
148
  linker.library("ruby", module_bytes, false)
153
149
 
150
+ RubyWasm.logger.info "Linking Ruby with extensions"
151
+
154
152
  libraries.each do |lib|
155
153
  # Non-DL openable libraries should be referenced as base name
156
154
  lib_name = File.basename(lib)
157
155
  module_bytes = File.binread(lib)
158
- RubyWasm.logger.info "Linking #{lib_name} (#{module_bytes.size} bytes)"
156
+ RubyWasm.logger.debug "Linking #{lib_name} (#{module_bytes.size} bytes)"
159
157
  linker.library(lib_name, module_bytes, false)
160
158
  end
161
159
 
@@ -164,7 +162,7 @@ class RubyWasm::Packager::Core
164
162
  # DL openable lib_name should be a relative path from ruby_root
165
163
  lib_name = "/" + Pathname.new(lib).relative_path_from(Pathname.new(File.dirname(root))).to_s
166
164
  module_bytes = File.binread(lib)
167
- RubyWasm.logger.info "Linking #{lib_name} (#{module_bytes.size} bytes)"
165
+ RubyWasm.logger.debug "Linking #{lib_name} (#{module_bytes.size} bytes)"
168
166
  linker.library(lib_name, module_bytes, true)
169
167
  end
170
168
  end
@@ -174,7 +172,7 @@ class RubyWasm::Packager::Core
174
172
  # e.g. wasi_snapshot_preview1.command.wasm -> wasi_snapshot_preview1
175
173
  adapter_name = adapter_name.split(".")[0]
176
174
  module_bytes = File.binread(adapter)
177
- 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)"
178
176
  linker.adapter(adapter_name, module_bytes)
179
177
  end
180
178
  return linker.encode()
@@ -187,31 +185,43 @@ class RubyWasm::Packager::Core
187
185
  baseruby.build(executor)
188
186
  end
189
187
 
190
- exts = specs_with_extensions.flat_map do |spec, exts|
191
- exts.map do |ext|
192
- ext_feature = File.dirname(ext) # e.g. "ext/cgi/escape"
193
- ext_srcdir = File.join(spec.full_gem_path, ext_feature)
194
- ext_relative_path = File.join(spec.full_name, ext_feature)
195
- prod = RubyWasm::CrossRubyExtProduct.new(
196
- ext_srcdir,
197
- build.toolchain,
198
- features: @packager.features,
199
- ext_relative_path: ext_relative_path
200
- )
201
- [prod, spec]
202
- end
203
- end
188
+ crossruby = build.crossruby
189
+ rbconfig_rb = crossruby.rbconfig_rb
204
190
 
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
- ]
211
- executor.begin_section prod.class, prod.name, "Building"
212
- prod.build(executor, build.crossruby, extra_mkargs)
213
- executor.end_section prod.class, prod.name
214
- end
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)
215
225
  end
216
226
 
217
227
  def cache_key(digest)
@@ -337,6 +347,14 @@ class RubyWasm::Packager::Core
337
347
  # No-op because we already built extensions as part of the Ruby build
338
348
  end
339
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
+
340
358
  def link_gem_exts(executor, ruby_root, gem_home, module_bytes)
341
359
  return module_bytes unless @packager.features.support_component_model?
342
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|
@@ -1,3 +1,3 @@
1
1
  module RubyWasm
2
- VERSION = "2.6.2"
2
+ VERSION = "2.7.1"
3
3
  end