ruby_wasm 2.5.0.pre.1

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 (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