ruby_wasm 2.5.1-aarch64-linux-musl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/.clang-format +8 -0
  3. data/CONTRIBUTING.md +128 -0
  4. data/Gemfile +17 -0
  5. data/LICENSE +21 -0
  6. data/NOTICE +1293 -0
  7. data/README.md +154 -0
  8. data/Rakefile +164 -0
  9. data/Steepfile +24 -0
  10. data/benchmarks/vm_deep_call.rb +55 -0
  11. data/docs/api.md +2 -0
  12. data/docs/cheat_sheet.md +195 -0
  13. data/docs/faq.md +25 -0
  14. data/exe/rbwasm +7 -0
  15. data/ext/.gitignore +2 -0
  16. data/ext/README.md +11 -0
  17. data/ext/extinit.c.erb +32 -0
  18. data/lib/ruby_wasm/3.1/ruby_wasm.so +0 -0
  19. data/lib/ruby_wasm/3.2/ruby_wasm.so +0 -0
  20. data/lib/ruby_wasm/3.3/ruby_wasm.so +0 -0
  21. data/lib/ruby_wasm/build/build_params.rb +3 -0
  22. data/lib/ruby_wasm/build/downloader.rb +18 -0
  23. data/lib/ruby_wasm/build/executor.rb +191 -0
  24. data/lib/ruby_wasm/build/product/baseruby.rb +37 -0
  25. data/lib/ruby_wasm/build/product/crossruby.rb +360 -0
  26. data/lib/ruby_wasm/build/product/libyaml.rb +70 -0
  27. data/lib/ruby_wasm/build/product/openssl.rb +93 -0
  28. data/lib/ruby_wasm/build/product/product.rb +39 -0
  29. data/lib/ruby_wasm/build/product/ruby_source.rb +103 -0
  30. data/lib/ruby_wasm/build/product/wasi_vfs.rb +45 -0
  31. data/lib/ruby_wasm/build/product/zlib.rb +70 -0
  32. data/lib/ruby_wasm/build/product.rb +8 -0
  33. data/lib/ruby_wasm/build/target.rb +24 -0
  34. data/lib/ruby_wasm/build/toolchain/wit_bindgen.rb +31 -0
  35. data/lib/ruby_wasm/build/toolchain.rb +193 -0
  36. data/lib/ruby_wasm/build.rb +92 -0
  37. data/lib/ruby_wasm/cli.rb +347 -0
  38. data/lib/ruby_wasm/packager/component_adapter/wasi_snapshot_preview1.command.wasm +0 -0
  39. data/lib/ruby_wasm/packager/component_adapter/wasi_snapshot_preview1.reactor.wasm +0 -0
  40. data/lib/ruby_wasm/packager/component_adapter.rb +14 -0
  41. data/lib/ruby_wasm/packager/core.rb +333 -0
  42. data/lib/ruby_wasm/packager/file_system.rb +160 -0
  43. data/lib/ruby_wasm/packager.rb +96 -0
  44. data/lib/ruby_wasm/rake_task.rb +60 -0
  45. data/lib/ruby_wasm/util.rb +15 -0
  46. data/lib/ruby_wasm/version.rb +3 -0
  47. data/lib/ruby_wasm.rb +34 -0
  48. data/package-lock.json +9777 -0
  49. data/package.json +12 -0
  50. data/rakelib/check.rake +37 -0
  51. data/rakelib/ci.rake +152 -0
  52. data/rakelib/doc.rake +29 -0
  53. data/rakelib/format.rake +35 -0
  54. data/rakelib/gem.rake +22 -0
  55. data/rakelib/packaging.rake +165 -0
  56. data/rakelib/version.rake +40 -0
  57. data/sig/open_uri.rbs +4 -0
  58. data/sig/ruby_wasm/build.rbs +327 -0
  59. data/sig/ruby_wasm/cli.rbs +51 -0
  60. data/sig/ruby_wasm/ext.rbs +26 -0
  61. data/sig/ruby_wasm/packager.rbs +122 -0
  62. data/sig/ruby_wasm/util.rbs +5 -0
  63. data/tools/clang-format-diff.sh +18 -0
  64. data/tools/exe/rbminify +12 -0
  65. data/tools/lib/syntax_tree/minify_ruby.rb +63 -0
  66. metadata +114 -0
@@ -0,0 +1,3 @@
1
+ module RubyWasm
2
+ BuildParams = Struct.new(:name, :target, :default_exts, keyword_init: true)
3
+ end
@@ -0,0 +1,18 @@
1
+ module RubyWasm
2
+ class Downloader
3
+ def download(url, dest, message)
4
+ require "open-uri"
5
+ content_length = 0
6
+ uri = URI.parse(url)
7
+ OpenURI.open_uri(
8
+ uri,
9
+ content_length_proc: ->(len) { content_length = len },
10
+ progress_proc: ->(size) do
11
+ print "\r#{message} (#{SizeFormatter.format(content_length)}) %.2f%%" %
12
+ (size.to_f / content_length * 100)
13
+ end
14
+ ) { |f| File.open(dest, "wb") { |out| out.write f.read } }
15
+ puts "\r"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,191 @@
1
+ module RubyWasm
2
+ # Build executor to run the actual build commands.
3
+ class BuildExecutor
4
+ attr_reader :process_count
5
+
6
+ def initialize(verbose: false, process_count: nil)
7
+ @verbose = verbose
8
+ @github_actions_markup = ENV["ENABLE_GITHUB_ACTIONS_MARKUP"] != nil
9
+ __skip__ =
10
+ begin
11
+ require "etc"
12
+ @process_count = process_count || Etc.nprocessors
13
+ rescue LoadError
14
+ @process_count = process_count || 1
15
+ end
16
+ end
17
+
18
+ def system(*args, chdir: nil, env: nil)
19
+ require "open3"
20
+
21
+ _print_command(args, env)
22
+
23
+ # @type var kwargs: Hash[Symbol, untyped]
24
+ kwargs = {}
25
+ kwargs[:chdir] = chdir if chdir
26
+
27
+ args = args.to_a.map(&:to_s)
28
+ # TODO: Remove __skip__ once we have open3 RBS definitions.
29
+ __skip__ =
30
+ if @verbose || !$stdout.tty?
31
+ kwargs[:exception] = true
32
+ if env
33
+ Kernel.system(env, *args, **kwargs)
34
+ else
35
+ Kernel.system(*args, **kwargs)
36
+ end
37
+ else
38
+ printer = StatusPrinter.new
39
+ block =
40
+ proc do |stdin, stdout, stderr, wait_thr|
41
+ mux = Mutex.new
42
+ out = String.new
43
+ err = String.new
44
+ readers =
45
+ [
46
+ [stdout, :stdout, out],
47
+ [stderr, :stderr, err]
48
+ ].map do |io, name, str|
49
+ reader =
50
+ Thread.new do
51
+ while (line = io.gets)
52
+ mux.synchronize do
53
+ printer.send(name, line)
54
+ str << line
55
+ end
56
+ end
57
+ end
58
+ reader.report_on_exception = false
59
+ reader
60
+ end
61
+
62
+ readers.each(&:join)
63
+
64
+ [out, err, wait_thr.value]
65
+ end
66
+ begin
67
+ stdout, stderr, status =
68
+ if env
69
+ Open3.popen3(env, *args, **kwargs, &block)
70
+ else
71
+ Open3.popen3(*args, **kwargs, &block)
72
+ end
73
+ unless status.success?
74
+ $stderr.puts stdout
75
+ $stderr.puts stderr
76
+ cmd_to_print = args.map { |a| "'#{a}'" }.join(" ")
77
+ raise "Command failed with status (#{status.exitstatus}): #{cmd_to_print}"
78
+ end
79
+ ensure
80
+ printer.done
81
+ end
82
+ end
83
+ return
84
+ rescue => e
85
+ $stdout.flush
86
+ $stderr.puts "Try running with `rake --verbose` for more complete output."
87
+ raise e
88
+ end
89
+
90
+ def begin_section(klass, name, note)
91
+ message = "\e[1;36m==>\e[0m \e[1m#{klass}(#{name}) -- #{note}\e[0m"
92
+ if @github_actions_markup
93
+ puts "::group::#{message}"
94
+ else
95
+ puts message
96
+ end
97
+
98
+ # Record the start time
99
+ @start_times ||= Hash.new
100
+ @start_times[[klass, name]] = Time.now
101
+
102
+ $stdout.flush
103
+ end
104
+
105
+ def end_section(klass, name)
106
+ took = Time.now - @start_times[[klass, name]]
107
+ puts "::endgroup::" if @github_actions_markup
108
+ puts "\e[1;36m==>\e[0m \e[1m#{klass}(#{name}) -- done in #{took.round(2)}s\e[0m"
109
+ end
110
+
111
+ def rm_rf(list)
112
+ FileUtils.rm_rf(list)
113
+ end
114
+
115
+ def rm_f(list)
116
+ FileUtils.rm_f(list)
117
+ end
118
+
119
+ def cp_r(src, dest)
120
+ FileUtils.cp_r(src, dest)
121
+ end
122
+
123
+ def mv(src, dest)
124
+ FileUtils.mv(src, dest)
125
+ end
126
+
127
+ def mkdir_p(list)
128
+ FileUtils.mkdir_p(list)
129
+ end
130
+
131
+ def ln_s(src, dest)
132
+ FileUtils.ln_s(src, dest)
133
+ end
134
+
135
+ def write(path, data)
136
+ File.write(path, data)
137
+ end
138
+
139
+ private
140
+
141
+ def _print_command(args, env)
142
+ require "shellwords"
143
+ # Bold cyan
144
+ print "\e[1;36m ==>\e[0m "
145
+ print "env " + env.map { |k, v| "#{k}=#{v}" }.join(" ") + " " if env
146
+ print args.map { |arg| Shellwords.escape(arg.to_s) }.join(" ") + "\n"
147
+ end
148
+ end
149
+
150
+ # Human readable status printer for the build.
151
+ class StatusPrinter
152
+ def initialize
153
+ @mutex = Mutex.new
154
+ @counter = 0
155
+ @indicators = "|/-\\"
156
+ end
157
+
158
+ def stdout(message)
159
+ require "io/console"
160
+ @mutex.synchronize do
161
+ $stdout.print "\e[K"
162
+ first_line = message.lines(chomp: true).first || ""
163
+
164
+ # Make sure we don't line-wrap the output
165
+ size =
166
+ __skip__ =
167
+ IO.respond_to?(:console_size) ? IO.console_size : IO.console.winsize
168
+ terminal_width = size[1].to_i.nonzero? || 80
169
+ width_limit = terminal_width / 2 - 3
170
+
171
+ if first_line.length > width_limit
172
+ first_line = (first_line[0..width_limit - 5] || "") + "..."
173
+ end
174
+ indicator = @indicators[@counter] || " "
175
+ to_print = " " + indicator + " " + first_line
176
+ $stdout.print to_print
177
+ $stdout.print "\e[1A\n"
178
+ @counter += 1
179
+ @counter = 0 if @counter >= @indicators.length
180
+ end
181
+ end
182
+
183
+ def stderr(message)
184
+ @mutex.synchronize { $stdout.print message }
185
+ end
186
+
187
+ def done
188
+ @mutex.synchronize { $stdout.print "\e[K" }
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,37 @@
1
+ require_relative "./product"
2
+
3
+ module RubyWasm
4
+ class BaseRubyProduct < BuildProduct
5
+ def initialize(build_dir, source)
6
+ @build_dir = build_dir
7
+ @source = source
8
+ @channel = source.name
9
+ end
10
+
11
+ def product_build_dir
12
+ File.join(@build_dir, RbConfig::CONFIG["host"], "baseruby-#{@channel}")
13
+ end
14
+
15
+ def install_dir
16
+ File.join(product_build_dir, "opt")
17
+ end
18
+
19
+ def name
20
+ "baseruby-#{@channel}"
21
+ end
22
+
23
+ def build(executor)
24
+ executor.mkdir_p product_build_dir
25
+ @source.build(executor)
26
+ return if Dir.exist?(install_dir)
27
+ executor.system @source.configure_file,
28
+ "--prefix=#{install_dir}",
29
+ "--disable-install-doc",
30
+ chdir: product_build_dir
31
+ executor.system "make",
32
+ "-j#{executor.process_count}",
33
+ "install",
34
+ chdir: product_build_dir
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,360 @@
1
+ require_relative "./product"
2
+ require "json"
3
+
4
+ module RubyWasm
5
+ class CrossRubyExtProduct < BuildProduct
6
+ attr_reader :name
7
+
8
+ def initialize(srcdir, toolchain, ext_relative_path: nil)
9
+ @srcdir, @toolchain = srcdir, toolchain
10
+ # ext_relative_path is relative path from build dir
11
+ # e.g. cgi-0.3.6/ext/cgi/escape
12
+ @ext_relative_path = ext_relative_path || File.basename(srcdir)
13
+ @name = @ext_relative_path
14
+ end
15
+
16
+ def product_build_dir(crossruby)
17
+ File.join(crossruby.ext_build_dir, @ext_relative_path)
18
+ end
19
+
20
+ def linklist(crossruby)
21
+ File.join(product_build_dir(crossruby), "link.filelist")
22
+ end
23
+
24
+ def metadata_json(crossruby)
25
+ File.join(product_build_dir(crossruby), "rbwasm.metadata.json")
26
+ end
27
+
28
+ def feature_name(crossruby)
29
+ metadata = JSON.parse(File.read(metadata_json(crossruby)))
30
+ metadata["target"]
31
+ end
32
+
33
+ def make_args(crossruby)
34
+ make_args = []
35
+ make_args << "CC=#{@toolchain.cc}"
36
+ make_args << "LD=#{@toolchain.ld}"
37
+ make_args << "AR=#{@toolchain.ar}"
38
+ make_args << "RANLIB=#{@toolchain.ranlib}"
39
+
40
+ make_args
41
+ end
42
+
43
+ def build(executor, crossruby)
44
+ objdir = product_build_dir crossruby
45
+ executor.mkdir_p objdir
46
+ do_extconf executor, crossruby
47
+
48
+ executor.system "make", "-C", objdir, *make_args(crossruby), "clean"
49
+ build_target = crossruby.target.pic? ? "install-so" : "static"
50
+ executor.system "make",
51
+ "-j#{executor.process_count}",
52
+ "-C",
53
+ "#{objdir}",
54
+ *make_args(crossruby),
55
+ build_target
56
+ # A ext can provide link args by link.filelist. It contains only built archive file by default.
57
+ unless File.exist?(linklist(crossruby))
58
+ executor.write(
59
+ linklist(crossruby),
60
+ Dir.glob("#{objdir}/*.a").join("\n")
61
+ )
62
+ end
63
+ end
64
+
65
+ def do_extconf(executor, crossruby)
66
+ unless crossruby.target.pic?
67
+ self.do_legacy_extconf(executor, crossruby)
68
+ return
69
+ end
70
+ objdir = product_build_dir crossruby
71
+ source = crossruby.source
72
+ rbconfig_rb = Dir.glob(File.join(crossruby.dest_dir, "usr/local/lib/ruby/*/wasm32-wasi/rbconfig.rb")).first
73
+ raise "rbconfig.rb not found" unless rbconfig_rb
74
+ extconf_args = [
75
+ "-C", objdir,
76
+ "#{@srcdir}/extconf.rb",
77
+ "--target-rbconfig=#{rbconfig_rb}",
78
+ ]
79
+ executor.system Gem.ruby, *extconf_args
80
+ end
81
+
82
+ def do_legacy_extconf(executor, crossruby)
83
+ objdir = product_build_dir crossruby
84
+ source = crossruby.source
85
+ extconf_args = [
86
+ "-C", objdir,
87
+ "--disable=gems",
88
+ # HACK: top_srcdir is required to find ruby headers
89
+ "-e",
90
+ %Q($top_srcdir="#{source.src_dir}"),
91
+ # HACK: extout is required to find config.h
92
+ "-e",
93
+ %Q($extout="#{crossruby.build_dir}/.ext"),
94
+ # HACK: force static ext build by imitating extmk
95
+ "-e",
96
+ "$static = true; trace_var(:$static) {|v| $static = true }",
97
+ # HACK: $0 should be extconf.rb path due to mkmf source file detection
98
+ # and we want to insert some hacks before it. But -e and $0 cannot be
99
+ # used together, so we rewrite $0 in -e.
100
+ "-e",
101
+ %Q($0="#{@srcdir}/extconf.rb"),
102
+ "-e",
103
+ %Q(require_relative "#{@srcdir}/extconf.rb"),
104
+ # HACK: extract "$target" from extconf.rb to get a full target name
105
+ # like "cgi/escape" instead of "escape"
106
+ "-e",
107
+ %Q(require "json"; File.write("#{metadata_json(crossruby)}", JSON.dump({target: $target}))),
108
+ "-I#{crossruby.build_dir}"
109
+ ]
110
+ # Clear RUBYOPT to avoid loading unrelated bundle setup
111
+ executor.system crossruby.baseruby_path,
112
+ *extconf_args,
113
+ env: {
114
+ "RUBYOPT" => ""
115
+ }
116
+ end
117
+
118
+ def do_install_rb(executor, crossruby)
119
+ objdir = product_build_dir crossruby
120
+ executor.system "make", "-C", objdir, *make_args(crossruby), "install-rb"
121
+ end
122
+
123
+ def cache_key(digest)
124
+ digest << @name
125
+ # Compute hash value of files under srcdir
126
+ Dir
127
+ .glob("#{@srcdir}/**/*", File::FNM_DOTMATCH)
128
+ .each do |f|
129
+ next if File.directory?(f)
130
+ digest << f
131
+ digest << File.read(f)
132
+ end
133
+ end
134
+ end
135
+
136
+ class CrossRubyProduct < AutoconfProduct
137
+ attr_reader :target, :source, :toolchain
138
+ attr_accessor :user_exts,
139
+ :wasmoptflags,
140
+ :cppflags,
141
+ :cflags,
142
+ :ldflags,
143
+ :debugflags,
144
+ :xcflags,
145
+ :xldflags
146
+
147
+ def initialize(params, build_dir, rubies_dir, baseruby, source, toolchain)
148
+ @params = params
149
+ @rubies_dir = rubies_dir
150
+ @build_dir = build_dir
151
+ @baseruby = baseruby
152
+ @source = source
153
+ @toolchain = toolchain
154
+ @user_exts = []
155
+ @wasmoptflags = []
156
+ @cppflags = []
157
+ @cflags = []
158
+ @ldflags = []
159
+ @debugflags = []
160
+ @xcflags = []
161
+ @xldflags = []
162
+ super(@params.target, @toolchain)
163
+ end
164
+
165
+ def configure(executor, reconfigure: false)
166
+ if !File.exist?("#{build_dir}/Makefile") || reconfigure
167
+ args = configure_args(RbConfig::CONFIG["host"], toolchain)
168
+ executor.system source.configure_file, *args, chdir: build_dir
169
+ end
170
+ # NOTE: we need rbconfig.rb at configuration time to build user given extensions with mkmf
171
+ executor.system "make", "rbconfig.rb", chdir: build_dir
172
+ end
173
+
174
+ def need_exts_build?
175
+ @user_exts.any?
176
+ end
177
+
178
+ def need_extinit_obj?
179
+ need_exts_build? && !@target.pic?
180
+ end
181
+
182
+ def build_exts(executor)
183
+ @user_exts.each do |prod|
184
+ executor.begin_section prod.class, prod.name, "Building"
185
+ prod.build(executor, self)
186
+ executor.end_section prod.class, prod.name
187
+ end
188
+ end
189
+
190
+ def build(executor, remake: false, reconfigure: false)
191
+ executor.mkdir_p dest_dir
192
+ executor.mkdir_p build_dir
193
+ @toolchain.install
194
+ [@source, @baseruby, @libyaml, @zlib, @openssl, @wasi_vfs].each do |prod|
195
+ next unless prod
196
+ executor.begin_section prod.class, prod.name, "Building"
197
+ prod.build(executor)
198
+ executor.end_section prod.class, prod.name
199
+ end
200
+ executor.begin_section self.class, name, "Configuring"
201
+ configure(executor, reconfigure: reconfigure)
202
+ executor.end_section self.class, name
203
+
204
+ build_exts(executor) if need_exts_build?
205
+
206
+ executor.begin_section self.class, name, "Building"
207
+
208
+ if need_extinit_obj?
209
+ executor.mkdir_p File.dirname(extinit_obj)
210
+ executor.system "ruby",
211
+ extinit_c_erb,
212
+ *@user_exts.map { |ext| ext.feature_name(self) },
213
+ "--cc",
214
+ toolchain.cc,
215
+ "--output",
216
+ extinit_obj
217
+ end
218
+ install_dir = File.join(build_dir, "install")
219
+ if !File.exist?(install_dir) || remake || reconfigure
220
+ executor.system "make",
221
+ "-j#{executor.process_count}",
222
+ "install",
223
+ "DESTDIR=#{install_dir}",
224
+ chdir: build_dir
225
+ end
226
+
227
+ executor.rm_rf dest_dir
228
+ executor.cp_r install_dir, dest_dir
229
+ @user_exts.each { |ext| ext.do_install_rb(executor, self) }
230
+ executor.system "tar", "cfz", artifact, "-C", @rubies_dir, name
231
+
232
+ executor.end_section self.class, name
233
+ end
234
+
235
+ def clean(executor)
236
+ executor.rm_rf dest_dir
237
+ executor.rm_rf build_dir
238
+ executor.rm_rf ext_build_dir
239
+ executor.rm_f artifact
240
+ end
241
+
242
+ def name
243
+ @params.name
244
+ end
245
+
246
+ def cache_key(digest)
247
+ @params.target.cache_key(digest)
248
+ digest << @params.default_exts
249
+ @wasmoptflags.each { |f| digest << f }
250
+ @cppflags.each { |f| digest << f }
251
+ @cflags.each { |f| digest << f }
252
+ @ldflags.each { |f| digest << f }
253
+ @debugflags.each { |f| digest << f }
254
+ @xcflags.each { |f| digest << f }
255
+ @xldflags.each { |f| digest << f }
256
+ @user_exts.each { |ext| ext.cache_key(digest) }
257
+ end
258
+
259
+ def build_dir
260
+ File.join(@build_dir, @params.target.to_s, name)
261
+ end
262
+
263
+ def ext_build_dir
264
+ File.join(@build_dir, @params.target.to_s, name + "-ext")
265
+ end
266
+
267
+ def with_libyaml(libyaml)
268
+ @libyaml = libyaml
269
+ end
270
+
271
+ def with_zlib(zlib)
272
+ @zlib = zlib
273
+ end
274
+
275
+ def with_wasi_vfs(wasi_vfs)
276
+ @wasi_vfs = wasi_vfs
277
+ end
278
+
279
+ def with_openssl(openssl)
280
+ @openssl = openssl
281
+ end
282
+
283
+ def dest_dir
284
+ File.join(@rubies_dir, name)
285
+ end
286
+
287
+ def artifact
288
+ File.join(@rubies_dir, "#{name}.tar.gz")
289
+ end
290
+
291
+ def extinit_obj
292
+ "#{ext_build_dir}/extinit.o"
293
+ end
294
+
295
+ def extinit_c_erb
296
+ lib_root = File.expand_path("../../../../..", __FILE__)
297
+ File.join(lib_root, "ext", "extinit.c.erb")
298
+ end
299
+
300
+ def baseruby_path
301
+ File.join(@baseruby.install_dir, "bin/ruby")
302
+ end
303
+
304
+ def configure_args(build_triple, toolchain)
305
+ target = @params.target.triple
306
+ default_exts = @params.default_exts
307
+
308
+ ldflags = @ldflags.dup
309
+ xldflags = @xldflags.dup
310
+
311
+ args = self.system_triplet_args + ["--build", build_triple]
312
+ args << "--with-static-linked-ext" unless @params.target.pic?
313
+ args << %Q(--with-ext=#{default_exts})
314
+ args << %Q(--with-libyaml-dir=#{@libyaml.install_root})
315
+ args << %Q(--with-zlib-dir=#{@zlib.install_root})
316
+ args << %Q(--with-openssl-dir=#{@openssl.install_root}) if @openssl
317
+ args << %Q(--with-baseruby=#{baseruby_path})
318
+
319
+ case target
320
+ when /^wasm32-unknown-wasi/
321
+ xldflags << @wasi_vfs.lib_wasi_vfs_a if @wasi_vfs
322
+ # TODO: Find a way to force cast or update API
323
+ # @type var wasi_sdk_path: untyped
324
+ wasi_sdk_path = @toolchain
325
+ args << %Q(WASMOPT=#{wasi_sdk_path.wasm_opt})
326
+ args << %Q(WASI_SDK_PATH=#{wasi_sdk_path.wasi_sdk_path})
327
+ when "wasm32-unknown-emscripten"
328
+ ldflags.concat(%w[-s MODULARIZE=1])
329
+ env_emcc_ldflags = ENV["RUBY_WASM_EMCC_LDFLAGS"] || ""
330
+ unless env_emcc_ldflags.empty?
331
+ ldflags << env_emcc_ldflags
332
+ end
333
+ else
334
+ raise "unknown target: #{target}"
335
+ end
336
+
337
+ args.concat(self.tools_args)
338
+ (@user_exts || []).each { |lib| xldflags << "@#{lib.linklist(self)}" }
339
+ xldflags << extinit_obj if need_extinit_obj?
340
+
341
+ cflags = @cflags.dup
342
+ xcflags = @xcflags.dup
343
+ xcflags << "-DWASM_SETJMP_STACK_BUFFER_SIZE=24576"
344
+ xcflags << "-DWASM_FIBER_STACK_BUFFER_SIZE=24576"
345
+ xcflags << "-DWASM_SCAN_STACK_BUFFER_SIZE=24576"
346
+
347
+ args << %Q(LDFLAGS=#{ldflags.join(" ")})
348
+ args << %Q(XLDFLAGS=#{xldflags.join(" ")})
349
+ args << %Q(CFLAGS=#{cflags.join(" ")})
350
+ args << %Q(XCFLAGS=#{xcflags.join(" ")})
351
+ args << %Q(debugflags=#{@debugflags.join(" ")})
352
+ args << %Q(cppflags=#{@cppflags.join(" ")})
353
+ unless wasmoptflags.empty?
354
+ args << %Q(wasmoptflags=#{@wasmoptflags.join(" ")})
355
+ end
356
+ args << "--disable-install-doc"
357
+ args
358
+ end
359
+ end
360
+ end
@@ -0,0 +1,70 @@
1
+ require_relative "./product"
2
+
3
+ module RubyWasm
4
+ class LibYAMLProduct < AutoconfProduct
5
+ attr_reader :target
6
+
7
+ LIBYAML_VERSION = "0.2.5"
8
+
9
+ def initialize(build_dir, target, toolchain)
10
+ @build_dir = build_dir
11
+ @target = target
12
+ super(target, toolchain)
13
+ end
14
+
15
+ def product_build_dir
16
+ File.join(@build_dir, target.to_s, "yaml-#{LIBYAML_VERSION}")
17
+ end
18
+
19
+ def destdir
20
+ File.join(product_build_dir, "opt")
21
+ end
22
+
23
+ def install_root
24
+ File.join(destdir, "usr", "local")
25
+ end
26
+
27
+ def name
28
+ "libyaml-#{LIBYAML_VERSION}-#{target}"
29
+ end
30
+
31
+ def build(executor)
32
+ return if Dir.exist?(install_root)
33
+
34
+ executor.mkdir_p File.dirname(product_build_dir)
35
+ executor.rm_rf product_build_dir
36
+ executor.mkdir_p product_build_dir
37
+ tarball_path =
38
+ File.join(product_build_dir, "libyaml-#{LIBYAML_VERSION}.tar.gz")
39
+ executor.system "curl",
40
+ "-o",
41
+ tarball_path,
42
+ "-L",
43
+ "https://github.com/yaml/libyaml/releases/download/#{LIBYAML_VERSION}/yaml-#{LIBYAML_VERSION}.tar.gz"
44
+ executor.system "tar",
45
+ "xzf",
46
+ tarball_path,
47
+ "-C",
48
+ product_build_dir,
49
+ "--strip-components=1"
50
+
51
+ # obtain the latest config.guess and config.sub for Emscripten and WASI triple support
52
+ executor.system "curl",
53
+ "-o",
54
+ "#{product_build_dir}/config/config.guess",
55
+ "https://cdn.jsdelivr.net/gh/gcc-mirror/gcc@master/config.guess"
56
+ executor.system "curl",
57
+ "-o",
58
+ "#{product_build_dir}/config/config.sub",
59
+ "https://cdn.jsdelivr.net/gh/gcc-mirror/gcc@master/config.sub"
60
+
61
+ configure_args = self.configure_args.dup
62
+ configure_args << "CFLAGS=-fPIC" if target.pic?
63
+ executor.system "./configure", *configure_args, chdir: product_build_dir
64
+ executor.system "make",
65
+ "install",
66
+ "DESTDIR=#{destdir}",
67
+ chdir: product_build_dir
68
+ end
69
+ end
70
+ end