ruby_wasm 2.5.0-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 (65) hide show
  1. checksums.yaml +7 -0
  2. data/.clang-format +8 -0
  3. data/CONTRIBUTING.md +126 -0
  4. data/Gemfile +17 -0
  5. data/LICENSE +21 -0
  6. data/NOTICE +1293 -0
  7. data/README.md +153 -0
  8. data/Rakefile +163 -0
  9. data/Steepfile +24 -0
  10. data/benchmarks/vm_deep_call.rb +55 -0
  11. data/builders/wasm32-unknown-emscripten/Dockerfile +43 -0
  12. data/builders/wasm32-unknown-emscripten/entrypoint.sh +7 -0
  13. data/builders/wasm32-unknown-wasi/Dockerfile +47 -0
  14. data/builders/wasm32-unknown-wasi/entrypoint.sh +7 -0
  15. data/docs/api.md +2 -0
  16. data/docs/cheat_sheet.md +195 -0
  17. data/docs/faq.md +25 -0
  18. data/exe/rbwasm +7 -0
  19. data/ext/.gitignore +2 -0
  20. data/ext/README.md +11 -0
  21. data/ext/extinit.c.erb +32 -0
  22. data/lib/ruby_wasm/3.1/ruby_wasm.so +0 -0
  23. data/lib/ruby_wasm/3.2/ruby_wasm.so +0 -0
  24. data/lib/ruby_wasm/build/build_params.rb +3 -0
  25. data/lib/ruby_wasm/build/downloader.rb +18 -0
  26. data/lib/ruby_wasm/build/executor.rb +187 -0
  27. data/lib/ruby_wasm/build/product/baseruby.rb +37 -0
  28. data/lib/ruby_wasm/build/product/crossruby.rb +330 -0
  29. data/lib/ruby_wasm/build/product/libyaml.rb +68 -0
  30. data/lib/ruby_wasm/build/product/openssl.rb +88 -0
  31. data/lib/ruby_wasm/build/product/product.rb +39 -0
  32. data/lib/ruby_wasm/build/product/ruby_source.rb +103 -0
  33. data/lib/ruby_wasm/build/product/wasi_vfs.rb +45 -0
  34. data/lib/ruby_wasm/build/product/zlib.rb +68 -0
  35. data/lib/ruby_wasm/build/product.rb +8 -0
  36. data/lib/ruby_wasm/build/toolchain/wit_bindgen.rb +31 -0
  37. data/lib/ruby_wasm/build/toolchain.rb +193 -0
  38. data/lib/ruby_wasm/build.rb +88 -0
  39. data/lib/ruby_wasm/cli.rb +217 -0
  40. data/lib/ruby_wasm/packager/core.rb +156 -0
  41. data/lib/ruby_wasm/packager/file_system.rb +158 -0
  42. data/lib/ruby_wasm/packager.rb +159 -0
  43. data/lib/ruby_wasm/rake_task.rb +59 -0
  44. data/lib/ruby_wasm/util.rb +15 -0
  45. data/lib/ruby_wasm/version.rb +3 -0
  46. data/lib/ruby_wasm.rb +33 -0
  47. data/package-lock.json +9500 -0
  48. data/package.json +12 -0
  49. data/rakelib/check.rake +37 -0
  50. data/rakelib/ci.rake +152 -0
  51. data/rakelib/doc.rake +29 -0
  52. data/rakelib/format.rake +35 -0
  53. data/rakelib/gem.rake +22 -0
  54. data/rakelib/packaging.rake +151 -0
  55. data/rakelib/version.rake +40 -0
  56. data/sig/open_uri.rbs +4 -0
  57. data/sig/ruby_wasm/build.rbs +318 -0
  58. data/sig/ruby_wasm/cli.rbs +27 -0
  59. data/sig/ruby_wasm/ext.rbs +13 -0
  60. data/sig/ruby_wasm/packager.rbs +91 -0
  61. data/sig/ruby_wasm/util.rbs +5 -0
  62. data/tools/clang-format-diff.sh +18 -0
  63. data/tools/exe/rbminify +12 -0
  64. data/tools/lib/syntax_tree/minify_ruby.rb +63 -0
  65. metadata +113 -0
@@ -0,0 +1,330 @@
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 << "DESTDIR=#{crossruby.dest_dir}"
41
+ make_args
42
+ end
43
+
44
+ def build(executor, crossruby)
45
+ objdir = product_build_dir crossruby
46
+ executor.mkdir_p objdir
47
+ do_extconf executor, crossruby
48
+ executor.system "make",
49
+ "-j#{executor.process_count}",
50
+ "-C",
51
+ "#{objdir}",
52
+ *make_args(crossruby),
53
+ "static"
54
+ # A ext can provide link args by link.filelist. It contains only built archive file by default.
55
+ unless File.exist?(linklist(crossruby))
56
+ executor.write(
57
+ linklist(crossruby),
58
+ Dir.glob("#{objdir}/*.a").join("\n")
59
+ )
60
+ end
61
+ end
62
+
63
+ def do_extconf(executor, crossruby)
64
+ objdir = product_build_dir crossruby
65
+ source = crossruby.source
66
+ extconf_args = [
67
+ "--disable=gems",
68
+ # HACK: top_srcdir is required to find ruby headers
69
+ "-e",
70
+ %Q($top_srcdir="#{source.src_dir}"),
71
+ # HACK: extout is required to find config.h
72
+ "-e",
73
+ %Q($extout="#{crossruby.build_dir}/.ext"),
74
+ # HACK: skip have_devel check since ruby is not installed yet
75
+ "-e",
76
+ "$have_devel = true",
77
+ # HACK: force static ext build by imitating extmk
78
+ "-e",
79
+ "$static = true; trace_var(:$static) {|v| $static = true }",
80
+ # HACK: $0 should be extconf.rb path due to mkmf source file detection
81
+ # and we want to insert some hacks before it. But -e and $0 cannot be
82
+ # used together, so we rewrite $0 in -e.
83
+ "-e",
84
+ %Q($0="#{@srcdir}/extconf.rb"),
85
+ "-e",
86
+ %Q(require_relative "#{@srcdir}/extconf.rb"),
87
+ # HACK: extract "$target" from extconf.rb to get a full target name
88
+ # like "cgi/escape" instead of "escape"
89
+ "-e",
90
+ %Q(require "json"; File.write("#{metadata_json(crossruby)}", JSON.dump({target: $target}))),
91
+ "-I#{crossruby.build_dir}"
92
+ ]
93
+ # Clear RUBYOPT to avoid loading unrelated bundle setup
94
+ executor.system crossruby.baseruby_path,
95
+ *extconf_args,
96
+ chdir: objdir,
97
+ env: {
98
+ "RUBYOPT" => ""
99
+ }
100
+ end
101
+
102
+ def do_install_rb(executor, crossruby)
103
+ objdir = product_build_dir crossruby
104
+ executor.system "make", "-C", objdir, *make_args(crossruby), "install-rb"
105
+ end
106
+
107
+ def cache_key(digest)
108
+ digest << @name
109
+ # Compute hash value of files under srcdir
110
+ Dir
111
+ .glob("#{@srcdir}/**/*", File::FNM_DOTMATCH)
112
+ .each do |f|
113
+ next if File.directory?(f)
114
+ digest << f
115
+ digest << File.read(f)
116
+ end
117
+ end
118
+ end
119
+
120
+ class CrossRubyProduct < AutoconfProduct
121
+ attr_reader :source, :toolchain
122
+ attr_accessor :user_exts,
123
+ :wasmoptflags,
124
+ :cppflags,
125
+ :cflags,
126
+ :ldflags,
127
+ :debugflags,
128
+ :xcflags,
129
+ :xldflags
130
+
131
+ def initialize(params, build_dir, rubies_dir, baseruby, source, toolchain)
132
+ @params = params
133
+ @rubies_dir = rubies_dir
134
+ @build_dir = build_dir
135
+ @baseruby = baseruby
136
+ @source = source
137
+ @toolchain = toolchain
138
+ @user_exts = []
139
+ @wasmoptflags = []
140
+ @cppflags = []
141
+ @cflags = []
142
+ @ldflags = []
143
+ @debugflags = []
144
+ @xcflags = []
145
+ @xldflags = []
146
+ super(@params.target, @toolchain)
147
+ end
148
+
149
+ def configure(executor, reconfigure: false)
150
+ if !File.exist?("#{build_dir}/Makefile") || reconfigure
151
+ args = configure_args(RbConfig::CONFIG["host"], toolchain)
152
+ executor.system source.configure_file, *args, chdir: build_dir
153
+ end
154
+ # NOTE: we need rbconfig.rb at configuration time to build user given extensions with mkmf
155
+ executor.system "make", "rbconfig.rb", chdir: build_dir
156
+ end
157
+
158
+ def build_exts(executor)
159
+ @user_exts.each do |prod|
160
+ executor.begin_section prod.class, prod.name, "Building"
161
+ prod.build(executor, self)
162
+ executor.end_section prod.class, prod.name
163
+ end
164
+ end
165
+
166
+ def build(executor, remake: false, reconfigure: false)
167
+ executor.mkdir_p dest_dir
168
+ executor.mkdir_p build_dir
169
+ @toolchain.install
170
+ [@source, @baseruby, @libyaml, @zlib, @openssl, @wasi_vfs].each do |prod|
171
+ executor.begin_section prod.class, prod.name, "Building"
172
+ prod.build(executor)
173
+ executor.end_section prod.class, prod.name
174
+ end
175
+ executor.begin_section self.class, name, "Configuring"
176
+ configure(executor, reconfigure: reconfigure)
177
+ executor.end_section self.class, name
178
+
179
+ build_exts(executor)
180
+
181
+ executor.begin_section self.class, name, "Building"
182
+ executor.mkdir_p File.dirname(extinit_obj)
183
+ executor.system "ruby",
184
+ extinit_c_erb,
185
+ *@user_exts.map { |ext| ext.feature_name(self) },
186
+ "--cc",
187
+ toolchain.cc,
188
+ "--output",
189
+ extinit_obj
190
+ install_dir = File.join(build_dir, "install")
191
+ if !File.exist?(install_dir) || remake || reconfigure
192
+ executor.system "make",
193
+ "-j#{executor.process_count}",
194
+ "install",
195
+ "DESTDIR=#{install_dir}",
196
+ chdir: build_dir
197
+ end
198
+
199
+ executor.rm_rf dest_dir
200
+ executor.cp_r install_dir, dest_dir
201
+ @user_exts.each { |ext| ext.do_install_rb(executor, self) }
202
+ executor.system "tar", "cfz", artifact, "-C", @rubies_dir, name
203
+
204
+ executor.end_section self.class, name
205
+ end
206
+
207
+ def clean(executor)
208
+ executor.rm_rf dest_dir
209
+ executor.rm_rf build_dir
210
+ executor.rm_rf ext_build_dir
211
+ executor.rm_f artifact
212
+ end
213
+
214
+ def name
215
+ @params.name
216
+ end
217
+
218
+ def cache_key(digest)
219
+ digest << @params.target
220
+ digest << @params.default_exts
221
+ @wasmoptflags.each { |f| digest << f }
222
+ @cppflags.each { |f| digest << f }
223
+ @cflags.each { |f| digest << f }
224
+ @ldflags.each { |f| digest << f }
225
+ @debugflags.each { |f| digest << f }
226
+ @xcflags.each { |f| digest << f }
227
+ @xldflags.each { |f| digest << f }
228
+ @user_exts.each { |ext| ext.cache_key(digest) }
229
+ end
230
+
231
+ def build_dir
232
+ File.join(@build_dir, @params.target, name)
233
+ end
234
+
235
+ def ext_build_dir
236
+ File.join(@build_dir, @params.target, name + "-ext")
237
+ end
238
+
239
+ def with_libyaml(libyaml)
240
+ @libyaml = libyaml
241
+ end
242
+
243
+ def with_zlib(zlib)
244
+ @zlib = zlib
245
+ end
246
+
247
+ def with_wasi_vfs(wasi_vfs)
248
+ @wasi_vfs = wasi_vfs
249
+ end
250
+
251
+ def with_openssl(openssl)
252
+ @openssl = openssl
253
+ end
254
+
255
+ def dest_dir
256
+ File.join(@rubies_dir, name)
257
+ end
258
+
259
+ def artifact
260
+ File.join(@rubies_dir, "#{name}.tar.gz")
261
+ end
262
+
263
+ def extinit_obj
264
+ "#{ext_build_dir}/extinit.o"
265
+ end
266
+
267
+ def extinit_c_erb
268
+ lib_root = File.expand_path("../../../../..", __FILE__)
269
+ File.join(lib_root, "ext", "extinit.c.erb")
270
+ end
271
+
272
+ def baseruby_path
273
+ File.join(@baseruby.install_dir, "bin/ruby")
274
+ end
275
+
276
+ def configure_args(build_triple, toolchain)
277
+ target = @params.target
278
+ default_exts = @params.default_exts
279
+
280
+ ldflags = @ldflags.dup
281
+ xldflags = @xldflags.dup
282
+
283
+ args = self.system_triplet_args + ["--build", build_triple]
284
+ args << "--with-static-linked-ext"
285
+ args << %Q(--with-ext=#{default_exts})
286
+ args << %Q(--with-libyaml-dir=#{@libyaml.install_root})
287
+ args << %Q(--with-zlib-dir=#{@zlib.install_root})
288
+ args << %Q(--with-openssl-dir=#{@openssl.install_root}) if @openssl
289
+ args << %Q(--with-baseruby=#{baseruby_path})
290
+
291
+ case target
292
+ when "wasm32-unknown-wasi"
293
+ xldflags << @wasi_vfs.lib_wasi_vfs_a if @wasi_vfs
294
+ # TODO: Find a way to force cast or update API
295
+ # @type var wasi_sdk_path: untyped
296
+ wasi_sdk_path = @toolchain
297
+ args << %Q(WASMOPT=#{wasi_sdk_path.wasm_opt})
298
+ args << %Q(WASI_SDK_PATH=#{wasi_sdk_path.wasi_sdk_path})
299
+ when "wasm32-unknown-emscripten"
300
+ ldflags.concat(%w[-s MODULARIZE=1])
301
+ env_emcc_ldflags = ENV["RUBY_WASM_EMCC_LDFLAGS"] || ""
302
+ unless env_emcc_ldflags.empty?
303
+ ldflags << env_emcc_ldflags
304
+ end
305
+ else
306
+ raise "unknown target: #{target}"
307
+ end
308
+
309
+ args.concat(self.tools_args)
310
+ (@user_exts || []).each { |lib| xldflags << "@#{lib.linklist(self)}" }
311
+ xldflags << extinit_obj
312
+
313
+ xcflags = @xcflags.dup
314
+ xcflags << "-DWASM_SETJMP_STACK_BUFFER_SIZE=24576"
315
+ xcflags << "-DWASM_FIBER_STACK_BUFFER_SIZE=24576"
316
+ xcflags << "-DWASM_SCAN_STACK_BUFFER_SIZE=24576"
317
+
318
+ args << %Q(LDFLAGS=#{ldflags.join(" ")})
319
+ args << %Q(XLDFLAGS=#{xldflags.join(" ")})
320
+ args << %Q(XCFLAGS=#{xcflags.join(" ")})
321
+ args << %Q(debugflags=#{@debugflags.join(" ")})
322
+ args << %Q(cppflags=#{@cppflags.join(" ")})
323
+ unless wasmoptflags.empty?
324
+ args << %Q(wasmoptflags=#{@wasmoptflags.join(" ")})
325
+ end
326
+ args << "--disable-install-doc"
327
+ args
328
+ end
329
+ end
330
+ end
@@ -0,0 +1,68 @@
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, "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://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD"
56
+ executor.system "curl",
57
+ "-o",
58
+ "#{product_build_dir}/config/config.sub",
59
+ "https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD"
60
+
61
+ executor.system "./configure", *configure_args, chdir: product_build_dir
62
+ executor.system "make",
63
+ "install",
64
+ "DESTDIR=#{destdir}",
65
+ chdir: product_build_dir
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,88 @@
1
+ require_relative "./product"
2
+
3
+ module RubyWasm
4
+ class OpenSSLProduct < AutoconfProduct
5
+ attr_reader :target
6
+
7
+ OPENSSL_VERSION = "3.2.0"
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, "openssl-#{OPENSSL_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
+ "openssl-#{OPENSSL_VERSION}-#{target}"
29
+ end
30
+
31
+ def configure_args
32
+ args = %w[
33
+ gcc
34
+ -static
35
+ -no-asm
36
+ -no-threads
37
+ -no-afalgeng
38
+ -no-ui-console
39
+ -no-tests
40
+ -no-sock
41
+ -no-dgram
42
+ --libdir=lib
43
+ -Wl,--allow-undefined
44
+ ]
45
+ if @target == "wasm32-unknown-wasi"
46
+ args.concat %w[
47
+ -D_WASI_EMULATED_SIGNAL
48
+ -D_WASI_EMULATED_PROCESS_CLOCKS
49
+ -D_WASI_EMULATED_MMAN
50
+ -D_WASI_EMULATED_GETPID
51
+ -DNO_CHMOD
52
+ -DHAVE_FORK=0
53
+ ]
54
+ end
55
+ args + tools_args
56
+ end
57
+
58
+ def build(executor)
59
+ return if File.exist?(File.join(install_root, "lib", "libssl.a"))
60
+
61
+ executor.mkdir_p File.dirname(product_build_dir)
62
+ executor.rm_rf product_build_dir
63
+ executor.mkdir_p product_build_dir
64
+ tarball_path =
65
+ File.join(product_build_dir, "openssl-#{OPENSSL_VERSION}.tar.gz")
66
+ executor.system "curl",
67
+ "-o",
68
+ tarball_path,
69
+ "-L",
70
+ "https://www.openssl.org/source/openssl-#{OPENSSL_VERSION}.tar.gz"
71
+ executor.system "tar",
72
+ "xzf",
73
+ tarball_path,
74
+ "-C",
75
+ product_build_dir,
76
+ "--strip-components=1"
77
+
78
+ executor.system "./Configure", *configure_args, chdir: product_build_dir
79
+ # Use "install_sw" instead of "install" because it tries to install docs and it's very slow.
80
+ # OpenSSL build system doesn't have well support for parallel build, so force -j1.
81
+ executor.system "make",
82
+ "-j1",
83
+ "install_dev",
84
+ "DESTDIR=#{destdir}",
85
+ chdir: product_build_dir
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,39 @@
1
+ module RubyWasm
2
+ class BuildProduct
3
+ def name
4
+ raise NotImplementedError, "identifiable product name must be implemented"
5
+ end
6
+ end
7
+
8
+ class AutoconfProduct < BuildProduct
9
+ def initialize(target, toolchain)
10
+ @target = target
11
+ @toolchain = toolchain
12
+ end
13
+ def system_triplet_args
14
+ args = []
15
+ case @target
16
+ when "wasm32-unknown-wasi"
17
+ args.concat(%W[--host wasm32-wasi])
18
+ when "wasm32-unknown-emscripten"
19
+ args.concat(%W[--host wasm32-emscripten])
20
+ else
21
+ raise "unknown target: #{@target}"
22
+ end
23
+ args
24
+ end
25
+
26
+ def tools_args
27
+ args = []
28
+ args << "CC=#{@toolchain.cc}"
29
+ args << "LD=#{@toolchain.ld}"
30
+ args << "AR=#{@toolchain.ar}"
31
+ args << "RANLIB=#{@toolchain.ranlib}"
32
+ args
33
+ end
34
+
35
+ def configure_args
36
+ system_triplet_args + tools_args
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,103 @@
1
+ require_relative "./product"
2
+
3
+ module RubyWasm
4
+ class BuildSource < BuildProduct
5
+ def initialize(params, build_dir)
6
+ @params = params
7
+ @build_dir = build_dir
8
+ end
9
+
10
+ def name
11
+ @params[:name]
12
+ end
13
+
14
+ def cache_key(digest)
15
+ digest << @params[:type]
16
+ case @params[:type]
17
+ when "github"
18
+ digest << @params[:rev]
19
+ when "tarball"
20
+ digest << @params[:url]
21
+ when "local"
22
+ digest << File.mtime(@params[:src]).to_i.to_s
23
+ else
24
+ raise "unknown source type: #{@params[:type]}"
25
+ end
26
+ end
27
+
28
+ def src_dir
29
+ File.join(@build_dir, "checkouts", @params[:name])
30
+ end
31
+
32
+ def configure_file
33
+ File.join(src_dir, "configure")
34
+ end
35
+
36
+ def fetch(executor)
37
+ case @params[:type]
38
+ when "github"
39
+ repo_url = "https://github.com/#{@params[:repo]}.git"
40
+ executor.mkdir_p src_dir
41
+ executor.system "git", "init", chdir: src_dir
42
+ executor.system "git",
43
+ "remote",
44
+ "add",
45
+ "origin",
46
+ repo_url,
47
+ chdir: src_dir
48
+ executor.system(
49
+ "git",
50
+ "fetch",
51
+ "--depth",
52
+ "1",
53
+ "origin",
54
+ "#{@params[:rev]}:origin/#{@params[:rev]}",
55
+ chdir: src_dir
56
+ )
57
+ executor.system(
58
+ "git",
59
+ "checkout",
60
+ "origin/#{@params[:rev]}",
61
+ chdir: src_dir
62
+ )
63
+ when "tarball"
64
+ executor.mkdir_p src_dir
65
+ tarball_path =
66
+ File.join(File.dirname(src_dir), File.basename(src_dir) + ".tar.gz")
67
+ executor.system("curl", "-L", "-o", tarball_path, @params[:url])
68
+ executor.system(
69
+ "tar",
70
+ "xf",
71
+ tarball_path,
72
+ "-C",
73
+ src_dir,
74
+ "--strip-components=1"
75
+ )
76
+ when "local"
77
+ executor.mkdir_p File.dirname(src_dir)
78
+ executor.cp_r @params[:src], src_dir
79
+ else
80
+ raise "unknown source type: #{@params[:type]}"
81
+ end
82
+ (@params[:patches] || []).each do |patch_path|
83
+ executor.system "patch", "-p1", patch_path, chdir: src_dir
84
+ end
85
+ end
86
+
87
+ def build(executor)
88
+ fetch(executor) unless File.exist?(src_dir)
89
+ unless File.exist?(configure_file)
90
+ executor.system "ruby",
91
+ "tool/downloader.rb",
92
+ "-d",
93
+ "tool",
94
+ "-e",
95
+ "gnu",
96
+ "config.guess",
97
+ "config.sub",
98
+ chdir: src_dir
99
+ executor.system "./autogen.sh", chdir: src_dir
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,45 @@
1
+ require_relative "./product"
2
+
3
+ module RubyWasm
4
+ class WasiVfsProduct < BuildProduct
5
+ WASI_VFS_VERSION = "0.5.0"
6
+
7
+ def initialize(build_dir)
8
+ @build_dir = build_dir
9
+ @need_fetch_lib = ENV["LIB_WASI_VFS_A"].nil?
10
+ end
11
+
12
+ def lib_product_build_dir
13
+ File.join(
14
+ @build_dir,
15
+ "wasm32-unknown-wasi",
16
+ "wasi-vfs-#{WASI_VFS_VERSION}"
17
+ )
18
+ end
19
+
20
+ def lib_wasi_vfs_a
21
+ ENV["LIB_WASI_VFS_A"] || File.join(lib_product_build_dir, "libwasi_vfs.a")
22
+ end
23
+
24
+ def name
25
+ "wasi-vfs-#{WASI_VFS_VERSION}-#{RbConfig::CONFIG["host"]}"
26
+ end
27
+
28
+ def build(executor)
29
+ return if !@need_fetch_lib || File.exist?(lib_wasi_vfs_a)
30
+ require "tmpdir"
31
+ lib_wasi_vfs_url =
32
+ "https://github.com/kateinoigakukun/wasi-vfs/releases/download/v#{WASI_VFS_VERSION}/libwasi_vfs-wasm32-unknown-unknown.zip"
33
+ Dir.mktmpdir do |tmpdir|
34
+ executor.system "curl",
35
+ "-L",
36
+ lib_wasi_vfs_url,
37
+ "-o",
38
+ "#{tmpdir}/libwasi_vfs.zip"
39
+ executor.system "unzip", "#{tmpdir}/libwasi_vfs.zip", "-d", tmpdir
40
+ executor.mkdir_p File.dirname(lib_wasi_vfs_a)
41
+ executor.mv File.join(tmpdir, "libwasi_vfs.a"), lib_wasi_vfs_a
42
+ end
43
+ end
44
+ end
45
+ end