ruby_wasm 2.5.0-x64-mingw-ucrt → 2.5.2-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 +4 -4
- data/CONTRIBUTING.md +9 -7
- data/Gemfile +1 -1
- data/README.md +12 -11
- data/Rakefile +9 -7
- data/docs/cheat_sheet.md +8 -8
- 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/executor.rb +4 -0
- data/lib/ruby_wasm/build/product/crossruby.rb +59 -25
- data/lib/ruby_wasm/build/product/libyaml.rb +5 -3
- data/lib/ruby_wasm/build/product/openssl.rb +7 -2
- data/lib/ruby_wasm/build/product/product.rb +3 -3
- data/lib/ruby_wasm/build/product/ruby_source.rb +3 -3
- data/lib/ruby_wasm/build/product/wasi_vfs.rb +1 -1
- data/lib/ruby_wasm/build/product/zlib.rb +3 -1
- data/lib/ruby_wasm/build/target.rb +24 -0
- data/lib/ruby_wasm/build/toolchain/wit_bindgen.rb +2 -2
- data/lib/ruby_wasm/build/toolchain.rb +1 -1
- data/lib/ruby_wasm/build.rb +7 -3
- data/lib/ruby_wasm/cli.rb +147 -11
- data/lib/ruby_wasm/feature_set.rb +30 -0
- data/lib/ruby_wasm/packager/component_adapter/wasi_snapshot_preview1.command.wasm +0 -0
- data/lib/ruby_wasm/packager/component_adapter/wasi_snapshot_preview1.reactor.wasm +0 -0
- data/lib/ruby_wasm/packager/component_adapter.rb +14 -0
- data/lib/ruby_wasm/packager/core.rb +199 -5
- data/lib/ruby_wasm/packager/file_system.rb +5 -3
- data/lib/ruby_wasm/packager.rb +22 -82
- data/lib/ruby_wasm/rake_task.rb +1 -0
- data/lib/ruby_wasm/version.rb +1 -1
- data/lib/ruby_wasm.rb +2 -0
- data/package-lock.json +5571 -7015
- data/package.json +3 -3
- data/rakelib/check.rake +23 -10
- data/rakelib/ci.rake +3 -3
- data/rakelib/packaging.rake +44 -15
- data/sig/ruby_wasm/build.rbs +38 -28
- data/sig/ruby_wasm/cli.rbs +27 -3
- data/sig/ruby_wasm/ext.rbs +25 -2
- data/sig/ruby_wasm/feature_set.rbs +12 -0
- data/sig/ruby_wasm/packager.rbs +44 -7
- metadata +10 -7
- data/builders/wasm32-unknown-emscripten/Dockerfile +0 -43
- data/builders/wasm32-unknown-emscripten/entrypoint.sh +0 -7
- data/builders/wasm32-unknown-wasi/Dockerfile +0 -47
- data/builders/wasm32-unknown-wasi/entrypoint.sh +0 -7
data/lib/ruby_wasm/build.rb
CHANGED
@@ -2,6 +2,7 @@ require_relative "build/build_params"
|
|
2
2
|
require_relative "build/product"
|
3
3
|
require_relative "build/toolchain"
|
4
4
|
require_relative "build/executor"
|
5
|
+
require_relative "build/target"
|
5
6
|
|
6
7
|
class RubyWasm::Build
|
7
8
|
# Source to build from.
|
@@ -36,6 +37,7 @@ class RubyWasm::Build
|
|
36
37
|
toolchain:,
|
37
38
|
build_dir:,
|
38
39
|
rubies_dir:,
|
40
|
+
wasi_vfs: :default,
|
39
41
|
**options
|
40
42
|
)
|
41
43
|
@target = target
|
@@ -45,7 +47,7 @@ class RubyWasm::Build
|
|
45
47
|
|
46
48
|
@libyaml = RubyWasm::LibYAMLProduct.new(@build_dir, @target, @toolchain)
|
47
49
|
@zlib = RubyWasm::ZlibProduct.new(@build_dir, @target, @toolchain)
|
48
|
-
@wasi_vfs = RubyWasm::WasiVfsProduct.new(@build_dir)
|
50
|
+
@wasi_vfs = wasi_vfs == :default ? RubyWasm::WasiVfsProduct.new(@build_dir) : wasi_vfs
|
49
51
|
@source = RubyWasm::BuildSource.new(src, @build_dir)
|
50
52
|
@baseruby = RubyWasm::BaseRubyProduct.new(@build_dir, @source)
|
51
53
|
@openssl = RubyWasm::OpenSSLProduct.new(@build_dir, @target, @toolchain)
|
@@ -78,11 +80,13 @@ class RubyWasm::Build
|
|
78
80
|
@crossruby.cache_key(digest)
|
79
81
|
digest << @build_dir
|
80
82
|
digest << @rubies_dir
|
81
|
-
|
83
|
+
@target.cache_key(digest)
|
82
84
|
digest << @toolchain.name
|
83
85
|
digest << @libyaml.name
|
84
86
|
digest << @zlib.name
|
85
87
|
digest << @openssl.name
|
86
|
-
|
88
|
+
if wasi_vfs = @wasi_vfs
|
89
|
+
digest << wasi_vfs.name
|
90
|
+
end
|
87
91
|
end
|
88
92
|
end
|
data/lib/ruby_wasm/cli.rb
CHANGED
@@ -42,7 +42,7 @@ module RubyWasm
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def build(args)
|
45
|
-
# @type var options:
|
45
|
+
# @type var options: cli_options
|
46
46
|
options = {
|
47
47
|
save_temps: false,
|
48
48
|
optimize: false,
|
@@ -50,14 +50,16 @@ module RubyWasm
|
|
50
50
|
reconfigure: false,
|
51
51
|
clean: false,
|
52
52
|
ruby_version: "3.3",
|
53
|
-
target_triplet: "wasm32-unknown-
|
53
|
+
target_triplet: "wasm32-unknown-wasip1",
|
54
54
|
profile: "full",
|
55
55
|
stdlib: true,
|
56
|
-
disable_gems: false
|
56
|
+
disable_gems: false,
|
57
|
+
gemfile: nil,
|
58
|
+
patches: [],
|
57
59
|
}
|
58
60
|
OptionParser
|
59
61
|
.new do |opts|
|
60
|
-
opts.banner = "Usage: rbwasm
|
62
|
+
opts.banner = "Usage: rbwasm build [options]"
|
61
63
|
opts.on("-h", "--help", "Prints this help") do
|
62
64
|
@stdout.puts opts
|
63
65
|
exit
|
@@ -106,6 +108,10 @@ module RubyWasm
|
|
106
108
|
options[:disable_gems] = true
|
107
109
|
end
|
108
110
|
|
111
|
+
opts.on("-p", "--patch PATCH", "Apply a patch") do |patch|
|
112
|
+
options[:patches] << patch
|
113
|
+
end
|
114
|
+
|
109
115
|
opts.on("--format FORMAT", "Output format") do |format|
|
110
116
|
options[:format] = format
|
111
117
|
end
|
@@ -116,8 +122,19 @@ module RubyWasm
|
|
116
122
|
end
|
117
123
|
.parse!(args)
|
118
124
|
|
125
|
+
__skip__ = if defined?(Bundler)
|
126
|
+
Bundler.settings.temporary(force_ruby_platform: true) do
|
127
|
+
do_build_with_force_ruby_platform(options)
|
128
|
+
end
|
129
|
+
else
|
130
|
+
do_build_with_force_ruby_platform(options)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def do_build_with_force_ruby_platform(options)
|
119
135
|
verbose = RubyWasm.logger.level == :debug
|
120
136
|
executor = RubyWasm::BuildExecutor.new(verbose: verbose)
|
137
|
+
|
121
138
|
packager = self.derive_packager(options)
|
122
139
|
|
123
140
|
if options[:print_ruby_cache_key]
|
@@ -152,10 +169,12 @@ module RubyWasm
|
|
152
169
|
private
|
153
170
|
|
154
171
|
def build_config(options)
|
155
|
-
|
172
|
+
build_source, all_default_exts = compute_build_source(options)
|
173
|
+
# @type var config: Packager::build_config
|
174
|
+
config = { target: options[:target_triplet], src: build_source }
|
156
175
|
case options[:profile]
|
157
176
|
when "full"
|
158
|
-
config[:default_exts] =
|
177
|
+
config[:default_exts] = all_default_exts || ""
|
159
178
|
env_additional_exts = ENV["RUBY_WASM_ADDITIONAL_EXTS"] || ""
|
160
179
|
unless env_additional_exts.empty?
|
161
180
|
config[:default_exts] += "," + env_additional_exts
|
@@ -170,12 +189,129 @@ module RubyWasm
|
|
170
189
|
config
|
171
190
|
end
|
172
191
|
|
173
|
-
def
|
192
|
+
def compute_build_source(options)
|
193
|
+
src_name = options[:ruby_version]
|
194
|
+
aliases = self.class.build_source_aliases(root)
|
195
|
+
source = aliases[src_name]
|
196
|
+
if source.nil?
|
197
|
+
if File.directory?(src_name)
|
198
|
+
# Treat as a local source if the given name is a source directory.
|
199
|
+
RubyWasm.logger.debug "Using local source: #{src_name}"
|
200
|
+
if options[:patches].any?
|
201
|
+
RubyWasm.logger.warn "Patches specified through --patch are ignored for local sources"
|
202
|
+
end
|
203
|
+
# @type var local_source: RubyWasm::Packager::build_source_local
|
204
|
+
local_source = { type: "local", path: src_name }
|
205
|
+
# @type var local_source: RubyWasm::Packager::build_source
|
206
|
+
local_source = local_source.merge(name: "local", patches: [])
|
207
|
+
return [local_source, nil]
|
208
|
+
end
|
209
|
+
# Otherwise, it's an unknown source.
|
210
|
+
raise(
|
211
|
+
"Unknown Ruby source: #{src_name} (available: #{aliases.keys.join(", ")} or a local directory)"
|
212
|
+
)
|
213
|
+
end
|
214
|
+
# Apply user-specified patches in addition to bundled patches.
|
215
|
+
source[:patches].concat(options[:patches])
|
216
|
+
# @type var all_default_exts: String
|
217
|
+
__skip__ = all_default_exts = source[:all_default_exts]
|
218
|
+
[source, all_default_exts]
|
219
|
+
end
|
220
|
+
|
221
|
+
# Retrieves the alias definitions for the Ruby sources.
|
222
|
+
def self.build_source_aliases(root)
|
223
|
+
# @type var sources: Hash[string, RubyWasm::Packager::build_source]
|
224
|
+
sources = {
|
225
|
+
"head" => {
|
226
|
+
type: "github",
|
227
|
+
repo: "ruby/ruby",
|
228
|
+
rev: "master",
|
229
|
+
all_default_exts: RubyWasm::Packager::ALL_DEFAULT_EXTS,
|
230
|
+
},
|
231
|
+
"3.3" => {
|
232
|
+
type: "tarball",
|
233
|
+
url: "https://cache.ruby-lang.org/pub/ruby/3.3/ruby-3.3.1.tar.gz",
|
234
|
+
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
|
+
},
|
236
|
+
"3.2" => {
|
237
|
+
type: "tarball",
|
238
|
+
url: "https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.4.tar.gz",
|
239
|
+
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",
|
240
|
+
}
|
241
|
+
}
|
242
|
+
|
243
|
+
# Apply bundled and user-specified `<root>/patches` directories.
|
244
|
+
sources.each do |name, source|
|
245
|
+
source[:name] = name
|
246
|
+
patches_dirs = [bundled_patches_path, File.join(root, "patches")]
|
247
|
+
source[:patches] = patches_dirs.flat_map do |patches_dir|
|
248
|
+
Dir[File.join(patches_dir, name, "*.patch")]
|
249
|
+
.map { |p| File.expand_path(p) }
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
build_manifest = File.join(root, "build_manifest.json")
|
254
|
+
if File.exist?(build_manifest)
|
255
|
+
begin
|
256
|
+
manifest = JSON.parse(File.read(build_manifest))
|
257
|
+
manifest["ruby_revisions"].each do |name, rev|
|
258
|
+
source = sources[name]
|
259
|
+
next unless source[:type] == "github"
|
260
|
+
# @type var source: RubyWasm::Packager::build_source_github
|
261
|
+
source[:rev] = rev
|
262
|
+
end
|
263
|
+
rescue StandardError => e
|
264
|
+
RubyWasm.logger.warn "Failed to load build_manifest.json: #{e}"
|
265
|
+
end
|
266
|
+
end
|
267
|
+
sources
|
268
|
+
end
|
269
|
+
|
270
|
+
# Retrieves the root directory of the Ruby project.
|
271
|
+
def root
|
174
272
|
__skip__ =
|
175
|
-
|
273
|
+
@root ||=
|
274
|
+
begin
|
275
|
+
if explicit = ENV["RUBY_WASM_ROOT"]
|
276
|
+
File.expand_path(explicit)
|
277
|
+
elsif defined?(Bundler)
|
278
|
+
Bundler.root
|
279
|
+
else
|
280
|
+
Dir.pwd
|
281
|
+
end
|
282
|
+
rescue Bundler::GemfileNotFound
|
283
|
+
Dir.pwd
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
# Path to the directory containing the bundled patches, which is shipped
|
288
|
+
# as part of ruby_wasm gem to backport fixes or try experimental features
|
289
|
+
# before landing them to the ruby/ruby repository.
|
290
|
+
def self.bundled_patches_path
|
291
|
+
dir = __dir__
|
292
|
+
raise "Unexpected directory structure, no __dir__!??" unless dir
|
293
|
+
lib_source_root = File.join(dir, "..", "..")
|
294
|
+
File.join(lib_source_root, "patches")
|
295
|
+
end
|
296
|
+
|
297
|
+
def derive_packager(options)
|
298
|
+
__skip__ = definition = nil
|
299
|
+
__skip__ = if defined?(Bundler) && !options[:disable_gems]
|
300
|
+
begin
|
301
|
+
# Silence Bundler UI if --print-ruby-cache-key is specified not to bother the JSON output.
|
302
|
+
level = options[:print_ruby_cache_key] ? :silent : Bundler.ui.level
|
303
|
+
old_level = Bundler.ui.level
|
304
|
+
Bundler.ui.level = level
|
176
305
|
definition = Bundler.definition
|
306
|
+
ensure
|
307
|
+
Bundler.ui.level = old_level
|
177
308
|
end
|
178
|
-
|
309
|
+
end
|
310
|
+
RubyWasm.logger.info "Using Gemfile: #{definition.gemfiles}" if definition
|
311
|
+
RubyWasm::Packager.new(
|
312
|
+
root, build_config(options), definition,
|
313
|
+
features: RubyWasm::FeatureSet.derive_from_env
|
314
|
+
)
|
179
315
|
end
|
180
316
|
|
181
317
|
def do_print_ruby_cache_key(packager)
|
@@ -197,9 +333,9 @@ module RubyWasm
|
|
197
333
|
RubyWasm.logger.info "Size: #{SizeFormatter.format(wasm_bytes.size)}"
|
198
334
|
case options[:output]
|
199
335
|
when "-"
|
200
|
-
@stdout.write wasm_bytes
|
336
|
+
@stdout.write wasm_bytes
|
201
337
|
else
|
202
|
-
File.binwrite(options[:output], wasm_bytes
|
338
|
+
File.binwrite(options[:output], wasm_bytes)
|
203
339
|
RubyWasm.logger.debug "Wrote #{options[:output]}"
|
204
340
|
end
|
205
341
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
##
|
2
|
+
# A set of feature flags that can be used to enable or disable experimental features.
|
3
|
+
class RubyWasm::FeatureSet
|
4
|
+
def initialize(features)
|
5
|
+
@features = features
|
6
|
+
end
|
7
|
+
|
8
|
+
# Maps the feature to the environment variable.
|
9
|
+
FEATURES = {
|
10
|
+
dynamic_linking: "RUBY_WASM_EXPERIMENTAL_DYNAMIC_LINKING",
|
11
|
+
component_model: "RUBY_WASM_EXPERIMENTAL_COMPONENT_MODEL",
|
12
|
+
}.freeze
|
13
|
+
private_constant :FEATURES
|
14
|
+
|
15
|
+
# Derives the feature set from the environment variables. A feature
|
16
|
+
# is enabled if the corresponding environment variable is set to "1",
|
17
|
+
# otherwise it is disabled.
|
18
|
+
def self.derive_from_env
|
19
|
+
values = FEATURES.transform_values { |key| ENV[key] == "1" }
|
20
|
+
new(values)
|
21
|
+
end
|
22
|
+
|
23
|
+
def support_dynamic_linking?
|
24
|
+
@features[:dynamic_linking]
|
25
|
+
end
|
26
|
+
|
27
|
+
def support_component_model?
|
28
|
+
@features[:component_model] || @features[:dynamic_linking]
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module RubyWasm::Packager::ComponentAdapter
|
2
|
+
module_function
|
3
|
+
|
4
|
+
# The path to the component adapter for the given WASI execution model.
|
5
|
+
#
|
6
|
+
# @param exec_model [String] "command" or "reactor"
|
7
|
+
def wasi_snapshot_preview1(exec_model)
|
8
|
+
File.join(
|
9
|
+
File.dirname(__FILE__),
|
10
|
+
"component_adapter",
|
11
|
+
"wasi_snapshot_preview1.#{exec_model}.wasm"
|
12
|
+
)
|
13
|
+
end
|
14
|
+
end
|
@@ -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_and_link_exts
|
16
16
|
|
17
17
|
private
|
18
18
|
|
@@ -20,7 +20,7 @@ class RubyWasm::Packager::Core
|
|
20
20
|
@build_strategy ||=
|
21
21
|
begin
|
22
22
|
has_exts = @packager.specs.any? { |spec| spec.extensions.any? }
|
23
|
-
if @packager.support_dynamic_linking?
|
23
|
+
if @packager.features.support_dynamic_linking?
|
24
24
|
DynamicLinking.new(@packager)
|
25
25
|
else
|
26
26
|
StaticLinking.new(@packager)
|
@@ -37,6 +37,10 @@ class RubyWasm::Packager::Core
|
|
37
37
|
raise NotImplementedError
|
38
38
|
end
|
39
39
|
|
40
|
+
def build_and_link_exts(executor, module_bytes)
|
41
|
+
raise NotImplementedError
|
42
|
+
end
|
43
|
+
|
40
44
|
# Array of paths to extconf.rb files.
|
41
45
|
def specs_with_extensions
|
42
46
|
@packager.specs.filter_map do |spec|
|
@@ -61,6 +65,168 @@ class RubyWasm::Packager::Core
|
|
61
65
|
end
|
62
66
|
|
63
67
|
class DynamicLinking < BuildStrategy
|
68
|
+
def build(executor, options)
|
69
|
+
build = derive_build
|
70
|
+
force_rebuild =
|
71
|
+
options[:remake] || options[:clean] || options[:reconfigure]
|
72
|
+
if File.exist?(build.crossruby.artifact) && !force_rebuild
|
73
|
+
# Always build extensions because they are usually not expensive to build
|
74
|
+
return build.crossruby.artifact
|
75
|
+
end
|
76
|
+
build.crossruby.clean(executor) if options[:clean]
|
77
|
+
|
78
|
+
do_build =
|
79
|
+
proc do
|
80
|
+
build.crossruby.build(
|
81
|
+
executor,
|
82
|
+
remake: options[:remake],
|
83
|
+
reconfigure: options[:reconfigure]
|
84
|
+
)
|
85
|
+
end
|
86
|
+
|
87
|
+
__skip__ =
|
88
|
+
if defined?(Bundler)
|
89
|
+
Bundler.with_unbundled_env(&do_build)
|
90
|
+
else
|
91
|
+
do_build.call
|
92
|
+
end
|
93
|
+
build.crossruby.artifact
|
94
|
+
end
|
95
|
+
|
96
|
+
def build_and_link_exts(executor, module_bytes)
|
97
|
+
build = derive_build
|
98
|
+
self.build_exts(executor, build)
|
99
|
+
self.link_exts(executor, build)
|
100
|
+
end
|
101
|
+
|
102
|
+
def link_exts(executor, build)
|
103
|
+
ruby_root = build.crossruby.dest_dir
|
104
|
+
|
105
|
+
libraries = [File.join(ruby_root, "usr", "local", "bin", "ruby")]
|
106
|
+
|
107
|
+
# TODO: Should be computed from dyinfo of ruby binary
|
108
|
+
wasi_libc_shared_libs = [
|
109
|
+
"libc.so",
|
110
|
+
"libwasi-emulated-getpid.so",
|
111
|
+
"libwasi-emulated-mman.so",
|
112
|
+
"libwasi-emulated-process-clocks.so",
|
113
|
+
"libwasi-emulated-signal.so",
|
114
|
+
]
|
115
|
+
|
116
|
+
wasi_libc_shared_libs.each do |lib|
|
117
|
+
# @type var toolchain: RubyWasm::WASISDK
|
118
|
+
toolchain = build.toolchain
|
119
|
+
wasi_sdk_path = toolchain.wasi_sdk_path
|
120
|
+
libraries << File.join(wasi_sdk_path, "share/wasi-sysroot/lib/wasm32-wasi", lib)
|
121
|
+
end
|
122
|
+
wasi_adapter = RubyWasm::Packager::ComponentAdapter.wasi_snapshot_preview1("command")
|
123
|
+
adapters = [wasi_adapter]
|
124
|
+
dl_openable_libs = Dir.glob(File.join(ruby_root, "usr", "local", "lib", "ruby", "**", "*.so"))
|
125
|
+
linker = RubyWasmExt::ComponentLink.new
|
126
|
+
linker.use_built_in_libdl(true)
|
127
|
+
linker.stub_missing_functions(false)
|
128
|
+
linker.validate(true)
|
129
|
+
|
130
|
+
libraries.each do |lib|
|
131
|
+
# Non-DL openable libraries should be referenced as base name
|
132
|
+
lib_name = File.basename(lib)
|
133
|
+
module_bytes = File.binread(lib)
|
134
|
+
RubyWasm.logger.info "Linking #{lib_name} (#{module_bytes.size} bytes)"
|
135
|
+
linker.library(lib_name, module_bytes, false)
|
136
|
+
end
|
137
|
+
|
138
|
+
dl_openable_libs.each do |lib|
|
139
|
+
# DL openable lib_name should be a relative path from ruby_root
|
140
|
+
lib_name = "/" + Pathname.new(lib).relative_path_from(Pathname.new(ruby_root)).to_s
|
141
|
+
module_bytes = File.binread(lib)
|
142
|
+
RubyWasm.logger.info "Linking #{lib_name} (#{module_bytes.size} bytes)"
|
143
|
+
linker.library(lib_name, module_bytes, true)
|
144
|
+
end
|
145
|
+
|
146
|
+
adapters.each do |adapter|
|
147
|
+
adapter_name = File.basename(adapter)
|
148
|
+
# e.g. wasi_snapshot_preview1.command.wasm -> wasi_snapshot_preview1
|
149
|
+
adapter_name = adapter_name.split(".")[0]
|
150
|
+
module_bytes = File.binread(adapter)
|
151
|
+
linker.adapter(adapter_name, module_bytes)
|
152
|
+
end
|
153
|
+
return linker.encode()
|
154
|
+
end
|
155
|
+
|
156
|
+
def build_exts(executor, build)
|
157
|
+
exts = specs_with_extensions.flat_map do |spec, exts|
|
158
|
+
exts.map do |ext|
|
159
|
+
ext_feature = File.dirname(ext) # e.g. "ext/cgi/escape"
|
160
|
+
ext_srcdir = File.join(spec.full_gem_path, ext_feature)
|
161
|
+
ext_relative_path = File.join(spec.full_name, ext_feature)
|
162
|
+
RubyWasm::CrossRubyExtProduct.new(
|
163
|
+
ext_srcdir,
|
164
|
+
build.toolchain,
|
165
|
+
features: @packager.features,
|
166
|
+
ext_relative_path: ext_relative_path
|
167
|
+
)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
exts.each do |prod|
|
172
|
+
executor.begin_section prod.class, prod.name, "Building"
|
173
|
+
prod.build(executor, build.crossruby)
|
174
|
+
executor.end_section prod.class, prod.name
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def cache_key(digest)
|
179
|
+
derive_build.cache_key(digest)
|
180
|
+
end
|
181
|
+
|
182
|
+
def artifact
|
183
|
+
derive_build.crossruby.artifact
|
184
|
+
end
|
185
|
+
|
186
|
+
def target
|
187
|
+
RubyWasm::Target.new(@packager.full_build_options[:target], pic: true)
|
188
|
+
end
|
189
|
+
|
190
|
+
def derive_build
|
191
|
+
return @build if @build
|
192
|
+
__skip__ =
|
193
|
+
build ||= RubyWasm::Build.new(
|
194
|
+
name, **@packager.full_build_options,
|
195
|
+
target: target,
|
196
|
+
# NOTE: We don't need linking libwasi_vfs because we use wasi-virt instead.
|
197
|
+
wasi_vfs: nil
|
198
|
+
)
|
199
|
+
build.crossruby.cflags = %w[-fPIC -fvisibility=default]
|
200
|
+
if @packager.full_build_options[:target] != "wasm32-unknown-emscripten"
|
201
|
+
build.crossruby.debugflags = %w[-g]
|
202
|
+
build.crossruby.wasmoptflags = %w[-O3 -g --pass-arg=asyncify-relocatable]
|
203
|
+
build.crossruby.ldflags = %w[
|
204
|
+
-Xlinker
|
205
|
+
--stack-first
|
206
|
+
-Xlinker
|
207
|
+
-z
|
208
|
+
-Xlinker
|
209
|
+
stack-size=16777216
|
210
|
+
]
|
211
|
+
build.crossruby.xldflags = %w[
|
212
|
+
-Xlinker -shared
|
213
|
+
-Xlinker --export-dynamic
|
214
|
+
-Xlinker --export-all
|
215
|
+
-Xlinker --experimental-pic
|
216
|
+
-Xlinker -export-if-defined=__main_argc_argv
|
217
|
+
]
|
218
|
+
end
|
219
|
+
@build = build
|
220
|
+
build
|
221
|
+
end
|
222
|
+
|
223
|
+
def name
|
224
|
+
require "digest"
|
225
|
+
options = @packager.full_build_options
|
226
|
+
src_channel = options[:src][:name]
|
227
|
+
target_triplet = options[:target]
|
228
|
+
"ruby-#{src_channel}-#{target_triplet}-pic#{options[:suffix]}"
|
229
|
+
end
|
64
230
|
end
|
65
231
|
|
66
232
|
class StaticLinking < BuildStrategy
|
@@ -93,16 +259,24 @@ class RubyWasm::Packager::Core
|
|
93
259
|
|
94
260
|
def cache_key(digest)
|
95
261
|
derive_build.cache_key(digest)
|
262
|
+
if enabled = @packager.features.support_component_model?
|
263
|
+
digest << enabled.to_s
|
264
|
+
end
|
96
265
|
end
|
97
266
|
|
98
267
|
def artifact
|
99
268
|
derive_build.crossruby.artifact
|
100
269
|
end
|
101
270
|
|
271
|
+
def target
|
272
|
+
RubyWasm::Target.new(@packager.full_build_options[:target])
|
273
|
+
end
|
274
|
+
|
102
275
|
def derive_build
|
103
276
|
return @build if @build
|
104
|
-
__skip__ =
|
105
|
-
|
277
|
+
__skip__ = build ||= RubyWasm::Build.new(
|
278
|
+
name, **@packager.full_build_options, target: target,
|
279
|
+
)
|
106
280
|
build.crossruby.user_exts = user_exts(build)
|
107
281
|
# Emscripten uses --global-base=1024 by default, but it conflicts with
|
108
282
|
# --stack-first and -z stack-size since global-base 1024 is smaller than
|
@@ -111,7 +285,9 @@ class RubyWasm::Packager::Core
|
|
111
285
|
# script of Ruby.
|
112
286
|
if @packager.full_build_options[:target] != "wasm32-unknown-emscripten"
|
113
287
|
build.crossruby.debugflags = %w[-g]
|
114
|
-
|
288
|
+
# We assume that imported functions provided through WASI will not change
|
289
|
+
# asyncify state, so we ignore them.
|
290
|
+
build.crossruby.wasmoptflags = %w[-O3 -g --pass-arg=asyncify-ignore-imports]
|
115
291
|
build.crossruby.ldflags = %w[
|
116
292
|
-Xlinker
|
117
293
|
--stack-first
|
@@ -125,6 +301,20 @@ class RubyWasm::Packager::Core
|
|
125
301
|
build
|
126
302
|
end
|
127
303
|
|
304
|
+
def build_and_link_exts(executor, module_bytes)
|
305
|
+
return module_bytes unless @packager.features.support_component_model?
|
306
|
+
|
307
|
+
linker = RubyWasmExt::ComponentEncode.new
|
308
|
+
linker.validate(true)
|
309
|
+
linker.module(module_bytes)
|
310
|
+
linker.adapter(
|
311
|
+
"wasi_snapshot_preview1",
|
312
|
+
File.binread(RubyWasm::Packager::ComponentAdapter.wasi_snapshot_preview1("reactor"))
|
313
|
+
)
|
314
|
+
|
315
|
+
linker.encode()
|
316
|
+
end
|
317
|
+
|
128
318
|
def user_exts(build)
|
129
319
|
@user_exts ||=
|
130
320
|
specs_with_extensions.flat_map do |spec, exts|
|
@@ -135,6 +325,7 @@ class RubyWasm::Packager::Core
|
|
135
325
|
RubyWasm::CrossRubyExtProduct.new(
|
136
326
|
ext_srcdir,
|
137
327
|
build.toolchain,
|
328
|
+
features: @packager.features,
|
138
329
|
ext_relative_path: ext_relative_path
|
139
330
|
)
|
140
331
|
end
|
@@ -150,6 +341,9 @@ class RubyWasm::Packager::Core
|
|
150
341
|
exts = specs_with_extensions.sort
|
151
342
|
hash = ::Digest::MD5.new
|
152
343
|
specs_with_extensions.each { |spec, _| hash << spec.full_name }
|
344
|
+
if enabled = @packager.features.support_component_model?
|
345
|
+
hash << enabled.to_s
|
346
|
+
end
|
153
347
|
exts.empty? ? base : "#{base}-#{hash.hexdigest}"
|
154
348
|
end
|
155
349
|
end
|
@@ -65,12 +65,14 @@ class RubyWasm::Packager::FileSystem
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def remove_non_runtime_files(executor)
|
68
|
-
%w[
|
69
|
-
**/*.so
|
68
|
+
patterns = %w[
|
70
69
|
usr/local/lib/libruby-static.a
|
71
70
|
usr/local/bin/ruby
|
72
71
|
usr/local/include
|
73
|
-
]
|
72
|
+
]
|
73
|
+
|
74
|
+
patterns << "**/*.so" unless @packager.features.support_dynamic_linking?
|
75
|
+
patterns.each do |pattern|
|
74
76
|
Dir
|
75
77
|
.glob(File.join(@dest_dir, pattern))
|
76
78
|
.each do |entry|
|