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.
- checksums.yaml +7 -0
- data/.clang-format +8 -0
- data/CONTRIBUTING.md +126 -0
- data/Gemfile +17 -0
- data/LICENSE +21 -0
- data/NOTICE +1293 -0
- data/README.md +153 -0
- data/Rakefile +163 -0
- data/Steepfile +24 -0
- data/benchmarks/vm_deep_call.rb +55 -0
- data/builders/wasm32-unknown-emscripten/Dockerfile +43 -0
- data/builders/wasm32-unknown-emscripten/entrypoint.sh +7 -0
- data/builders/wasm32-unknown-wasi/Dockerfile +47 -0
- data/builders/wasm32-unknown-wasi/entrypoint.sh +7 -0
- data/docs/api.md +2 -0
- data/docs/cheat_sheet.md +195 -0
- data/docs/faq.md +25 -0
- data/exe/rbwasm +7 -0
- data/ext/.gitignore +2 -0
- data/ext/README.md +11 -0
- data/ext/extinit.c.erb +32 -0
- data/lib/ruby_wasm/3.1/ruby_wasm.so +0 -0
- data/lib/ruby_wasm/3.2/ruby_wasm.so +0 -0
- data/lib/ruby_wasm/build/build_params.rb +3 -0
- data/lib/ruby_wasm/build/downloader.rb +18 -0
- data/lib/ruby_wasm/build/executor.rb +187 -0
- data/lib/ruby_wasm/build/product/baseruby.rb +37 -0
- data/lib/ruby_wasm/build/product/crossruby.rb +330 -0
- data/lib/ruby_wasm/build/product/libyaml.rb +68 -0
- data/lib/ruby_wasm/build/product/openssl.rb +88 -0
- data/lib/ruby_wasm/build/product/product.rb +39 -0
- data/lib/ruby_wasm/build/product/ruby_source.rb +103 -0
- data/lib/ruby_wasm/build/product/wasi_vfs.rb +45 -0
- data/lib/ruby_wasm/build/product/zlib.rb +68 -0
- data/lib/ruby_wasm/build/product.rb +8 -0
- data/lib/ruby_wasm/build/toolchain/wit_bindgen.rb +31 -0
- data/lib/ruby_wasm/build/toolchain.rb +193 -0
- data/lib/ruby_wasm/build.rb +88 -0
- data/lib/ruby_wasm/cli.rb +217 -0
- data/lib/ruby_wasm/packager/core.rb +156 -0
- data/lib/ruby_wasm/packager/file_system.rb +158 -0
- data/lib/ruby_wasm/packager.rb +159 -0
- data/lib/ruby_wasm/rake_task.rb +59 -0
- data/lib/ruby_wasm/util.rb +15 -0
- data/lib/ruby_wasm/version.rb +3 -0
- data/lib/ruby_wasm.rb +33 -0
- data/package-lock.json +9500 -0
- data/package.json +12 -0
- data/rakelib/check.rake +37 -0
- data/rakelib/ci.rake +152 -0
- data/rakelib/doc.rake +29 -0
- data/rakelib/format.rake +35 -0
- data/rakelib/gem.rake +22 -0
- data/rakelib/packaging.rake +151 -0
- data/rakelib/version.rake +40 -0
- data/sig/open_uri.rbs +4 -0
- data/sig/ruby_wasm/build.rbs +318 -0
- data/sig/ruby_wasm/cli.rbs +27 -0
- data/sig/ruby_wasm/ext.rbs +13 -0
- data/sig/ruby_wasm/packager.rbs +91 -0
- data/sig/ruby_wasm/util.rbs +5 -0
- data/tools/clang-format-diff.sh +18 -0
- data/tools/exe/rbminify +12 -0
- data/tools/lib/syntax_tree/minify_ruby.rb +63 -0
- metadata +113 -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
|