ruby_wasm 2.5.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.clang-format +8 -0
  3. data/CONTRIBUTING.md +124 -0
  4. data/Cargo.lock +2452 -0
  5. data/Cargo.toml +7 -0
  6. data/Gemfile +17 -0
  7. data/LICENSE +21 -0
  8. data/NOTICE +1293 -0
  9. data/README.md +161 -0
  10. data/Rakefile +164 -0
  11. data/Steepfile +24 -0
  12. data/benchmarks/vm_deep_call.rb +55 -0
  13. data/builders/wasm32-unknown-emscripten/Dockerfile +43 -0
  14. data/builders/wasm32-unknown-emscripten/entrypoint.sh +7 -0
  15. data/builders/wasm32-unknown-wasi/Dockerfile +47 -0
  16. data/builders/wasm32-unknown-wasi/entrypoint.sh +7 -0
  17. data/docs/api.md +2 -0
  18. data/docs/cheat_sheet.md +195 -0
  19. data/docs/faq.md +25 -0
  20. data/exe/rbwasm +7 -0
  21. data/ext/.gitignore +2 -0
  22. data/ext/README.md +11 -0
  23. data/ext/extinit.c.erb +32 -0
  24. data/ext/ruby_wasm/Cargo.toml +17 -0
  25. data/ext/ruby_wasm/extconf.rb +6 -0
  26. data/ext/ruby_wasm/src/lib.rs +69 -0
  27. data/lib/ruby_wasm/build/build_params.rb +3 -0
  28. data/lib/ruby_wasm/build/downloader.rb +18 -0
  29. data/lib/ruby_wasm/build/executor.rb +187 -0
  30. data/lib/ruby_wasm/build/product/baseruby.rb +37 -0
  31. data/lib/ruby_wasm/build/product/crossruby.rb +326 -0
  32. data/lib/ruby_wasm/build/product/libyaml.rb +68 -0
  33. data/lib/ruby_wasm/build/product/openssl.rb +88 -0
  34. data/lib/ruby_wasm/build/product/product.rb +39 -0
  35. data/lib/ruby_wasm/build/product/ruby_source.rb +103 -0
  36. data/lib/ruby_wasm/build/product/wasi_vfs.rb +83 -0
  37. data/lib/ruby_wasm/build/product/zlib.rb +68 -0
  38. data/lib/ruby_wasm/build/product.rb +8 -0
  39. data/lib/ruby_wasm/build/toolchain/wit_bindgen.rb +31 -0
  40. data/lib/ruby_wasm/build/toolchain.rb +193 -0
  41. data/lib/ruby_wasm/build.rb +88 -0
  42. data/lib/ruby_wasm/cli.rb +195 -0
  43. data/lib/ruby_wasm/packager/core.rb +156 -0
  44. data/lib/ruby_wasm/packager/file_system.rb +157 -0
  45. data/lib/ruby_wasm/packager.rb +159 -0
  46. data/lib/ruby_wasm/rake_task.rb +58 -0
  47. data/lib/ruby_wasm/util.rb +15 -0
  48. data/lib/ruby_wasm/version.rb +3 -0
  49. data/lib/ruby_wasm.rb +33 -0
  50. data/package-lock.json +9500 -0
  51. data/package.json +12 -0
  52. data/ruby_wasm.gemspec +32 -0
  53. data/sig/open_uri.rbs +4 -0
  54. data/sig/ruby_wasm/build.rbs +322 -0
  55. data/sig/ruby_wasm/cli.rbs +24 -0
  56. data/sig/ruby_wasm/ext.rbs +11 -0
  57. data/sig/ruby_wasm/packager.rbs +91 -0
  58. data/sig/ruby_wasm/util.rbs +5 -0
  59. data/tasks/check.rake +37 -0
  60. data/tasks/ci.rake +152 -0
  61. data/tasks/doc.rake +24 -0
  62. data/tasks/format.rake +34 -0
  63. data/tasks/gem.rake +19 -0
  64. data/tasks/packaging.rake +148 -0
  65. data/tasks/version.rake +38 -0
  66. data/tools/clang-format-diff.sh +18 -0
  67. data/tools/exe/rbminify +12 -0
  68. data/tools/lib/syntax_tree/minify_ruby.rb +63 -0
  69. metadata +115 -0
data/package.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "ruby.wasm",
3
+ "private": true,
4
+ "workspaces": [
5
+ "packages/npm-packages/*"
6
+ ],
7
+ "devDependencies": {
8
+ "@playwright/test": "^1.40.1",
9
+ "@rollup/plugin-json": "^6.0.1",
10
+ "rollup": "^4.6.1"
11
+ }
12
+ }
data/ruby_wasm.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/ruby_wasm/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "ruby_wasm"
7
+ spec.version = RubyWasm::VERSION
8
+ spec.authors = ["Yuta Saito"]
9
+ spec.email = ["kateinoigakukun@gmail.com"]
10
+
11
+ spec.summary = %q{Ruby to WebAssembly toolkit}
12
+ spec.description = %q{Ruby to WebAssembly toolkit. This gem takes Ruby code and Gemfile, and packages them with Ruby runtime into a WebAssembly binary.}
13
+ spec.homepage = "https://github.com/ruby/ruby.wasm"
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 2.6.0"
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = spec.homepage
19
+
20
+ # Specify which files should be added to the gem when it is released.
21
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
+ spec.files = Dir.chdir(__dir__) do
23
+ `git ls-files -z`.split("\x0").reject do |f|
24
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)}) ||
25
+ f.match(%r{\Apackages/})
26
+ end
27
+ end
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+ spec.extensions = ["ext/ruby_wasm/Cargo.toml"]
32
+ end
data/sig/open_uri.rbs ADDED
@@ -0,0 +1,4 @@
1
+ # TODO: Upstream OpenURI sigs to rbs/stdlib
2
+ module OpenURI
3
+ def self.open_uri: [T] (*untyped, **untyped) { (untyped) -> T } -> T
4
+ end
@@ -0,0 +1,322 @@
1
+ module RubyWasm
2
+ VERSION: String
3
+
4
+ interface _Cacheable
5
+ def cache_key: (Digest::SHA256 digest) -> void
6
+ end
7
+
8
+ class Build
9
+ include _Cacheable
10
+
11
+ @target: String
12
+ @build_dir: String
13
+ @rubies_dir: String
14
+ @toolchain: Toolchain
15
+ @libyaml: LibYAMLProduct
16
+ @zlib: ZlibProduct
17
+ @openssl: OpenSSLProduct
18
+ @wasi_vfs: WasiVfsProduct
19
+ @baseruby: BaseRubyProduct
20
+ @crossruby: CrossRubyProduct
21
+ @source: BuildSource
22
+
23
+ attr_reader toolchain: Toolchain
24
+
25
+ def initialize: (
26
+ string name,
27
+ target: String,
28
+ src: Packager::build_source,
29
+ toolchain: Toolchain?,
30
+ build_dir: string,
31
+ rubies_dir: string,
32
+ **untyped
33
+ ) -> void
34
+ def crossruby: () -> CrossRubyProduct
35
+ end
36
+
37
+ class BuildParams
38
+ attr_accessor name: String
39
+ attr_accessor target: String
40
+ attr_accessor default_exts: String
41
+
42
+ def initialize: (name: string, target: string, default_exts: string) -> void
43
+ end
44
+
45
+ class BuildProduct
46
+ def name: -> String
47
+ end
48
+
49
+ class AutoconfProduct < BuildProduct
50
+ @target: String
51
+ @toolchain: Toolchain
52
+
53
+ def initialize: (String target, Toolchain toolchain) -> void
54
+ def system_triplet_args: -> Array[String]
55
+ | -> Array[String]
56
+ def tools_args: -> Array[String]
57
+ | -> Array[String]
58
+ def configure_args: -> Array[String]
59
+ | -> Array[String]
60
+ end
61
+
62
+ class BuildSource < BuildProduct
63
+ @params: Hash[untyped, untyped]
64
+ @build_dir: String
65
+
66
+ def initialize: (untyped params, String build_dir) -> void
67
+ def name: -> String
68
+ def cache_key: (Digest::SHA256 digest) -> void
69
+ def src_dir: -> String
70
+ def configure_file: -> String
71
+ def fetch: (BuildExecutor executor) -> void
72
+ def build: (BuildExecutor executor) -> void
73
+ end
74
+
75
+ class BaseRubyProduct < BuildProduct
76
+ @build_dir: String
77
+ @source: BuildSource
78
+ @channel: String
79
+
80
+ def initialize: (String build_dir, BuildSource source) -> void
81
+ def product_build_dir: -> String
82
+ def install_dir: -> String
83
+ def name: -> String
84
+ def build: (BuildExecutor executor) -> void
85
+ end
86
+
87
+ class ZlibProduct < AutoconfProduct
88
+ ZLIB_VERSION: String
89
+ @build_dir: String
90
+
91
+ attr_reader target: String
92
+ def initialize: (String build_dir, String target, Toolchain toolchain) -> void
93
+ def product_build_dir: -> String
94
+ def destdir: -> String
95
+ def install_root: -> String
96
+ def name: -> String
97
+ def configure_args: -> Array[String]
98
+ def build: (BuildExecutor executor) -> void
99
+ end
100
+
101
+ class LibYAMLProduct < AutoconfProduct
102
+ LIBYAML_VERSION: String
103
+ @build_dir: String
104
+
105
+ attr_reader target: String
106
+ def initialize: (String build_dir, String target, Toolchain toolchain) -> void
107
+ def product_build_dir: -> String
108
+ def destdir: -> String
109
+ def install_root: -> String
110
+ def name: -> String
111
+ def build: (BuildExecutor executor) -> void
112
+ end
113
+
114
+ class OpenSSLProduct < AutoconfProduct
115
+ OPENSSL_VERSION: String
116
+ @build_dir: String
117
+
118
+ attr_reader target: String
119
+ def initialize: (String build_dir, String target, Toolchain toolchain) -> void
120
+ def product_build_dir: -> String
121
+ def destdir: -> String
122
+ def install_root: -> String
123
+ def name: -> String
124
+ def configure_args: -> Array[String]
125
+ def build: (BuildExecutor executor) -> void
126
+ end
127
+
128
+ class WasiVfsProduct < BuildProduct
129
+ WASI_VFS_VERSION: String
130
+ @build_dir: String
131
+ @need_fetch_lib: bool
132
+ @cli_path: String
133
+ @need_fetch_cli: bool
134
+
135
+ def initialize: (String build_dir) -> void
136
+ def lib_product_build_dir: -> String
137
+ def lib_wasi_vfs_a: -> String
138
+ def cli_product_build_dir: -> String
139
+ def cli_bin_path: -> String
140
+ def name: -> String
141
+ def build: (BuildExecutor executor) -> void
142
+ def install_cli: -> bool?
143
+ def cli_download_url: -> String
144
+ end
145
+
146
+ class CrossRubyExtProduct < BuildProduct
147
+ include RubyWasm::_Cacheable
148
+
149
+ @toolchain: Toolchain
150
+ @srcdir: String
151
+ @ext_relative_path: String
152
+
153
+ attr_reader name: String
154
+ def initialize: (String srcdir, Toolchain toolchain, ?ext_relative_path: String?) -> void
155
+ def product_build_dir: (CrossRubyProduct crossruby) -> String
156
+ def linklist: (CrossRubyProduct crossruby) -> String
157
+ def metadata_json: (CrossRubyProduct crossruby) -> String
158
+ def feature_name: (CrossRubyProduct crossruby) -> String
159
+
160
+ def make_args: (CrossRubyProduct crossruby) -> Array[String]
161
+ def build: (BuildExecutor executor, CrossRubyProduct crossruby) -> void
162
+ def do_extconf: (BuildExecutor executor, CrossRubyProduct crossruby) -> void
163
+ def do_install_rb: (BuildExecutor executor, CrossRubyProduct crossruby) -> void
164
+ end
165
+
166
+ class CrossRubyProduct < AutoconfProduct
167
+ include RubyWasm::_Cacheable
168
+
169
+ @params: BuildParams
170
+ @rubies_dir: String
171
+ @build_dir: String
172
+ @baseruby: BaseRubyProduct
173
+ @libyaml: LibYAMLProduct
174
+ @zlib: ZlibProduct
175
+ @openssl: OpenSSLProduct
176
+ @wasi_vfs: WasiVfsProduct
177
+
178
+ attr_reader source: BuildSource
179
+ attr_reader toolchain: Toolchain
180
+ attr_accessor user_exts: Array[CrossRubyExtProduct]
181
+ attr_accessor wasmoptflags: Array[String]
182
+ attr_accessor cppflags: Array[String]
183
+ attr_accessor cflags: Array[String]
184
+ attr_accessor ldflags: Array[String]
185
+ attr_accessor debugflags: Array[String]
186
+ attr_accessor xcflags: Array[String]
187
+ attr_accessor xldflags: Array[String]
188
+ def initialize: (BuildParams params, String build_dir, String rubies_dir, BaseRubyProduct baseruby, BuildSource source, Toolchain toolchain) -> void
189
+ def configure: (BuildExecutor executor, ?reconfigure: bool) -> void
190
+ def build_exts: (BuildExecutor executor) -> void
191
+ def build: (BuildExecutor executor, ?remake: bool, ?reconfigure: bool) -> void
192
+ def clean: (BuildExecutor executor) -> void
193
+ def name: -> String
194
+ def build_dir: -> String
195
+ def ext_build_dir: -> String
196
+ def with_libyaml: (LibYAMLProduct libyaml) -> LibYAMLProduct
197
+ def with_zlib: (ZlibProduct zlib) -> ZlibProduct
198
+ def with_wasi_vfs: (WasiVfsProduct wasi_vfs) -> WasiVfsProduct
199
+ def with_openssl: (OpenSSLProduct openssl) -> OpenSSLProduct
200
+ def dest_dir: -> String
201
+ def artifact: -> String
202
+ def extinit_obj: -> String
203
+ def extinit_c_erb: -> String
204
+ def baseruby_path: -> String
205
+ def configure_args: (String build_triple, Toolchain toolchain) -> Array[String]
206
+ end
207
+
208
+ class WitBindgen
209
+ @build_dir: String
210
+ @tool_dir: String
211
+ @revision: String
212
+
213
+ attr_reader bin_path: String
214
+ def initialize: (build_dir: String, ?revision: String) -> void
215
+ def install: -> void
216
+ end
217
+
218
+ class Toolchain
219
+ @tools: Hash[untyped, untyped]
220
+ @tools_cache: Hash[untyped, untyped]
221
+
222
+ attr_reader name: String
223
+ def initialize: -> void
224
+ def find_tool: (Symbol name) -> String
225
+ def check_envvar: (untyped name) -> void
226
+ def self.get: (String target, ?String? build_dir) -> (Toolchain)
227
+ def self.find_path: (String command) -> String?
228
+ def self.check_executable: (String command) -> String
229
+ def cc: -> String
230
+ def ranlib: -> String
231
+ def ld: -> String
232
+ def ar: -> String
233
+
234
+ def install: -> void
235
+ end
236
+
237
+ class WASISDK < Toolchain
238
+ @wasm_opt_path: String
239
+ @need_fetch_wasi_sdk: bool
240
+ @need_fetch_binaryen: bool
241
+ @tools: Hash[Symbol, String]
242
+ @wasi_sdk_path: String
243
+ @binaryen_version: Integer
244
+ @version_major: Integer
245
+ @version_minor: Integer
246
+ @binaryen_path: String
247
+
248
+ def initialize: (?String? wasi_sdk_path, ?build_dir: String?, ?version_major: Integer, ?version_minor: Integer, ?binaryen_version: Integer) -> void
249
+ def find_tool: (Symbol name) -> String
250
+ def wasm_opt: -> String
251
+ def wasi_sdk_path: -> String
252
+ def download_url: (Integer? version_major, Integer? version_minor) -> String
253
+ def binaryen_download_url: (Integer? version) -> String
254
+ def install_wasi_sdk: -> void
255
+ def install_binaryen: -> void
256
+ end
257
+
258
+ class Emscripten < Toolchain
259
+ @tools: Hash[Symbol, String]
260
+
261
+ def initialize: -> void
262
+ def find_tool: (Symbol name) -> String
263
+ end
264
+
265
+ class BuildExecutor
266
+ @verbose: bool
267
+ @github_actions_markup: bool
268
+ @process_count: Integer
269
+ @start_times: Hash[[Class, String], Time]
270
+
271
+ attr_reader process_count: Integer
272
+
273
+ def initialize: (?verbose: bool) -> void
274
+ def system: (*_ToS args, ?chdir: String?, ?env: Hash[String, String]?) -> void
275
+ def rm_rf: (FileUtils::pathlist list) -> void
276
+ def rm_f: (FileUtils::pathlist list) -> void
277
+ def cp_r: (FileUtils::pathlist src, path dest) -> void
278
+ def mv: (FileUtils::pathlist src, path dest) -> void
279
+ def mkdir_p: (FileUtils::pathlist list) -> void
280
+ def write: (String path, _ToS data) -> void
281
+
282
+ def begin_section: (Class klass, String name, String note) -> void
283
+ def end_section: (Class klass, String name) -> void
284
+
285
+ private def _print_command: (Array[_ToS] command, Hash[String, String]? env) -> void
286
+ end
287
+
288
+ class StatusPrinter
289
+ @mutex: Mutex
290
+ @counter: Integer
291
+ @indicators: String
292
+
293
+ def initialize: () -> void
294
+ def stdout: (String message) -> void
295
+ def stderr: (String message) -> void
296
+ def done: () -> void
297
+ end
298
+
299
+ class Downloader
300
+ def format_size: (Integer size) -> String
301
+
302
+ def download: (String url, String dest, String message) -> void
303
+ end
304
+
305
+ class BuildTask
306
+ @build_dir: String
307
+ @rubies_dir: String
308
+ @openssl: OpenSSLProduct
309
+
310
+ attr_accessor name: String
311
+ attr_reader source: BuildSource
312
+ attr_reader target: String
313
+ attr_reader toolchain: Toolchain
314
+ attr_reader libyaml: LibYAMLProduct
315
+ attr_reader zlib: ZlibProduct
316
+ attr_reader wasi_vfs: WasiVfsProduct
317
+ attr_reader baseruby: BaseRubyProduct
318
+ attr_reader crossruby: CrossRubyProduct
319
+ def initialize: (String name, target: String, src: untyped, ?toolchain: Toolchain?, ?build_dir: String?, ?rubies_dir: String?, **untyped) -> void
320
+ def hexdigest: -> String
321
+ end
322
+ end
@@ -0,0 +1,24 @@
1
+ module RubyWasm
2
+ class CLI
3
+ DEFAULT_RUBIES_DIR: string
4
+
5
+ @stdout: IO
6
+ @stderr: IO
7
+
8
+ def initialize: (stdout: IO, stderr: IO) -> void
9
+
10
+ def build: (Array[String] args) -> void
11
+
12
+ private
13
+
14
+ def build_config: (Hash[untyped, untyped] options) -> Hash[untyped, untyped]
15
+
16
+ def derive_packager: (Hash[untyped, untyped] options) -> Packager
17
+ def do_print_ruby_cache_key: (Packager) -> void
18
+ def do_build: (BuildExecutor, string tmpdir, Packager, Hash[untyped, untyped] options) -> void
19
+ end
20
+
21
+ self.@logger: Logger?
22
+ def self.logger: () -> Logger
23
+ attr_accessor self.log_level: Symbol
24
+ end
@@ -0,0 +1,11 @@
1
+ module RubyWasmExt
2
+ def self.preinitialize: (Array[Integer] module_bytes) -> Array[Integer]
3
+
4
+ class WasiVfs
5
+ def initialize: () -> void
6
+
7
+ def map_dir: (String guest_path, String host_path) -> void
8
+
9
+ def pack: (Array[Integer] module_bytes) -> Array[Integer]
10
+ end
11
+ end
@@ -0,0 +1,91 @@
1
+
2
+ class RubyWasm::Packager
3
+ @definition: untyped
4
+ @config: Hash[untyped, untyped]
5
+
6
+ def initialize: (untyped?, Hash[untyped, untyped]?) -> void
7
+
8
+ def package: (RubyWasm::BuildExecutor, string dest_dir, untyped options) -> Array[Integer]
9
+
10
+ @ruby_core_build: RubyWasm::Packager::Core?
11
+ def ruby_core_build: () -> RubyWasm::Packager::Core
12
+
13
+ EXCLUDED_GEMS: Array[string]
14
+
15
+ def specs: () -> Array[untyped]
16
+ def support_dynamic_linking?: () -> bool
17
+
18
+ def root: () -> string
19
+
20
+ type build_source = Hash[Symbol, (String | Array[String])]
21
+ def self.build_source_aliases: (string root) -> Hash[string, build_source]
22
+
23
+ ALL_DEFAULT_EXTS: string
24
+
25
+ def build_options: () -> Hash[Symbol, untyped]
26
+ def full_build_options: () -> Hash[Symbol, untyped]
27
+
28
+ class Core
29
+ include RubyWasm::_Cacheable
30
+
31
+ @packager: RubyWasm::Packager
32
+ def initialize: (RubyWasm::Packager) -> void
33
+ def build: (RubyWasm::BuildExecutor, untyped options) -> String
34
+
35
+ extend Forwardable
36
+
37
+ def artifact: () -> string
38
+
39
+ private
40
+
41
+ @build_strategy: BuildStrategy?
42
+ def build_strategy: () -> BuildStrategy
43
+
44
+ class BuildStrategy
45
+ @packager: RubyWasm::Packager
46
+ def initialize: (RubyWasm::Packager) -> void
47
+ def build: (RubyWasm::BuildExecutor, untyped options) -> String
48
+ def specs_with_extensions: () -> Array[[untyped, Array[string]]]
49
+ end
50
+
51
+ class DynamicLinking < RubyWasm::Packager::Core::BuildStrategy
52
+ end
53
+
54
+ class StaticLinking < RubyWasm::Packager::Core::BuildStrategy
55
+ @build: RubyWasm::Build
56
+ def derive_build: () -> RubyWasm::Build
57
+ @user_exts: Array[RubyWasm::CrossRubyExtProduct]?
58
+ def user_exts: (RubyWasm::Build) -> Array[RubyWasm::CrossRubyExtProduct]
59
+
60
+ def name: () -> string
61
+ end
62
+ end
63
+
64
+ class FileSystem
65
+ @dest_dir: string
66
+ @packager: RubyWasm::Packager
67
+ @ruby_root: string
68
+
69
+ def initialize: (string dest_dir, RubyWasm::Packager) -> void
70
+ def package_ruby_root: (String tarball, RubyWasm::BuildExecutor) -> void
71
+ def remove_stdlib: (RubyWasm::BuildExecutor) -> void
72
+ def package_gems: () -> void
73
+
74
+ def setup_rb_content: () -> String
75
+
76
+ def remove_non_runtime_files: (RubyWasm::BuildExecutor) -> void
77
+
78
+ def bundle_dir: () -> String
79
+ def ruby_root: () -> string
80
+
81
+ private
82
+
83
+ def each_gem_content_path: () { (String, String) -> void } -> void
84
+ def each_gem_require_path: () { (String, String) -> void } -> void
85
+ def each_gem_extension_path: () { (String, String) -> void } -> void
86
+
87
+ def bundle_relative_path: () -> String
88
+ def ruby_version: () -> String
89
+ def rubyarchdir: () -> String
90
+ end
91
+ end
@@ -0,0 +1,5 @@
1
+ module RubyWasm
2
+ module SizeFormatter
3
+ def self?.format: (Integer size) -> String
4
+ end
5
+ end
data/tasks/check.rake ADDED
@@ -0,0 +1,37 @@
1
+ namespace :check do
2
+ wit_bindgen = RubyWasm::WitBindgen.new(build_dir: "build")
3
+ task :install_wit_bindgen do
4
+ wit_bindgen.install
5
+ end
6
+ task bindgen_c: :install_wit_bindgen do
7
+ wits = [
8
+ %w[packages/gems/js/ext/witapi/bindgen/rb-abi-guest.wit --export],
9
+ %w[packages/gems/js/ext/js/bindgen/rb-js-abi-host.wit --import]
10
+ ]
11
+ wits.each do |wit|
12
+ path, mode = wit
13
+ sh "#{wit_bindgen.bin_path} guest c #{mode} #{path} --out-dir #{File.dirname(path)}"
14
+ end
15
+ end
16
+
17
+ task bindgen_js: :install_wit_bindgen do
18
+ sh *[
19
+ wit_bindgen.bin_path,
20
+ "host",
21
+ "js",
22
+ "--import",
23
+ "packages/gems/js/ext/witapi/bindgen/rb-abi-guest.wit",
24
+ "--export",
25
+ "packages/gems/js/ext/js/bindgen/rb-js-abi-host.wit",
26
+ "--out-dir",
27
+ "packages/npm-packages/ruby-wasm-wasi/src/bindgen"
28
+ ]
29
+ end
30
+
31
+ desc "Check wit-bindgen'ed sources are up-to-date"
32
+ task bindgen: %i[bindgen_c bindgen_js]
33
+
34
+ task :type do
35
+ sh "bundle exec steep check"
36
+ end
37
+ end
data/tasks/ci.rake ADDED
@@ -0,0 +1,152 @@
1
+ def latest_build_sources
2
+ BUILD_SOURCES
3
+ .filter_map do |name|
4
+ src = RubyWasm::Packager.build_source_aliases(LIB_ROOT)[name]
5
+ case src[:type]
6
+ when "github"
7
+ url = "repos/#{src[:repo]}/commits/#{src[:rev]}"
8
+ revision = JSON.parse(`gh api #{url}`)
9
+ [name, revision["sha"]]
10
+ when "tarball"
11
+ nil
12
+ else
13
+ raise "#{src[:type]} is not supported to pin source revision"
14
+ end
15
+ end
16
+ .to_h
17
+ end
18
+
19
+ def release_note
20
+ output = <<EOS
21
+ | channel | source |
22
+ |:-------:|:------:|
23
+ EOS
24
+
25
+ BUILD_SOURCES.each do |name|
26
+ source = RubyWasm::Packager.build_source_aliases(LIB_ROOT)[name]
27
+ case source[:type]
28
+ when "github"
29
+ output +=
30
+ "| #{name} | [`#{source[:repo]}@#{source[:rev]}`](https://github.com/ruby/ruby/tree/#{source[:rev]}) |\n"
31
+ when "tarball"
32
+ output += "| #{name} | #{source[:url]} |\n"
33
+ else
34
+ raise "unknown source type: #{source[:type]}"
35
+ end
36
+ end
37
+ output
38
+ end
39
+
40
+ def sh_or_warn(*cmd)
41
+ sh *cmd do |ok, status|
42
+ unless ok
43
+ warn "Command failed with status (#{status.exitstatus}): #{cmd.join ""}"
44
+ end
45
+ end
46
+ end
47
+
48
+ def rake_task_matrix
49
+ require "pathname"
50
+ ruby_cache_keys = {}
51
+ BUILD_TASKS.each { |build| ruby_cache_keys[build.name] = build.hexdigest }
52
+ build_entries =
53
+ BUILD_TASKS.map do |build|
54
+ {
55
+ task: "build:#{build.name}",
56
+ artifact:
57
+ Pathname.new(build.artifact).relative_path_from(LIB_ROOT).to_s,
58
+ artifact_name: File.basename(build.artifact, ".tar.gz"),
59
+ builder: build.target,
60
+ rubies_cache_key: ruby_cache_keys[build.name]
61
+ }
62
+ end
63
+ npm_entries =
64
+ NPM_PACKAGES.map do |pkg|
65
+ entry = {
66
+ task: "npm:#{pkg[:name]}",
67
+ prerelease: "npm:configure_prerelease",
68
+ artifact: "packages/npm-packages/#{pkg[:name]}/#{pkg[:name]}-*.tgz",
69
+ artifact_name: "npm-#{pkg[:name]}",
70
+ builder: pkg[:target],
71
+ rubies_cache_key: npm_pkg_rubies_cache_key(pkg)
72
+ }
73
+ # Run tests only if the package has 'test' script
74
+ package_json =
75
+ JSON.parse(
76
+ File.read("packages/npm-packages/#{pkg[:name]}/package.json")
77
+ )
78
+ if package_json["scripts"] && package_json["scripts"]["test"]
79
+ entry[:test] = "npm:#{pkg[:name]}:check"
80
+ end
81
+ entry
82
+ end
83
+ standalone_entries =
84
+ STANDALONE_PACKAGES.map do |pkg|
85
+ {
86
+ task: "standalone:#{pkg[:name]}",
87
+ artifact: "packages/standalone/#{pkg[:name]}/dist",
88
+ artifact_name: "standalone-#{pkg[:name]}",
89
+ builder: "wasm32-unknown-wasi",
90
+ rubies_cache_key: ruby_cache_keys[pkg[:build]]
91
+ }
92
+ end
93
+ { build: build_entries, npm: npm_entries, standalone: standalone_entries }
94
+ end
95
+
96
+ namespace :ci do
97
+ task :rake_task_matrix do
98
+ print JSON.generate(rake_task_matrix.flat_map { |_, entries| entries })
99
+ end
100
+
101
+ task :pin_build_manifest do
102
+ content = JSON.generate({ ruby_revisions: latest_build_sources })
103
+ File.write("build_manifest.json", content)
104
+ end
105
+
106
+ desc "Fetch artifacts of a run of GitHub Actions"
107
+ task :fetch_artifacts, [:run_id] do |t, args|
108
+ RubyWasm::Toolchain.check_executable("gh")
109
+
110
+ artifacts =
111
+ JSON.load(
112
+ `gh api repos/{owner}/{repo}/actions/runs/#{args[:run_id]}/artifacts`
113
+ )
114
+ matrix = rake_task_matrix.flat_map { |_, entries| entries }
115
+ release_artifacts = matrix.map { |entry| entry[:artifact_name] }
116
+ artifacts =
117
+ artifacts["artifacts"].filter { release_artifacts.include?(_1["name"]) }
118
+ mkdir_p "release"
119
+ Dir.chdir("release") do
120
+ artifacts.each do |artifact|
121
+ url = artifact["archive_download_url"]
122
+ sh "gh api #{url} > #{artifact["name"]}.zip"
123
+ mkdir_p artifact["name"]
124
+ sh "unzip #{artifact["name"]}.zip -d #{artifact["name"]}"
125
+ rm "#{artifact["name"]}.zip"
126
+ end
127
+ end
128
+ end
129
+
130
+ desc "Publish artifacts as a GitHub Release"
131
+ task :publish, [:tag] do |t, args|
132
+ RubyWasm::Toolchain.check_executable("gh")
133
+
134
+ nightly = /^\d{4}-\d{2}-\d{2}-.$/.match?(args[:tag])
135
+ matrix = rake_task_matrix
136
+ files =
137
+ matrix
138
+ .flat_map { |_, entries| entries }
139
+ .map { |entry| "release/#{entry[:artifact_name]}/*" }
140
+ File.open("release/note.md", "w") { |f| f.print release_note }
141
+ matrix[:npm].each do |task|
142
+ artifact = task[:artifact_name]
143
+ tarball = Dir.glob("release/#{artifact}/*")
144
+ next if tarball.empty?
145
+ tarball = tarball[0]
146
+ # tolerate failure as a case that has already been released
147
+ npm_tag = nightly ? "next" : "latest"
148
+ sh_or_warn %Q(npm publish --tag #{npm_tag} #{tarball})
149
+ end
150
+ sh %Q(gh release create #{args[:tag]} --title #{args[:tag]} --notes-file release/note.md #{nightly ? "--prerelease" : ""} #{files.join(" ")})
151
+ end
152
+ end