ruby_wasm 2.5.0-x64-mingw-ucrt → 2.5.1-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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +9 -7
  3. data/Gemfile +1 -1
  4. data/README.md +10 -9
  5. data/Rakefile +8 -7
  6. data/docs/cheat_sheet.md +8 -8
  7. data/lib/ruby_wasm/3.1/ruby_wasm.so +0 -0
  8. data/lib/ruby_wasm/3.2/ruby_wasm.so +0 -0
  9. data/lib/ruby_wasm/3.3/ruby_wasm.so +0 -0
  10. data/lib/ruby_wasm/build/executor.rb +4 -0
  11. data/lib/ruby_wasm/build/product/crossruby.rb +53 -23
  12. data/lib/ruby_wasm/build/product/libyaml.rb +5 -3
  13. data/lib/ruby_wasm/build/product/openssl.rb +7 -2
  14. data/lib/ruby_wasm/build/product/product.rb +3 -3
  15. data/lib/ruby_wasm/build/product/ruby_source.rb +3 -3
  16. data/lib/ruby_wasm/build/product/wasi_vfs.rb +1 -1
  17. data/lib/ruby_wasm/build/product/zlib.rb +3 -1
  18. data/lib/ruby_wasm/build/target.rb +24 -0
  19. data/lib/ruby_wasm/build/toolchain.rb +1 -1
  20. data/lib/ruby_wasm/build.rb +7 -3
  21. data/lib/ruby_wasm/cli.rb +141 -11
  22. data/lib/ruby_wasm/packager/component_adapter/wasi_snapshot_preview1.command.wasm +0 -0
  23. data/lib/ruby_wasm/packager/component_adapter/wasi_snapshot_preview1.reactor.wasm +0 -0
  24. data/lib/ruby_wasm/packager/component_adapter.rb +14 -0
  25. data/lib/ruby_wasm/packager/core.rb +180 -3
  26. data/lib/ruby_wasm/packager/file_system.rb +5 -3
  27. data/lib/ruby_wasm/packager.rb +18 -81
  28. data/lib/ruby_wasm/rake_task.rb +1 -0
  29. data/lib/ruby_wasm/version.rb +1 -1
  30. data/lib/ruby_wasm.rb +1 -0
  31. data/package-lock.json +410 -133
  32. data/package.json +3 -3
  33. data/rakelib/ci.rake +3 -3
  34. data/rakelib/packaging.rake +26 -12
  35. data/sig/ruby_wasm/build.rbs +36 -27
  36. data/sig/ruby_wasm/cli.rbs +27 -3
  37. data/sig/ruby_wasm/ext.rbs +15 -2
  38. data/sig/ruby_wasm/packager.rbs +37 -6
  39. metadata +8 -7
  40. data/builders/wasm32-unknown-emscripten/Dockerfile +0 -43
  41. data/builders/wasm32-unknown-emscripten/entrypoint.sh +0 -7
  42. data/builders/wasm32-unknown-wasi/Dockerfile +0 -47
  43. data/builders/wasm32-unknown-wasi/entrypoint.sh +0 -7
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: Hash[Symbol, untyped]
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-wasi",
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 componentize [options]"
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,11 @@ module RubyWasm
152
169
  private
153
170
 
154
171
  def build_config(options)
155
- config = { target: options[:target_triplet], src: options[:ruby_version] }
172
+ # @type var config: Packager::build_config
173
+ config = { target: options[:target_triplet], src: compute_build_source(options) }
156
174
  case options[:profile]
157
175
  when "full"
158
- config[:default_exts] = RubyWasm::Packager::ALL_DEFAULT_EXTS
176
+ config[:default_exts] = config[:src][:all_default_exts]
159
177
  env_additional_exts = ENV["RUBY_WASM_ADDITIONAL_EXTS"] || ""
160
178
  unless env_additional_exts.empty?
161
179
  config[:default_exts] += "," + env_additional_exts
@@ -170,12 +188,124 @@ module RubyWasm
170
188
  config
171
189
  end
172
190
 
173
- def derive_packager(options)
191
+ def compute_build_source(options)
192
+ src_name = options[:ruby_version]
193
+ aliases = self.class.build_source_aliases(root)
194
+ source = aliases[src_name]
195
+ if source.nil?
196
+ if File.directory?(src_name)
197
+ # Treat as a local source if the given name is a source directory.
198
+ RubyWasm.logger.debug "Using local source: #{src_name}"
199
+ if options[:patches].any?
200
+ RubyWasm.logger.warn "Patches specified through --patch are ignored for local sources"
201
+ end
202
+ # @type var local_source: RubyWasm::Packager::build_source_local
203
+ local_source = { type: "local", path: src_name }
204
+ # @type var local_source: RubyWasm::Packager::build_source
205
+ local_source = local_source.merge(name: "local", patches: [])
206
+ return local_source
207
+ end
208
+ # Otherwise, it's an unknown source.
209
+ raise(
210
+ "Unknown Ruby source: #{src_name} (available: #{aliases.keys.join(", ")} or a local directory)"
211
+ )
212
+ end
213
+ # Apply user-specified patches in addition to bundled patches.
214
+ source[:patches].concat(options[:patches])
215
+ source
216
+ end
217
+
218
+ # Retrieves the alias definitions for the Ruby sources.
219
+ def self.build_source_aliases(root)
220
+ # @type var sources: Hash[string, RubyWasm::Packager::build_source]
221
+ sources = {
222
+ "head" => {
223
+ type: "github",
224
+ repo: "ruby/ruby",
225
+ rev: "master",
226
+ all_default_exts: RubyWasm::Packager::ALL_DEFAULT_EXTS,
227
+ },
228
+ "3.3" => {
229
+ type: "tarball",
230
+ url: "https://cache.ruby-lang.org/pub/ruby/3.3/ruby-3.3.0.tar.gz",
231
+ 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",
232
+ },
233
+ "3.2" => {
234
+ type: "tarball",
235
+ url: "https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.3.tar.gz",
236
+ 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",
237
+ }
238
+ }
239
+
240
+ # Apply bundled and user-specified `<root>/patches` directories.
241
+ sources.each do |name, source|
242
+ source[:name] = name
243
+ patches_dirs = [bundled_patches_path, File.join(root, "patches")]
244
+ source[:patches] = patches_dirs.flat_map do |patches_dir|
245
+ Dir[File.join(patches_dir, name, "*.patch")]
246
+ .map { |p| File.expand_path(p) }
247
+ end
248
+ end
249
+
250
+ build_manifest = File.join(root, "build_manifest.json")
251
+ if File.exist?(build_manifest)
252
+ begin
253
+ manifest = JSON.parse(File.read(build_manifest))
254
+ manifest["ruby_revisions"].each do |name, rev|
255
+ source = sources[name]
256
+ next unless source[:type] == "github"
257
+ # @type var source: RubyWasm::Packager::build_source_github
258
+ source[:rev] = rev
259
+ end
260
+ rescue StandardError => e
261
+ RubyWasm.logger.warn "Failed to load build_manifest.json: #{e}"
262
+ end
263
+ end
264
+ sources
265
+ end
266
+
267
+ # Retrieves the root directory of the Ruby project.
268
+ def root
174
269
  __skip__ =
175
- if defined?(Bundler) && !options[:disable_gems]
270
+ @root ||=
271
+ begin
272
+ if explicit = ENV["RUBY_WASM_ROOT"]
273
+ File.expand_path(explicit)
274
+ elsif defined?(Bundler)
275
+ Bundler.root
276
+ else
277
+ Dir.pwd
278
+ end
279
+ rescue Bundler::GemfileNotFound
280
+ Dir.pwd
281
+ end
282
+ end
283
+
284
+ # Path to the directory containing the bundled patches, which is shipped
285
+ # as part of ruby_wasm gem to backport fixes or try experimental features
286
+ # before landing them to the ruby/ruby repository.
287
+ def self.bundled_patches_path
288
+ dir = __dir__
289
+ raise "Unexpected directory structure, no __dir__!??" unless dir
290
+ lib_source_root = File.join(dir, "..", "..")
291
+ File.join(lib_source_root, "patches")
292
+ end
293
+
294
+ def derive_packager(options)
295
+ __skip__ = definition = nil
296
+ __skip__ = if defined?(Bundler) && !options[:disable_gems]
297
+ begin
298
+ # Silence Bundler UI if --print-ruby-cache-key is specified not to bother the JSON output.
299
+ level = options[:print_ruby_cache_key] ? :silent : Bundler.ui.level
300
+ old_level = Bundler.ui.level
301
+ Bundler.ui.level = level
176
302
  definition = Bundler.definition
303
+ ensure
304
+ Bundler.ui.level = old_level
177
305
  end
178
- RubyWasm::Packager.new(build_config(options), definition)
306
+ end
307
+ RubyWasm.logger.info "Using Gemfile: #{definition.gemfiles}" if definition
308
+ RubyWasm::Packager.new(root, build_config(options), definition)
179
309
  end
180
310
 
181
311
  def do_print_ruby_cache_key(packager)
@@ -197,9 +327,9 @@ module RubyWasm
197
327
  RubyWasm.logger.info "Size: #{SizeFormatter.format(wasm_bytes.size)}"
198
328
  case options[:output]
199
329
  when "-"
200
- @stdout.write wasm_bytes.pack("C*")
330
+ @stdout.write wasm_bytes
201
331
  else
202
- File.binwrite(options[:output], wasm_bytes.pack("C*"))
332
+ File.binwrite(options[:output], wasm_bytes)
203
333
  RubyWasm.logger.debug "Wrote #{options[:output]}"
204
334
  end
205
335
  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
 
@@ -37,6 +37,10 @@ class RubyWasm::Packager::Core
37
37
  raise NotImplementedError
38
38
  end
39
39
 
40
+ def build_and_link_exts(executor)
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,167 @@ 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)
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
+ ext_relative_path: ext_relative_path
166
+ )
167
+ end
168
+ end
169
+
170
+ exts.each do |prod|
171
+ executor.begin_section prod.class, prod.name, "Building"
172
+ prod.build(executor, build.crossruby)
173
+ executor.end_section prod.class, prod.name
174
+ end
175
+ end
176
+
177
+ def cache_key(digest)
178
+ derive_build.cache_key(digest)
179
+ end
180
+
181
+ def artifact
182
+ derive_build.crossruby.artifact
183
+ end
184
+
185
+ def target
186
+ RubyWasm::Target.new(@packager.full_build_options[:target], pic: true)
187
+ end
188
+
189
+ def derive_build
190
+ return @build if @build
191
+ __skip__ =
192
+ build ||= RubyWasm::Build.new(
193
+ name, **@packager.full_build_options,
194
+ target: target,
195
+ # NOTE: We don't need linking libwasi_vfs because we use wasi-virt instead.
196
+ wasi_vfs: nil
197
+ )
198
+ build.crossruby.cflags = %w[-fPIC -fvisibility=default]
199
+ if @packager.full_build_options[:target] != "wasm32-unknown-emscripten"
200
+ build.crossruby.debugflags = %w[-g]
201
+ build.crossruby.wasmoptflags = %w[-O3 -g --pass-arg=asyncify-relocatable]
202
+ build.crossruby.ldflags = %w[
203
+ -Xlinker
204
+ --stack-first
205
+ -Xlinker
206
+ -z
207
+ -Xlinker
208
+ stack-size=16777216
209
+ ]
210
+ build.crossruby.xldflags = %w[
211
+ -Xlinker -shared
212
+ -Xlinker --export-dynamic
213
+ -Xlinker --export-all
214
+ -Xlinker --experimental-pic
215
+ -Xlinker -export-if-defined=__main_argc_argv
216
+ ]
217
+ end
218
+ @build = build
219
+ build
220
+ end
221
+
222
+ def name
223
+ require "digest"
224
+ options = @packager.full_build_options
225
+ src_channel = options[:src][:name]
226
+ target_triplet = options[:target]
227
+ "ruby-#{src_channel}-#{target_triplet}-pic#{options[:suffix]}"
228
+ end
64
229
  end
65
230
 
66
231
  class StaticLinking < BuildStrategy
@@ -99,10 +264,14 @@ class RubyWasm::Packager::Core
99
264
  derive_build.crossruby.artifact
100
265
  end
101
266
 
267
+ def target
268
+ RubyWasm::Target.new(@packager.full_build_options[:target])
269
+ end
270
+
102
271
  def derive_build
103
272
  return @build if @build
104
273
  __skip__ =
105
- build ||= RubyWasm::Build.new(name, **@packager.full_build_options)
274
+ build ||= RubyWasm::Build.new(name, **@packager.full_build_options, target: target)
106
275
  build.crossruby.user_exts = user_exts(build)
107
276
  # Emscripten uses --global-base=1024 by default, but it conflicts with
108
277
  # --stack-first and -z stack-size since global-base 1024 is smaller than
@@ -111,7 +280,9 @@ class RubyWasm::Packager::Core
111
280
  # script of Ruby.
112
281
  if @packager.full_build_options[:target] != "wasm32-unknown-emscripten"
113
282
  build.crossruby.debugflags = %w[-g]
114
- build.crossruby.wasmoptflags = %w[-O3 -g]
283
+ # We assume that imported functions provided through WASI will not change
284
+ # asyncify state, so we ignore them.
285
+ build.crossruby.wasmoptflags = %w[-O3 -g --pass-arg=asyncify-ignore-imports]
115
286
  build.crossruby.ldflags = %w[
116
287
  -Xlinker
117
288
  --stack-first
@@ -125,6 +296,12 @@ class RubyWasm::Packager::Core
125
296
  build
126
297
  end
127
298
 
299
+ def build_and_link_exts(executor)
300
+ build = derive_build
301
+ ruby_root = build.crossruby.dest_dir
302
+ File.binread(File.join(ruby_root, "usr", "local", "bin", "ruby"))
303
+ end
304
+
128
305
  def user_exts(build)
129
306
  @user_exts ||=
130
307
  specs_with_extensions.flat_map do |spec, exts|
@@ -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
- ].each do |pattern|
72
+ ]
73
+
74
+ patterns << "**/*.so" unless @packager.support_dynamic_linking?
75
+ patterns.each do |pattern|
74
76
  Dir
75
77
  .glob(File.join(@dest_dir, pattern))
76
78
  .each do |entry|
@@ -2,9 +2,15 @@
2
2
  class RubyWasm::Packager
3
3
  # Initializes a new instance of the RubyWasm::Packager class.
4
4
  #
5
+ # @param root [String] The root directory of the Ruby project.
6
+ # The root directory (will) contain the following files:
7
+ # * build_manifest.json
8
+ # * rubies
9
+ # * build
5
10
  # @param config [Hash] The build config used for building Ruby.
6
11
  # @param definition [Bundler::Definition] The Bundler definition.
7
- def initialize(config = nil, definition = nil)
12
+ def initialize(root, config = nil, definition = nil)
13
+ @root = root
8
14
  @definition = definition
9
15
  @config = config
10
16
  end
@@ -21,15 +27,13 @@ class RubyWasm::Packager
21
27
 
22
28
  fs = RubyWasm::Packager::FileSystem.new(dest_dir, self)
23
29
  fs.package_ruby_root(tarball, executor)
24
-
25
- ruby_wasm_bin = File.expand_path("bin/ruby", fs.ruby_root)
26
- wasm_bytes = File.binread(ruby_wasm_bin).bytes
30
+ wasm_bytes = ruby_core.build_and_link_exts(executor)
27
31
 
28
32
  fs.package_gems
29
33
  fs.remove_non_runtime_files(executor)
30
34
  fs.remove_stdlib(executor) unless options[:stdlib]
31
35
 
32
- if full_build_options[:target] == "wasm32-unknown-wasi"
36
+ if full_build_options[:target] == "wasm32-unknown-wasip1" && !support_dynamic_linking?
33
37
  # wasi-vfs supports only WASI target
34
38
  wasi_vfs = RubyWasmExt::WasiVfs.new
35
39
  wasi_vfs.map_dir("/bundle", fs.bundle_dir)
@@ -52,79 +56,23 @@ class RubyWasm::Packager
52
56
  # Retrieves the specs from the Bundler definition, excluding the excluded gems.
53
57
  def specs
54
58
  return [] unless @definition
55
- @definition.specs.reject { |spec| EXCLUDED_GEMS.include?(spec.name) }
59
+ @specs ||= @definition.resolve.materialize(@definition.requested_dependencies)
60
+ .reject { |spec| EXCLUDED_GEMS.include?(spec.name) }
61
+ @specs
56
62
  end
57
63
 
58
64
  # Checks if dynamic linking is supported.
59
65
  def support_dynamic_linking?
60
- @ruby_channel == "head"
61
- end
62
-
63
- # Retrieves the root directory of the Ruby project.
64
- # The root directory contains the following stuff:
65
- # * patches/*.patch
66
- # * build_manifest.json
67
- # * rubies
68
- # * build
69
- def root
70
- __skip__ =
71
- @root ||=
72
- begin
73
- if explicit = ENV["RUBY_WASM_ROOT"]
74
- File.expand_path(explicit)
75
- elsif defined?(Bundler)
76
- Bundler.root
77
- else
78
- Dir.pwd
79
- end
80
- rescue Bundler::GemfileNotFound
81
- Dir.pwd
82
- end
83
- end
84
-
85
- # Retrieves the alias definitions for the Ruby sources.
86
- def self.build_source_aliases(root)
87
- patches = Dir[File.join(root, "patches", "*.patch")]
88
- sources = {
89
- "head" => {
90
- type: "github",
91
- repo: "ruby/ruby",
92
- rev: "master",
93
- patches: patches.map { |p| File.expand_path(p) }
94
- },
95
- "3.3" => {
96
- type: "tarball",
97
- url: "https://cache.ruby-lang.org/pub/ruby/3.3/ruby-3.3.0.tar.gz"
98
- },
99
- "3.2" => {
100
- type: "tarball",
101
- url: "https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.3.tar.gz"
102
- }
103
- }
104
- sources.each { |name, source| source[:name] = name }
105
-
106
- build_manifest = File.join(root, "build_manifest.json")
107
- if File.exist?(build_manifest)
108
- begin
109
- manifest = JSON.parse(File.read(build_manifest))
110
- manifest["ruby_revisions"].each do |name, rev|
111
- sources[name][:rev] = rev
112
- end
113
- rescue StandardError => e
114
- RubyWasm.logger.warn "Failed to load build_manifest.json: #{e}"
115
- end
116
- end
117
- sources
66
+ ENV["RUBY_WASM_EXPERIMENTAL_DYNAMIC_LINKING"] == "1"
118
67
  end
119
68
 
120
69
  ALL_DEFAULT_EXTS =
121
- "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"
70
+ "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"
122
71
 
123
72
  # Retrieves the build options used for building Ruby itself.
124
73
  def build_options
125
74
  default = {
126
- target: "wasm32-unknown-wasi",
127
- src: "3.3",
75
+ target: RubyWasm::Target.new("wasm32-unknown-wasip1"),
128
76
  default_exts: ALL_DEFAULT_EXTS
129
77
  }
130
78
  override = @config || {}
@@ -135,25 +83,14 @@ class RubyWasm::Packager
135
83
  # Retrieves the resolved build options
136
84
  def full_build_options
137
85
  options = build_options
138
- build_dir = File.join(root, "build")
139
- rubies_dir = File.join(root, "rubies")
86
+ build_dir = File.join(@root, "build")
87
+ rubies_dir = File.join(@root, "rubies")
140
88
  toolchain = RubyWasm::Toolchain.get(options[:target], build_dir)
141
- src =
142
- if options[:src].is_a?(Hash)
143
- options[:src]
144
- else
145
- src_name = options[:src]
146
- aliases = self.class.build_source_aliases(root)
147
- aliases[src_name] ||
148
- raise(
149
- "Unknown Ruby source: #{src_name} (available: #{aliases.keys.join(", ")})"
150
- )
151
- end
152
89
  options.merge(
153
90
  toolchain: toolchain,
154
91
  build_dir: build_dir,
155
92
  rubies_dir: rubies_dir,
156
- src: src
93
+ src: options[:src]
157
94
  )
158
95
  end
159
96
  end
@@ -16,6 +16,7 @@ class RubyWasm::BuildTask < ::Rake::TaskLib
16
16
  **options,
17
17
  &block
18
18
  )
19
+ target = Target.new(target)
19
20
  @build =
20
21
  RubyWasm::Build.new(
21
22
  name,
@@ -1,3 +1,3 @@
1
1
  module RubyWasm
2
- VERSION = "2.5.0"
2
+ VERSION = "2.5.1"
3
3
  end
data/lib/ruby_wasm.rb CHANGED
@@ -4,6 +4,7 @@ require_relative "ruby_wasm/version"
4
4
  require_relative "ruby_wasm/util"
5
5
  require_relative "ruby_wasm/build"
6
6
  require_relative "ruby_wasm/packager"
7
+ require_relative "ruby_wasm/packager/component_adapter"
7
8
  require_relative "ruby_wasm/packager/file_system"
8
9
  require_relative "ruby_wasm/packager/core"
9
10