ruby_wasm 2.5.0-x86_64-linux

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 +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.0/ruby_wasm.so +0 -0
  23. data/lib/ruby_wasm/3.1/ruby_wasm.so +0 -0
  24. data/lib/ruby_wasm/3.2/ruby_wasm.so +0 -0
  25. data/lib/ruby_wasm/build/build_params.rb +3 -0
  26. data/lib/ruby_wasm/build/downloader.rb +18 -0
  27. data/lib/ruby_wasm/build/executor.rb +187 -0
  28. data/lib/ruby_wasm/build/product/baseruby.rb +37 -0
  29. data/lib/ruby_wasm/build/product/crossruby.rb +330 -0
  30. data/lib/ruby_wasm/build/product/libyaml.rb +68 -0
  31. data/lib/ruby_wasm/build/product/openssl.rb +88 -0
  32. data/lib/ruby_wasm/build/product/product.rb +39 -0
  33. data/lib/ruby_wasm/build/product/ruby_source.rb +103 -0
  34. data/lib/ruby_wasm/build/product/wasi_vfs.rb +45 -0
  35. data/lib/ruby_wasm/build/product/zlib.rb +68 -0
  36. data/lib/ruby_wasm/build/product.rb +8 -0
  37. data/lib/ruby_wasm/build/toolchain/wit_bindgen.rb +31 -0
  38. data/lib/ruby_wasm/build/toolchain.rb +193 -0
  39. data/lib/ruby_wasm/build.rb +88 -0
  40. data/lib/ruby_wasm/cli.rb +217 -0
  41. data/lib/ruby_wasm/packager/core.rb +156 -0
  42. data/lib/ruby_wasm/packager/file_system.rb +158 -0
  43. data/lib/ruby_wasm/packager.rb +159 -0
  44. data/lib/ruby_wasm/rake_task.rb +59 -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 +33 -0
  48. data/package-lock.json +9500 -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 +151 -0
  56. data/rakelib/version.rake +40 -0
  57. data/sig/open_uri.rbs +4 -0
  58. data/sig/ruby_wasm/build.rbs +318 -0
  59. data/sig/ruby_wasm/cli.rbs +27 -0
  60. data/sig/ruby_wasm/ext.rbs +13 -0
  61. data/sig/ruby_wasm/packager.rbs +91 -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,68 @@
1
+ require_relative "./product"
2
+
3
+ module RubyWasm
4
+ class ZlibProduct < AutoconfProduct
5
+ attr_reader :target
6
+
7
+ ZLIB_VERSION = "1.3.1"
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, "zlib-#{ZLIB_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
+ "zlib-#{ZLIB_VERSION}-#{target}"
29
+ end
30
+
31
+ def configure_args
32
+ args = %w[CHOST=linux]
33
+
34
+ args + tools_args
35
+ end
36
+
37
+ def build(executor)
38
+ return if Dir.exist?(install_root)
39
+
40
+ executor.mkdir_p File.dirname(product_build_dir)
41
+ executor.rm_rf product_build_dir
42
+ executor.mkdir_p product_build_dir
43
+
44
+ tarball_path = File.join(product_build_dir, "zlib-#{ZLIB_VERSION}.tar.gz")
45
+ executor.system "curl",
46
+ "-o",
47
+ tarball_path,
48
+ "-L",
49
+ "https://github.com/madler/zlib/releases/download/v#{ZLIB_VERSION}/zlib-#{ZLIB_VERSION}.tar.gz"
50
+ executor.system "tar",
51
+ "xzf",
52
+ tarball_path,
53
+ "-C",
54
+ product_build_dir,
55
+ "--strip-components=1"
56
+
57
+ executor.system "env",
58
+ *configure_args,
59
+ "./configure",
60
+ "--static",
61
+ 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,8 @@
1
+ require_relative "product/product"
2
+ require_relative "product/ruby_source"
3
+ require_relative "product/baseruby"
4
+ require_relative "product/zlib"
5
+ require_relative "product/libyaml"
6
+ require_relative "product/openssl"
7
+ require_relative "product/wasi_vfs"
8
+ require_relative "product/crossruby"
@@ -0,0 +1,31 @@
1
+ module RubyWasm
2
+ class WitBindgen
3
+ attr_reader :bin_path
4
+
5
+ def initialize(
6
+ build_dir:,
7
+ revision: "251e84b89121751f79ac268629e9285082b2596d"
8
+ )
9
+ @build_dir = build_dir
10
+ @tool_dir = File.join(@build_dir, "toolchain", "wit-bindgen")
11
+ @bin_path = File.join(@tool_dir, "bin", "wit-bindgen")
12
+ @revision = revision
13
+ end
14
+
15
+ def install
16
+ return if File.exist?(@bin_path)
17
+ RubyWasm::Toolchain.check_executable("cargo")
18
+ Kernel.system(
19
+ "cargo",
20
+ "install",
21
+ "--git",
22
+ "https://github.com/bytecodealliance/wit-bindgen",
23
+ "--rev",
24
+ @revision,
25
+ "--root",
26
+ @tool_dir,
27
+ "wit-bindgen-cli"
28
+ )
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,193 @@
1
+ require_relative "./toolchain/wit_bindgen"
2
+
3
+ module RubyWasm
4
+ class Toolchain
5
+ attr_reader :name
6
+
7
+ def initialize
8
+ @tools = {}
9
+ end
10
+
11
+ def find_tool(name)
12
+ raise "not implemented"
13
+ end
14
+
15
+ def check_envvar(name)
16
+ raise "missing environment variable: #{name}" if ENV[name].nil?
17
+ end
18
+
19
+ def self.get(target, build_dir = nil)
20
+ case target
21
+ when "wasm32-unknown-wasi"
22
+ return RubyWasm::WASISDK.new(build_dir: build_dir)
23
+ when "wasm32-unknown-emscripten"
24
+ return RubyWasm::Emscripten.new
25
+ else
26
+ raise "unknown target: #{target}"
27
+ end
28
+ end
29
+
30
+ def self.find_path(command)
31
+ (ENV["PATH"] || "")
32
+ .split(File::PATH_SEPARATOR)
33
+ .each do |path_dir|
34
+ bin_path = File.join(path_dir, command)
35
+ return bin_path if File.executable?(bin_path)
36
+ end
37
+ nil
38
+ end
39
+
40
+ def self.check_executable(command)
41
+ tool = find_path(command)
42
+ raise "missing executable: #{command}" unless tool
43
+ tool
44
+ end
45
+
46
+ %i[cc ranlib ld ar].each do |name|
47
+ define_method(name) do
48
+ @tools_cache ||= {}
49
+ @tools_cache[name] ||= find_tool(name)
50
+ @tools_cache[name]
51
+ end
52
+ end
53
+ end
54
+
55
+ class WASISDK < Toolchain
56
+ def initialize(
57
+ wasi_sdk_path = ENV["WASI_SDK_PATH"],
58
+ build_dir: nil,
59
+ version_major: 20,
60
+ version_minor: 0,
61
+ binaryen_version: 108
62
+ )
63
+ @wasm_opt_path = Toolchain.find_path("wasm-opt")
64
+ @need_fetch_wasi_sdk = wasi_sdk_path.nil?
65
+ @need_fetch_binaryen = @wasm_opt_path.nil?
66
+
67
+ if @need_fetch_wasi_sdk
68
+ if build_dir.nil?
69
+ raise "build_dir is required when WASI_SDK_PATH is not set"
70
+ end
71
+ wasi_sdk_path = File.join(build_dir, "toolchain", "wasi-sdk")
72
+ @version_major = version_major
73
+ @version_minor = version_minor
74
+ end
75
+
76
+ if @need_fetch_binaryen
77
+ if build_dir.nil?
78
+ raise "build_dir is required when wasm-opt not installed in PATH"
79
+ end
80
+ @binaryen_path = File.join(build_dir, "toolchain", "binaryen")
81
+ @binaryen_version = binaryen_version
82
+ @wasm_opt_path = File.join(@binaryen_path, "bin", "wasm-opt")
83
+ end
84
+
85
+ @tools = {
86
+ cc: "#{wasi_sdk_path}/bin/clang",
87
+ ld: "#{wasi_sdk_path}/bin/clang",
88
+ ar: "#{wasi_sdk_path}/bin/llvm-ar",
89
+ ranlib: "#{wasi_sdk_path}/bin/llvm-ranlib"
90
+ }
91
+ @wasi_sdk_path = wasi_sdk_path
92
+ @name = "wasi-sdk"
93
+ end
94
+
95
+ def find_tool(name)
96
+ if !File.exist?(@tools[name]) && !ENV["WASI_SDK_PATH"].nil?
97
+ raise "missing tool '#{name}' at #{@tools[name]}"
98
+ end
99
+ @tools[name]
100
+ end
101
+
102
+ def wasm_opt
103
+ @wasm_opt_path
104
+ end
105
+
106
+ def wasi_sdk_path
107
+ @wasi_sdk_path
108
+ end
109
+
110
+ def download_url(version_major, version_minor)
111
+ version = "#{version_major}.#{version_minor}"
112
+ assets = [
113
+ [/x86_64-linux/, "wasi-sdk-#{version}-linux.tar.gz"],
114
+ [/(arm64e?|x86_64)-darwin/, "wasi-sdk-#{version}-macos.tar.gz"]
115
+ ]
116
+ asset = assets.find { |os, _| os =~ RUBY_PLATFORM }&.at(1)
117
+ if asset.nil?
118
+ raise "unsupported platform for fetching WASI SDK: #{RUBY_PLATFORM}"
119
+ end
120
+ "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-#{version_major}/#{asset}"
121
+ end
122
+
123
+ def binaryen_download_url(version)
124
+ assets = [
125
+ [
126
+ /x86_64-linux/,
127
+ "binaryen-version_#{@binaryen_version}-x86_64-linux.tar.gz"
128
+ ],
129
+ [
130
+ /x86_64-darwin/,
131
+ "binaryen-version_#{@binaryen_version}-x86_64-macos.tar.gz"
132
+ ],
133
+ [
134
+ /arm64e?-darwin/,
135
+ "binaryen-version_#{@binaryen_version}-arm64-macos.tar.gz"
136
+ ]
137
+ ]
138
+ asset = assets.find { |os, _| os =~ RUBY_PLATFORM }&.at(1)
139
+ if asset.nil?
140
+ raise "unsupported platform for fetching Binaryen: #{RUBY_PLATFORM}"
141
+ end
142
+ "https://github.com/WebAssembly/binaryen/releases/download/version_#{@binaryen_version}/#{asset}"
143
+ end
144
+
145
+ def install_wasi_sdk
146
+ return unless @need_fetch_wasi_sdk
147
+ wasi_sdk_tarball =
148
+ File.join(File.dirname(@wasi_sdk_path), "wasi-sdk.tar.gz")
149
+ unless File.exist? wasi_sdk_tarball
150
+ FileUtils.mkdir_p File.dirname(wasi_sdk_tarball)
151
+ system "curl -L -o #{wasi_sdk_tarball} #{self.download_url(@version_major, @version_minor)}"
152
+ end
153
+ unless File.exist? @wasi_sdk_path
154
+ FileUtils.mkdir_p @wasi_sdk_path
155
+ system "tar -C #{@wasi_sdk_path} --strip-component 1 -xzf #{wasi_sdk_tarball}"
156
+ end
157
+ end
158
+
159
+ def install_binaryen
160
+ return unless @need_fetch_binaryen
161
+ binaryen_tarball = File.expand_path("../binaryen.tar.gz", @binaryen_path)
162
+ unless File.exist? binaryen_tarball
163
+ FileUtils.mkdir_p File.dirname(binaryen_tarball)
164
+ system "curl -L -o #{binaryen_tarball} #{self.binaryen_download_url(@binaryen_version)}"
165
+ end
166
+
167
+ unless File.exist? @binaryen_path
168
+ FileUtils.mkdir_p @binaryen_path
169
+ system "tar -C #{@binaryen_path} --strip-component 1 -xzf #{binaryen_tarball}"
170
+ end
171
+ end
172
+
173
+ def install
174
+ install_wasi_sdk
175
+ install_binaryen
176
+ end
177
+ end
178
+
179
+ class Emscripten < Toolchain
180
+ def initialize
181
+ @tools = { cc: "emcc", ld: "emcc", ar: "emar", ranlib: "emranlib" }
182
+ @name = "emscripten"
183
+ end
184
+
185
+ def install
186
+ end
187
+
188
+ def find_tool(name)
189
+ Toolchain.check_executable(@tools[name])
190
+ @tools[name]
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,88 @@
1
+ require_relative "build/build_params"
2
+ require_relative "build/product"
3
+ require_relative "build/toolchain"
4
+ require_relative "build/executor"
5
+
6
+ class RubyWasm::Build
7
+ # Source to build from.
8
+ attr_reader :source
9
+
10
+ # Target to build for.
11
+ attr_reader :target
12
+
13
+ # Toolchain for the build.
14
+ # Defaults to the Toolchain.get for the target.
15
+ attr_reader :toolchain
16
+
17
+ # LibYAML product to build.
18
+ attr_reader :libyaml
19
+
20
+ # zlib product to build.
21
+ attr_reader :zlib
22
+
23
+ # wasi-vfs product used by the crossruby.
24
+ attr_reader :wasi_vfs
25
+
26
+ # BaseRuby product to build.
27
+ attr_reader :baseruby
28
+
29
+ # CrossRuby product to build.
30
+ attr_reader :crossruby
31
+
32
+ def initialize(
33
+ name,
34
+ target:,
35
+ src:,
36
+ toolchain:,
37
+ build_dir:,
38
+ rubies_dir:,
39
+ **options
40
+ )
41
+ @target = target
42
+ @build_dir = build_dir
43
+ @rubies_dir = rubies_dir
44
+ @toolchain = (toolchain || RubyWasm::Toolchain.get(target, @build_dir))
45
+
46
+ @libyaml = RubyWasm::LibYAMLProduct.new(@build_dir, @target, @toolchain)
47
+ @zlib = RubyWasm::ZlibProduct.new(@build_dir, @target, @toolchain)
48
+ @wasi_vfs = RubyWasm::WasiVfsProduct.new(@build_dir)
49
+ @source = RubyWasm::BuildSource.new(src, @build_dir)
50
+ @baseruby = RubyWasm::BaseRubyProduct.new(@build_dir, @source)
51
+ @openssl = RubyWasm::OpenSSLProduct.new(@build_dir, @target, @toolchain)
52
+
53
+ build_params =
54
+ RubyWasm::BuildParams.new(
55
+ name: name,
56
+ target: target,
57
+ default_exts: options[:default_exts]
58
+ )
59
+
60
+ @crossruby =
61
+ RubyWasm::CrossRubyProduct.new(
62
+ build_params,
63
+ @build_dir,
64
+ @rubies_dir,
65
+ @baseruby,
66
+ @source,
67
+ @toolchain
68
+ )
69
+
70
+ @crossruby.with_libyaml @libyaml
71
+ @crossruby.with_zlib @zlib
72
+ @crossruby.with_wasi_vfs @wasi_vfs
73
+ @crossruby.with_openssl @openssl
74
+ end
75
+
76
+ def cache_key(digest)
77
+ @source.cache_key(digest)
78
+ @crossruby.cache_key(digest)
79
+ digest << @build_dir
80
+ digest << @rubies_dir
81
+ digest << @target
82
+ digest << @toolchain.name
83
+ digest << @libyaml.name
84
+ digest << @zlib.name
85
+ digest << @openssl.name
86
+ digest << @wasi_vfs.name
87
+ end
88
+ end
@@ -0,0 +1,217 @@
1
+ require "optparse"
2
+ require "rbconfig"
3
+
4
+ module RubyWasm
5
+ class CLI
6
+ def initialize(stdout:, stderr:)
7
+ @stdout = stdout
8
+ @stderr = stderr
9
+ end
10
+
11
+ def run(args)
12
+ available_commands = %w[build pack]
13
+ parser =
14
+ OptionParser.new do |opts|
15
+ opts.banner = <<~USAGE
16
+ Usage: rbwasm [options...] [command]
17
+
18
+ Available commands: #{available_commands.join(", ")}
19
+ USAGE
20
+ opts.version = RubyWasm::VERSION
21
+ opts.on("-h", "--help", "Prints this help") do
22
+ @stderr.puts opts
23
+ exit
24
+ end
25
+ opts.on("--log-level LEVEL", "Log level") do |level|
26
+ RubyWasm.log_level = level.to_sym
27
+ end
28
+ end
29
+ parser.order!(args)
30
+
31
+ command = args.shift
32
+ case command
33
+ when "build"
34
+ build(args)
35
+ when "pack"
36
+ pack(args)
37
+ else
38
+ @stderr.puts "Unknown command: #{command}"
39
+ @stderr.puts parser
40
+ exit
41
+ end
42
+ end
43
+
44
+ def build(args)
45
+ # @type var options: Hash[Symbol, untyped]
46
+ options = {
47
+ save_temps: false,
48
+ optimize: false,
49
+ remake: false,
50
+ reconfigure: false,
51
+ clean: false,
52
+ ruby_version: "3.3",
53
+ target_triplet: "wasm32-unknown-wasi",
54
+ profile: "full",
55
+ stdlib: true,
56
+ disable_gems: false
57
+ }
58
+ OptionParser
59
+ .new do |opts|
60
+ opts.banner = "Usage: rbwasm componentize [options]"
61
+ opts.on("-h", "--help", "Prints this help") do
62
+ @stdout.puts opts
63
+ exit
64
+ end
65
+
66
+ opts.on("--save-temps", "Save temporary files") do
67
+ options[:save_temps] = true
68
+ end
69
+
70
+ opts.on("--ruby-version VERSION", "Ruby version") do |version|
71
+ options[:ruby_version] = version
72
+ end
73
+
74
+ opts.on("--target TRIPLET", "Target triplet") do |triplet|
75
+ options[:target_triplet] = triplet
76
+ end
77
+
78
+ opts.on(
79
+ "--build-profile PROFILE",
80
+ "Build profile. full or minimal"
81
+ ) { |profile| options[:profile] = profile }
82
+
83
+ opts.on("--optimize", "Optimize the output") do
84
+ options[:optimize] = true
85
+ end
86
+
87
+ opts.on("--remake", "Re-execute make for Ruby") do
88
+ options[:remake] = true
89
+ end
90
+
91
+ opts.on("--reconfigure", "Re-execute configure for Ruby") do
92
+ options[:reconfigure] = true
93
+ end
94
+
95
+ opts.on("--clean", "Clean build artifacts") { options[:clean] = true }
96
+
97
+ opts.on("-o", "--output FILE", "Output file") do |file|
98
+ options[:output] = file
99
+ end
100
+
101
+ opts.on("--[no-]stdlib", "Include stdlib") do |stdlib|
102
+ options[:stdlib] = stdlib
103
+ end
104
+
105
+ opts.on("--disable-gems", "Disable gems") do
106
+ options[:disable_gems] = true
107
+ end
108
+
109
+ opts.on("--format FORMAT", "Output format") do |format|
110
+ options[:format] = format
111
+ end
112
+
113
+ opts.on("--print-ruby-cache-key", "Print Ruby cache key") do
114
+ options[:print_ruby_cache_key] = true
115
+ end
116
+ end
117
+ .parse!(args)
118
+
119
+ verbose = RubyWasm.logger.level == :debug
120
+ executor = RubyWasm::BuildExecutor.new(verbose: verbose)
121
+ packager = self.derive_packager(options)
122
+
123
+ if options[:print_ruby_cache_key]
124
+ self.do_print_ruby_cache_key(packager)
125
+ exit
126
+ end
127
+
128
+ unless options[:output]
129
+ @stderr.puts "Output file is not specified"
130
+ exit 1
131
+ end
132
+
133
+ require "tmpdir"
134
+
135
+ if options[:save_temps]
136
+ tmpdir = Dir.mktmpdir
137
+ self.do_build(executor, tmpdir, packager, options)
138
+ @stderr.puts "Temporary files are saved to #{tmpdir}"
139
+ exit
140
+ else
141
+ Dir.mktmpdir do |tmpdir|
142
+ self.do_build(executor, tmpdir, packager, options)
143
+ end
144
+ end
145
+ end
146
+
147
+ def pack(args)
148
+ self.require_extension
149
+ RubyWasmExt::WasiVfs.run_cli([$0, "pack", *args])
150
+ end
151
+
152
+ private
153
+
154
+ def build_config(options)
155
+ config = { target: options[:target_triplet], src: options[:ruby_version] }
156
+ case options[:profile]
157
+ when "full"
158
+ config[:default_exts] = RubyWasm::Packager::ALL_DEFAULT_EXTS
159
+ env_additional_exts = ENV["RUBY_WASM_ADDITIONAL_EXTS"] || ""
160
+ unless env_additional_exts.empty?
161
+ config[:default_exts] += "," + env_additional_exts
162
+ end
163
+ when "minimal"
164
+ config[:default_exts] = ""
165
+ else
166
+ RubyWasm.logger.error "Unknown profile: #{options[:profile]} (available: full, minimal)"
167
+ exit 1
168
+ end
169
+ config[:suffix] = "-#{options[:profile]}"
170
+ config
171
+ end
172
+
173
+ def derive_packager(options)
174
+ __skip__ =
175
+ if defined?(Bundler) && !options[:disable_gems]
176
+ definition = Bundler.definition
177
+ end
178
+ RubyWasm::Packager.new(build_config(options), definition)
179
+ end
180
+
181
+ def do_print_ruby_cache_key(packager)
182
+ ruby_core_build = packager.ruby_core_build
183
+ require "digest"
184
+ digest = Digest::SHA256.new
185
+ ruby_core_build.cache_key(digest)
186
+ hexdigest = digest.hexdigest
187
+ require "json"
188
+ @stdout.puts JSON.generate(
189
+ hexdigest: hexdigest,
190
+ artifact: ruby_core_build.artifact
191
+ )
192
+ end
193
+
194
+ def do_build(executor, tmpdir, packager, options)
195
+ self.require_extension
196
+ wasm_bytes = packager.package(executor, tmpdir, options)
197
+ RubyWasm.logger.info "Size: #{SizeFormatter.format(wasm_bytes.size)}"
198
+ case options[:output]
199
+ when "-"
200
+ @stdout.write wasm_bytes.pack("C*")
201
+ else
202
+ File.binwrite(options[:output], wasm_bytes.pack("C*"))
203
+ RubyWasm.logger.debug "Wrote #{options[:output]}"
204
+ end
205
+ end
206
+
207
+ def require_extension
208
+ # Tries to require the extension for the given Ruby version first
209
+ begin
210
+ RUBY_VERSION =~ /(\d+\.\d+)/
211
+ require_relative "#{Regexp.last_match(1)}/ruby_wasm.so"
212
+ rescue LoadError
213
+ require_relative "ruby_wasm.so"
214
+ end
215
+ end
216
+ end
217
+ end