ruby_wasm 2.6.0-x86_64-linux-musl → 2.6.2-x86_64-linux-musl
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +4 -2
- data/README.md +1 -1
- data/Rakefile +3 -2
- data/docs/cheat_sheet.md +8 -8
- data/ext/ruby_wasm/README.md +3 -0
- data/lib/ruby_wasm/3.1/ruby_wasm.so +0 -0
- data/lib/ruby_wasm/3.2/ruby_wasm.so +0 -0
- data/lib/ruby_wasm/3.3/ruby_wasm.so +0 -0
- data/lib/ruby_wasm/build/product/crossruby.rb +10 -7
- data/lib/ruby_wasm/build/toolchain/wit_bindgen.rb +1 -1
- data/lib/ruby_wasm/build/toolchain.rb +1 -1
- data/lib/ruby_wasm/cli.rb +17 -3
- data/lib/ruby_wasm/packager/core.rb +88 -52
- data/lib/ruby_wasm/packager/file_system.rb +17 -0
- data/lib/ruby_wasm/packager.rb +27 -4
- data/lib/ruby_wasm/version.rb +1 -1
- data/package-lock.json +841 -386
- data/package.json +3 -2
- data/rakelib/packaging.rake +4 -3
- data/sig/ruby_wasm/build.rbs +2 -1
- data/sig/ruby_wasm/cli.rbs +2 -0
- data/sig/ruby_wasm/ext.rbs +8 -0
- data/sig/ruby_wasm/packager.rbs +11 -5
- metadata +4 -5
- data/ext/.gitignore +0 -2
- data/ext/README.md +0 -11
- /data/{ext → lib/ruby_wasm/build/product/crossruby}/extinit.c.erb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 600f38b1685c5427dc537c287f3fb6d17944613758b5451ea46110318d681500
|
4
|
+
data.tar.gz: 880db754bb7abf5744ef2adbcfa7f4bb6af06eb8be610e7e7781a7f15a648b54
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2614e52c087fc8e9927917e40bcfce57cd2d3117ebfb8657af7e993d08084e5614e6e0d61bdc601f3a644f9ef725e79a2f44944efb1daa1431700c24f859cd59
|
7
|
+
data.tar.gz: 74c712f53ed169c9173e7ffd5efd0207c6f933c82e3ceaf2b5f9a0f0d5ca0b20fa15e7584e213c319a79075de737075cefcffb7754584ad549728d216cff549f
|
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.
|
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.
|
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.
|
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.
|
55
|
-
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.6.
|
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.
|
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.
|
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.
|
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.
|
147
|
-
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.6.
|
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
|
|
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
|
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
|
-
|
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
|
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[:
|
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
|
-
|
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.
|
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, :
|
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
|
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
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
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
|
109
|
+
def build_gem_exts(executor, gem_home)
|
97
110
|
build = derive_build
|
98
|
-
self.
|
99
|
-
|
111
|
+
self.with_unbundled_env do
|
112
|
+
self._build_gem_exts(executor, build, gem_home)
|
113
|
+
end
|
100
114
|
end
|
101
115
|
|
102
|
-
def
|
103
|
-
|
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
|
-
|
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(
|
141
|
+
wasi_adapter = RubyWasm::Packager::ComponentAdapter.wasi_snapshot_preview1(wasi_exec_model)
|
123
142
|
adapters = [wasi_adapter]
|
124
|
-
dl_openable_libs =
|
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(
|
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 |
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
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
|
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
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
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
|
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(
|
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(
|
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}"
|
data/lib/ruby_wasm/packager.rb
CHANGED
@@ -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
|
-
|
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.
|
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
|
|
data/lib/ruby_wasm/version.rb
CHANGED