ruby_wasm 2.7.1 → 2.8.1

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: 66b759c02ace22303d907da3a0946c2f45f8e748c9999f158315297a9f6ba228
4
- data.tar.gz: 435fd739cfc81ed29845981604996490322a34902289838495dfa6c6142c46ee
3
+ metadata.gz: 878e62686b8adacaa720e4e83d4cb98fec1c0914b4adb47d2aa6fd191fd975ee
4
+ data.tar.gz: 4947a7cf6733b47cbfe966137d74643d3635b194d1bb112b2d27386d9a3a637a
5
5
  SHA512:
6
- metadata.gz: 8b3400df7a4004808c0c4e89f2dfa2e3ce8ad6d2d179edbd794c71b6d87143533c1acf116af7df1c21562b70cb9f82bd9728e4477cb56b3ec7fdca808835d62a
7
- data.tar.gz: 8ce2c317c921e927ceb6a9b696c98d485b58139e077fbb2fe38d8118f40eb675c7eed0742089131b6940259cb5c066db6ed1fedd0bff81e5de4f15ce03e19bbd
6
+ metadata.gz: b735b04fde796b84f85873e7f805f30e914e4106e0f3264a8051f827bd2c1aea34f71256b8eb0baf7fbf4a5c0757ff89879ed100c6016ebeffd817404e05c1f3
7
+ data.tar.gz: fc7722e2f44e1cde69170d602e0a02b1f43c90b8a7adc64a01957bfc7ac84be593b3212730ab5f58e8764e5a8685aea0c83b1cff6a692c0290f096e71e1afd9c
data/CONTRIBUTING.md CHANGED
@@ -129,7 +129,7 @@ $ npm install --save @ruby/wasm-wasi@latest
129
129
  # or if you want the nightly snapshot
130
130
  $ npm install --save @ruby/wasm-wasi@next
131
131
  # or you can specify the exact snapshot version
132
- $ npm install --save @ruby/wasm-wasi@2.7.1-2025-01-23-a
132
+ $ npm install --save @ruby/wasm-wasi@2.8.0-2025-12-29-a
133
133
  ```
134
134
 
135
135
 
@@ -138,7 +138,7 @@ $ npm install --save @ruby/wasm-wasi@2.7.1-2025-01-23-a
138
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
139
 
140
140
  1. Update `lib/ruby_wasm/cli.rb`:
141
- - Add a new entry in the `build_source_aliases` method for the new version
141
+ - Add a new entry in the `build_config_aliases` method for the new version
142
142
  - Specify the tarball URL and required default extensions
143
143
 
144
144
  2. Update `Rakefile`:
data/Cargo.lock CHANGED
@@ -1361,7 +1361,7 @@ dependencies = [
1361
1361
  "wasi-virt",
1362
1362
  "wasm-compose 0.219.1",
1363
1363
  "wit-component 0.216.0",
1364
- "wizer",
1364
+ "wizer 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
1365
1365
  ]
1366
1366
 
1367
1367
  [[package]]
@@ -1835,13 +1835,13 @@ dependencies = [
1835
1835
  [[package]]
1836
1836
  name = "wasi-vfs-cli"
1837
1837
  version = "0.5.3"
1838
- source = "git+https://github.com/kateinoigakukun/wasi-vfs/?tag=v0.5.3#39d83db2b2518d1f991276960d22d3948d62f7df"
1838
+ source = "git+https://github.com/kateinoigakukun/wasi-vfs/?tag=v0.5.3-p1#32437aed43b117fe6905f547924196c15bf7b966"
1839
1839
  dependencies = [
1840
1840
  "anyhow",
1841
1841
  "structopt",
1842
1842
  "wasm-encoder 0.212.0",
1843
1843
  "wasmparser 0.212.0",
1844
- "wizer",
1844
+ "wizer 6.0.0 (git+https://github.com/kateinoigakukun/wizer.git?branch=katei/add-env-option-6.0.0)",
1845
1845
  ]
1846
1846
 
1847
1847
  [[package]]
@@ -2750,6 +2750,21 @@ dependencies = [
2750
2750
  "wasmtime",
2751
2751
  ]
2752
2752
 
2753
+ [[package]]
2754
+ name = "wizer"
2755
+ version = "6.0.0"
2756
+ source = "git+https://github.com/kateinoigakukun/wizer.git?branch=katei/add-env-option-6.0.0#8e7158013eb3d1059504229eff834eb1f3e33949"
2757
+ dependencies = [
2758
+ "anyhow",
2759
+ "cap-std",
2760
+ "log",
2761
+ "rayon",
2762
+ "wasi-common",
2763
+ "wasm-encoder 0.202.0",
2764
+ "wasmparser 0.202.0",
2765
+ "wasmtime",
2766
+ ]
2767
+
2753
2768
  [[package]]
2754
2769
  name = "zerocopy"
2755
2770
  version = "0.7.34"
data/Gemfile CHANGED
@@ -14,5 +14,5 @@ group :check do
14
14
  # Use the latest version of webrick for URI change in Ruby 3.4
15
15
  gem "webrick", "~> 1.8.2"
16
16
  gem "syntax_tree", "~> 3.5"
17
- gem "steep", "~> 1.9" if RUBY_VERSION >= "3.1.0"
17
+ gem "steep", "1.10.0" if RUBY_VERSION >= "3.1.0"
18
18
  end
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.4-wasm-wasi@2.7.1/dist/browser.script.iife.js"></script>
26
+ <script src="https://cdn.jsdelivr.net/npm/@ruby/4.0-wasm-wasi@2.8.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.4-wasm32-unknown-wasip1-full.tar.gz
44
- $ tar xfz ruby-3.4-wasm32-unknown-wasip1-full.tar.gz
43
+ $ curl -LO https://github.com/ruby/ruby.wasm/releases/latest/download/ruby-4.0-wasm32-unknown-wasip1-full.tar.gz
44
+ $ tar xfz ruby-4.0-wasm32-unknown-wasip1-full.tar.gz
45
45
 
46
46
  # Extract ruby binary not to pack itself
47
- $ mv ruby-3.4-wasm32-unknown-wasip1-full/usr/local/bin/ruby ruby.wasm
47
+ $ mv ruby-4.0-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.4-wasm32-unknown-wasip1-full/usr::/usr -o my-ruby-app.wasm
54
+ $ rbwasm pack ruby.wasm --dir ./src::/src --dir ./ruby-4.0-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-4.0-wasm-wasi">@ruby/4.0-wasm-wasi</a></td>
76
+ <td>CRuby 4.0 built on WASI with JS interop support</td>
77
+ <td><a href="https://www.npmjs.com/package/@ruby/4.0-wasm-wasi" rel="nofollow"><img src="https://badge.fury.io/js/@ruby%2F4.0-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.4-wasm-wasi">@ruby/3.4-wasm-wasi</a></td>
76
81
  <td>CRuby 3.4 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.4 3.3 3.2 head]
12
+ BUILD_SOURCES = %w[4.0 3.4 3.3 3.2 head]
13
13
  BUILD_PROFILES = %w[full minimal]
14
14
 
15
15
  BUILDS =
@@ -29,19 +29,25 @@ NPM_PACKAGES = [
29
29
  name: "ruby-head-wasm-wasi",
30
30
  ruby_version: "head",
31
31
  gemfile: "packages/npm-packages/ruby-head-wasm-wasi/Gemfile",
32
- target: "wasm32-unknown-wasip1",
32
+ target: "wasm32-unknown-wasip1"
33
33
  },
34
34
  {
35
35
  name: "ruby-head-wasm-wasip2",
36
36
  ruby_version: "head",
37
37
  gemfile: "packages/npm-packages/ruby-head-wasm-wasip2/Gemfile",
38
38
  target: "wasm32-unknown-wasip2",
39
- enable_component_model: true,
39
+ enable_component_model: true
40
+ },
41
+ {
42
+ name: "ruby-4.0-wasm-wasi",
43
+ ruby_version: "4.0",
44
+ gemfile: "packages/npm-packages/ruby-4.0-wasm-wasi/Gemfile",
45
+ target: "wasm32-unknown-wasip1"
40
46
  },
41
47
  {
42
48
  name: "ruby-3.4-wasm-wasi",
43
49
  ruby_version: "3.4",
44
- gemfile: "packages/npm-packages/ruby-3.3-wasm-wasi/Gemfile",
50
+ gemfile: "packages/npm-packages/ruby-3.4-wasm-wasi/Gemfile",
45
51
  target: "wasm32-unknown-wasip1"
46
52
  },
47
53
  {
@@ -66,16 +72,6 @@ STANDALONE_PACKAGES = [
66
72
 
67
73
  LIB_ROOT = File.dirname(__FILE__)
68
74
 
69
- TOOLCHAINS = {}
70
- BUILDS
71
- .map { |_, target, _| target }
72
- .uniq
73
- .each do |target|
74
- build_dir = File.join(LIB_ROOT, "build")
75
- toolchain = RubyWasm::Toolchain.get(target, build_dir)
76
- TOOLCHAINS[toolchain.name] = toolchain
77
- end
78
-
79
75
  class BuildTask < Struct.new(:name, :target, :build_command)
80
76
  def ruby_cache_key
81
77
  return @key if @key
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.4-wasm-wasi` and `@ruby/wasm-wasi` from npm:
11
+ To install the package, install `@ruby/4.0-wasm-wasi` and `@ruby/wasm-wasi` from npm:
12
12
 
13
13
  ```console
14
- npm install --save @ruby/3.4-wasm-wasi @ruby/wasm-wasi
14
+ npm install --save @ruby/4.0-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.4-wasm-wasi/dist/ruby.wasm");
23
+ const binary = await fs.readFile("./node_modules/@ruby/4.0-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.4-wasm-wasi@2.7.1/dist/browser.script.iife.js"></script>
41
+ <script src="https://cdn.jsdelivr.net/npm/@ruby/4.0-wasm-wasi@2.8.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.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");
54
+ import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.8.0/dist/browser/+esm";
55
+ const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/4.0-wasm-wasi@2.8.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.7.1/dist/browser.umd.js"></script>
72
+ <script src="https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.8.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.4-wasm-wasi@2.7.1/dist/ruby+stdlib.wasm");
76
+ const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/4.0-wasm-wasi@2.8.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.4-wasm-wasi@2.7.1/dist/browser.script.iife.js"></script>
131
+ <script src="https://cdn.jsdelivr.net/npm/@ruby/4.0-wasm-wasi@2.8.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.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");
146
+ import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.8.0/dist/browser/+esm";
147
+ const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/4.0-wasm-wasi@2.8.1/dist/ruby+stdlib.wasm");
148
148
  const module = await WebAssembly.compileStreaming(response);
149
149
  const { vm } = await DefaultRubyVM(module);
150
150
 
@@ -13,7 +13,7 @@ crate-type = ["cdylib"]
13
13
  magnus = { version = "0.7.1", features = ["bytes"] }
14
14
  bytes = "1"
15
15
  wizer = "6.0.0"
16
- wasi-vfs-cli = { git = "https://github.com/kateinoigakukun/wasi-vfs/", tag = "v0.5.3" }
16
+ wasi-vfs-cli = { git = "https://github.com/kateinoigakukun/wasi-vfs/", tag = "v0.5.3-p1" }
17
17
  structopt = "0.3.26"
18
18
  wit-component = "0.216.0"
19
19
  wasm-compose = "0.219.1"
@@ -147,6 +147,16 @@ module RubyWasm
147
147
  end
148
148
  end
149
149
 
150
+ class SilentExecutor
151
+ def system(*args, chdir: nil, env: nil)
152
+ # @type var kwargs: Hash[Symbol, untyped]
153
+ kwargs = {}
154
+ kwargs[:chdir] = chdir if chdir
155
+ kwargs[:exception] = true
156
+ __skip__ = env ? Kernel.system(env, *args, **kwargs) : Kernel.system(*args, **kwargs)
157
+ end
158
+ end
159
+
150
160
  # Human readable status printer for the build.
151
161
  class StatusPrinter
152
162
  def initialize
@@ -204,7 +204,7 @@ module RubyWasm
204
204
  def build(executor, remake: false, reconfigure: false)
205
205
  executor.mkdir_p dest_dir
206
206
  executor.mkdir_p build_dir
207
- @toolchain.install
207
+ @toolchain.install(executor)
208
208
  [@source, @baseruby, @libyaml, @zlib, @openssl, @wasi_vfs].each do |prod|
209
209
  next unless prod
210
210
  executor.begin_section prod.class, prod.name, "Building"
@@ -345,6 +345,17 @@ module RubyWasm
345
345
  wasi_sdk_path = @toolchain
346
346
  args << %Q(WASMOPT=#{wasi_sdk_path.wasm_opt})
347
347
  args << %Q(WASI_SDK_PATH=#{wasi_sdk_path.wasi_sdk_path})
348
+ # NOTE: wasi-libc 22 and later defines stubs for fchmod and chmod
349
+ # but they just return ENOTSUP, and ruby's configure doesn't check
350
+ # the runtime behavior. So we need to tell configure that
351
+ # these functions are not available.
352
+ # https://github.com/WebAssembly/wasi-libc/pull/463
353
+ args << %Q(ac_cv_func_fchmod=no)
354
+ args << %Q(ac_cv_func_chmod=no)
355
+ # TODO: wasi-libc 22 and later started using musl's realpath impl but
356
+ # it broke Kernel#require on @bjorn3/browser_wasi_shim setup for some
357
+ # reason. So we disable it for now.
358
+ args << %Q(ac_cv_func_realpath=no)
348
359
  when "wasm32-unknown-emscripten"
349
360
  ldflags.concat(%w[-s MODULARIZE=1])
350
361
  env_emcc_ldflags = ENV["RUBY_WASM_EMCC_LDFLAGS"] || ""
@@ -16,10 +16,15 @@ module RubyWasm
16
16
  raise "missing environment variable: #{name}" if ENV[name].nil?
17
17
  end
18
18
 
19
- def self.get(target, build_dir = nil)
19
+ def self.get(target, options, build_dir = nil)
20
20
  case target
21
21
  when /^wasm32-unknown-wasi/
22
- return RubyWasm::WASISDK.new(build_dir: build_dir)
22
+ return(
23
+ RubyWasm::WASISDK.new(
24
+ build_dir: build_dir,
25
+ version: options[:wasi_sdk_version]
26
+ )
27
+ )
23
28
  when "wasm32-unknown-emscripten"
24
29
  return RubyWasm::Emscripten.new
25
30
  else
@@ -46,7 +51,7 @@ module RubyWasm
46
51
  %i[cc cxx ranlib ld ar].each do |name|
47
52
  define_method(name) do
48
53
  @tools_cache ||= {} #: Hash[String, String]
49
- @tools_cache[name] ||= find_tool(name)
54
+ __skip__ = @tools_cache[name] ||= find_tool(name)
50
55
  @tools_cache[name]
51
56
  end
52
57
  end
@@ -56,32 +61,24 @@ module RubyWasm
56
61
  def initialize(
57
62
  wasi_sdk_path = ENV["WASI_SDK_PATH"],
58
63
  build_dir: nil,
59
- version_major: 21,
60
- version_minor: 0,
64
+ version: "23.0",
61
65
  binaryen_version: 108
62
66
  )
63
- @wasm_opt_path = Toolchain.find_path("wasm-opt")
64
67
  @need_fetch_wasi_sdk = wasi_sdk_path.nil?
65
- @need_fetch_binaryen = @wasm_opt_path.nil?
66
-
67
68
  if @need_fetch_wasi_sdk
68
69
  if build_dir.nil?
69
70
  raise "build_dir is required when WASI_SDK_PATH is not set"
70
71
  end
71
- wasi_sdk_path = File.join(build_dir, "toolchain", "wasi-sdk")
72
- @version_major = version_major
73
- @version_minor = version_minor
74
- end
75
-
76
- if @need_fetch_binaryen
77
- if build_dir.nil?
78
- raise "build_dir is required when wasm-opt not installed in PATH"
72
+ wasi_sdk_path = File.join(build_dir, "toolchain", "wasi-sdk-#{version}")
73
+ if version.nil?
74
+ raise "version is required when WASI_SDK_PATH is not set"
79
75
  end
80
- @binaryen_path = File.join(build_dir, "toolchain", "binaryen")
81
- @binaryen_version = binaryen_version
82
- @wasm_opt_path = File.join(@binaryen_path, "bin", "wasm-opt")
76
+ @version = version
83
77
  end
84
78
 
79
+ @binaryen =
80
+ Binaryen.new(build_dir: build_dir, binaryen_version: binaryen_version)
81
+
85
82
  @tools = {
86
83
  cc: "#{wasi_sdk_path}/bin/clang",
87
84
  cxx: "#{wasi_sdk_path}/bin/clang++",
@@ -101,27 +98,127 @@ module RubyWasm
101
98
  end
102
99
 
103
100
  def wasm_opt
104
- @wasm_opt_path
101
+ @binaryen.wasm_opt
105
102
  end
106
103
 
107
104
  def wasi_sdk_path
108
105
  @wasi_sdk_path
109
106
  end
110
107
 
111
- def download_url(version_major, version_minor)
112
- version = "#{version_major}.#{version_minor}"
108
+ def download_url
109
+ major, _ = @version.split(".").map(&:to_i)
110
+ # @type var assets: Array[[Regexp, Array[String]]]
113
111
  assets = [
114
- [/x86_64-linux/, "wasi-sdk-#{version}-linux.tar.gz"],
115
- [/(arm64e?|x86_64)-darwin/, "wasi-sdk-#{version}-macos.tar.gz"]
112
+ [
113
+ /x86_64-linux/,
114
+ [
115
+ "wasi-sdk-#{@version}-x86_64-linux.tar.gz",
116
+ # For wasi-sdk version < 23.0
117
+ "wasi-sdk-#{@version}-linux.tar.gz"
118
+ ]
119
+ ],
120
+ [
121
+ /arm64e?-darwin/,
122
+ [
123
+ "wasi-sdk-#{@version}-arm64-macos.tar.gz",
124
+ # For wasi-sdk version < 23.0
125
+ "wasi-sdk-#{@version}-macos.tar.gz"
126
+ ]
127
+ ],
128
+ [
129
+ /x86_64-darwin/,
130
+ [
131
+ "wasi-sdk-#{@version}-x86_64-macos.tar.gz",
132
+ # For wasi-sdk version < 23.0
133
+ "wasi-sdk-#{@version}-macos.tar.gz"
134
+ ]
135
+ ]
116
136
  ]
117
- asset = assets.find { |os, _| os =~ RUBY_PLATFORM }&.at(1)
137
+ asset = assets.find { |os, candidates| os =~ RUBY_PLATFORM }
118
138
  if asset.nil?
119
139
  raise "unsupported platform for fetching WASI SDK: #{RUBY_PLATFORM}"
120
140
  end
121
- "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-#{version_major}/#{asset}"
141
+ _, candidates = asset
142
+ candidates_urls =
143
+ candidates.map do |candidate|
144
+ "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-#{major}/#{candidate}"
145
+ end
146
+ require "net/http"
147
+ # Find an asset that exists by checking HEAD response to see if the asset exists
148
+ candidates_urls.each do |url_str|
149
+ # @type var url: URI::HTTPS
150
+ url = URI.parse(url_str)
151
+ ok =
152
+ __skip__ = Net::HTTP.start(
153
+ url.host,
154
+ url.port,
155
+ use_ssl: url.scheme == "https"
156
+ ) do |http|
157
+ response = http.head(url.request_uri)
158
+ next response.code == "302"
159
+ end
160
+ return url_str if ok
161
+ end
162
+ raise "WASI SDK asset not found: #{candidates_urls.join(", ")}"
163
+ end
164
+
165
+ def install_wasi_sdk(executor)
166
+ return unless @need_fetch_wasi_sdk
167
+ wasi_sdk_tarball =
168
+ File.join(File.dirname(@wasi_sdk_path), "wasi-sdk-#{@version}.tar.gz")
169
+ unless File.exist? wasi_sdk_tarball
170
+ FileUtils.mkdir_p File.dirname(wasi_sdk_tarball)
171
+ executor.system "curl",
172
+ "-fsSL",
173
+ "-o",
174
+ wasi_sdk_tarball,
175
+ self.download_url
176
+ end
177
+ unless File.exist? @wasi_sdk_path
178
+ FileUtils.mkdir_p @wasi_sdk_path
179
+ executor.system "tar",
180
+ "-C",
181
+ @wasi_sdk_path,
182
+ "--strip-component",
183
+ "1",
184
+ "-xzf",
185
+ wasi_sdk_tarball
186
+ end
187
+ end
188
+
189
+ def install(executor)
190
+ install_wasi_sdk(executor)
191
+ @binaryen.install(executor)
192
+ end
193
+ end
194
+
195
+ class Binaryen
196
+ def initialize(build_dir: nil, binaryen_version: 108)
197
+ @wasm_opt_path = Toolchain.find_path("wasm-opt")
198
+ @need_fetch_binaryen = @wasm_opt_path.nil?
199
+ if @need_fetch_binaryen
200
+ if build_dir.nil?
201
+ raise "build_dir is required when wasm-opt not installed in PATH"
202
+ end
203
+ @binaryen_path = File.join(build_dir, "toolchain", "binaryen")
204
+ @binaryen_version = binaryen_version
205
+ @wasm_opt_path = File.join(@binaryen_path, "bin", "wasm-opt")
206
+ end
207
+ end
208
+
209
+ def wasm_opt
210
+ @wasm_opt_path
122
211
  end
123
212
 
124
- def binaryen_download_url(version)
213
+ def binaryen_path
214
+ @binaryen_path
215
+ end
216
+
217
+ def binaryen_version
218
+ @binaryen_version
219
+ end
220
+
221
+ def download_url(version)
125
222
  assets = [
126
223
  [
127
224
  /x86_64-linux/,
@@ -143,47 +240,44 @@ module RubyWasm
143
240
  "https://github.com/WebAssembly/binaryen/releases/download/version_#{@binaryen_version}/#{asset}"
144
241
  end
145
242
 
146
- def install_wasi_sdk
147
- return unless @need_fetch_wasi_sdk
148
- wasi_sdk_tarball =
149
- File.join(File.dirname(@wasi_sdk_path), "wasi-sdk.tar.gz")
150
- unless File.exist? wasi_sdk_tarball
151
- FileUtils.mkdir_p File.dirname(wasi_sdk_tarball)
152
- system "curl -L -o #{wasi_sdk_tarball} #{self.download_url(@version_major, @version_minor)}"
153
- end
154
- unless File.exist? @wasi_sdk_path
155
- FileUtils.mkdir_p @wasi_sdk_path
156
- system "tar -C #{@wasi_sdk_path} --strip-component 1 -xzf #{wasi_sdk_tarball}"
157
- end
158
- end
159
-
160
- def install_binaryen
243
+ def install(executor)
161
244
  return unless @need_fetch_binaryen
162
245
  binaryen_tarball = File.expand_path("../binaryen.tar.gz", @binaryen_path)
163
246
  unless File.exist? binaryen_tarball
164
247
  FileUtils.mkdir_p File.dirname(binaryen_tarball)
165
- system "curl -L -o #{binaryen_tarball} #{self.binaryen_download_url(@binaryen_version)}"
248
+ executor.system "curl",
249
+ "-L",
250
+ "-o",
251
+ binaryen_tarball,
252
+ self.download_url(@binaryen_version)
166
253
  end
167
254
 
168
255
  unless File.exist? @binaryen_path
169
256
  FileUtils.mkdir_p @binaryen_path
170
- system "tar -C #{@binaryen_path} --strip-component 1 -xzf #{binaryen_tarball}"
257
+ executor.system "tar",
258
+ "-C",
259
+ @binaryen_path,
260
+ "--strip-component",
261
+ "1",
262
+ "-xzf",
263
+ binaryen_tarball
171
264
  end
172
265
  end
173
-
174
- def install
175
- install_wasi_sdk
176
- install_binaryen
177
- end
178
266
  end
179
267
 
180
268
  class Emscripten < Toolchain
181
269
  def initialize
182
- @tools = { cc: "emcc", cxx: "em++", ld: "emcc", ar: "emar", ranlib: "emranlib" }
270
+ @tools = {
271
+ cc: "emcc",
272
+ cxx: "em++",
273
+ ld: "emcc",
274
+ ar: "emar",
275
+ ranlib: "emranlib"
276
+ }
183
277
  @name = "emscripten"
184
278
  end
185
279
 
186
- def install
280
+ def install(executor)
187
281
  end
188
282
 
189
283
  def find_tool(name)
@@ -43,7 +43,7 @@ class RubyWasm::Build
43
43
  @target = target
44
44
  @build_dir = build_dir
45
45
  @rubies_dir = rubies_dir
46
- @toolchain = (toolchain || RubyWasm::Toolchain.get(target, @build_dir))
46
+ @toolchain = toolchain || raise("toolchain is required")
47
47
 
48
48
  @libyaml = RubyWasm::LibYAMLProduct.new(@build_dir, @target, @toolchain)
49
49
  @zlib = RubyWasm::ZlibProduct.new(@build_dir, @target, @toolchain)