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,156 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
|
3
|
+
class RubyWasm::Packager::Core
|
4
|
+
def initialize(packager)
|
5
|
+
@packager = packager
|
6
|
+
end
|
7
|
+
|
8
|
+
def build(executor, options)
|
9
|
+
strategy = build_strategy
|
10
|
+
strategy.build(executor, options)
|
11
|
+
end
|
12
|
+
|
13
|
+
extend Forwardable
|
14
|
+
|
15
|
+
def_delegators :build_strategy, :cache_key, :artifact
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def build_strategy
|
20
|
+
@build_strategy ||=
|
21
|
+
begin
|
22
|
+
has_exts = @packager.specs.any? { |spec| spec.extensions.any? }
|
23
|
+
if @packager.support_dynamic_linking?
|
24
|
+
DynamicLinking.new(@packager)
|
25
|
+
else
|
26
|
+
StaticLinking.new(@packager)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class BuildStrategy
|
32
|
+
def initialize(packager)
|
33
|
+
@packager = packager
|
34
|
+
end
|
35
|
+
|
36
|
+
def build(executor, options)
|
37
|
+
raise NotImplementedError
|
38
|
+
end
|
39
|
+
|
40
|
+
# Array of paths to extconf.rb files.
|
41
|
+
def specs_with_extensions
|
42
|
+
@packager.specs.filter_map do |spec|
|
43
|
+
exts =
|
44
|
+
spec.extensions.select do |ext|
|
45
|
+
# Filter out extensions of default gems (e.g. json, openssl)
|
46
|
+
# for the exactly same gem version.
|
47
|
+
File.exist?(File.join(spec.full_gem_path, ext))
|
48
|
+
end
|
49
|
+
next nil if exts.empty?
|
50
|
+
[spec, exts]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def cache_key(digest)
|
55
|
+
raise NotImplementedError
|
56
|
+
end
|
57
|
+
|
58
|
+
def artifact
|
59
|
+
raise NotImplementedError
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class DynamicLinking < BuildStrategy
|
64
|
+
end
|
65
|
+
|
66
|
+
class StaticLinking < BuildStrategy
|
67
|
+
def build(executor, options)
|
68
|
+
build = derive_build
|
69
|
+
force_rebuild =
|
70
|
+
options[:remake] || options[:clean] || options[:reconfigure]
|
71
|
+
if File.exist?(build.crossruby.artifact) && !force_rebuild
|
72
|
+
return build.crossruby.artifact
|
73
|
+
end
|
74
|
+
build.crossruby.clean(executor) if options[:clean]
|
75
|
+
|
76
|
+
do_build =
|
77
|
+
proc do
|
78
|
+
build.crossruby.build(
|
79
|
+
executor,
|
80
|
+
remake: options[:remake],
|
81
|
+
reconfigure: options[:reconfigure]
|
82
|
+
)
|
83
|
+
end
|
84
|
+
|
85
|
+
__skip__ =
|
86
|
+
if defined?(Bundler)
|
87
|
+
Bundler.with_unbundled_env(&do_build)
|
88
|
+
else
|
89
|
+
do_build.call
|
90
|
+
end
|
91
|
+
build.crossruby.artifact
|
92
|
+
end
|
93
|
+
|
94
|
+
def cache_key(digest)
|
95
|
+
derive_build.cache_key(digest)
|
96
|
+
end
|
97
|
+
|
98
|
+
def artifact
|
99
|
+
derive_build.crossruby.artifact
|
100
|
+
end
|
101
|
+
|
102
|
+
def derive_build
|
103
|
+
return @build if @build
|
104
|
+
__skip__ =
|
105
|
+
build ||= RubyWasm::Build.new(name, **@packager.full_build_options)
|
106
|
+
build.crossruby.user_exts = user_exts(build)
|
107
|
+
# Emscripten uses --global-base=1024 by default, but it conflicts with
|
108
|
+
# --stack-first and -z stack-size since global-base 1024 is smaller than
|
109
|
+
# the large stack size.
|
110
|
+
# Also -g produces some warnings on Emscripten and it confuses the configure
|
111
|
+
# script of Ruby.
|
112
|
+
if @packager.full_build_options[:target] != "wasm32-unknown-emscripten"
|
113
|
+
build.crossruby.debugflags = %w[-g]
|
114
|
+
build.crossruby.wasmoptflags = %w[-O3 -g]
|
115
|
+
build.crossruby.ldflags = %w[
|
116
|
+
-Xlinker
|
117
|
+
--stack-first
|
118
|
+
-Xlinker
|
119
|
+
-z
|
120
|
+
-Xlinker
|
121
|
+
stack-size=16777216
|
122
|
+
]
|
123
|
+
end
|
124
|
+
@build = build
|
125
|
+
build
|
126
|
+
end
|
127
|
+
|
128
|
+
def user_exts(build)
|
129
|
+
@user_exts ||=
|
130
|
+
specs_with_extensions.flat_map do |spec, exts|
|
131
|
+
exts.map do |ext|
|
132
|
+
ext_feature = File.dirname(ext) # e.g. "ext/cgi/escape"
|
133
|
+
ext_srcdir = File.join(spec.full_gem_path, ext_feature)
|
134
|
+
ext_relative_path = File.join(spec.full_name, ext_feature)
|
135
|
+
RubyWasm::CrossRubyExtProduct.new(
|
136
|
+
ext_srcdir,
|
137
|
+
build.toolchain,
|
138
|
+
ext_relative_path: ext_relative_path
|
139
|
+
)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def name
|
145
|
+
require "digest"
|
146
|
+
options = @packager.full_build_options
|
147
|
+
src_channel = options[:src][:name]
|
148
|
+
target_triplet = options[:target]
|
149
|
+
base = "ruby-#{src_channel}-#{target_triplet}#{options[:suffix]}"
|
150
|
+
exts = specs_with_extensions.sort
|
151
|
+
hash = ::Digest::MD5.new
|
152
|
+
specs_with_extensions.each { |spec, _| hash << spec.full_name }
|
153
|
+
exts.empty? ? base : "#{base}-#{hash.hexdigest}"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# Package Ruby code into a mountable directory.
|
2
|
+
class RubyWasm::Packager::FileSystem
|
3
|
+
def initialize(dest_dir, packager)
|
4
|
+
@dest_dir = dest_dir
|
5
|
+
@packager = packager
|
6
|
+
@ruby_root = File.join(@dest_dir, "usr", "local")
|
7
|
+
end
|
8
|
+
|
9
|
+
def package_ruby_root(tarball, executor)
|
10
|
+
usr_dir = File.dirname(@ruby_root)
|
11
|
+
executor.mkdir_p usr_dir
|
12
|
+
executor.system(
|
13
|
+
"tar",
|
14
|
+
"-C",
|
15
|
+
usr_dir,
|
16
|
+
"-xzf",
|
17
|
+
tarball,
|
18
|
+
"--strip-components=2"
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
def remove_stdlib(executor)
|
23
|
+
# Include only rbconfig.rb
|
24
|
+
rbconfig =
|
25
|
+
File.join(
|
26
|
+
@ruby_root,
|
27
|
+
"lib",
|
28
|
+
"ruby",
|
29
|
+
ruby_version,
|
30
|
+
"wasm32-wasi",
|
31
|
+
"rbconfig.rb"
|
32
|
+
)
|
33
|
+
# Remove all files except rbconfig.rb
|
34
|
+
RubyWasm.logger.info "Removing stdlib (except rbconfig.rb: #{rbconfig})"
|
35
|
+
rbconfig_contents = File.read(rbconfig)
|
36
|
+
executor.rm_rf @ruby_root
|
37
|
+
executor.mkdir_p File.dirname(rbconfig)
|
38
|
+
File.write(rbconfig, rbconfig_contents)
|
39
|
+
end
|
40
|
+
|
41
|
+
def package_gems
|
42
|
+
@packager.specs.each do |spec|
|
43
|
+
RubyWasm.logger.info "Packaging gem: #{spec.full_name}"
|
44
|
+
end
|
45
|
+
self.each_gem_content_path do |relative, source|
|
46
|
+
RubyWasm.logger.debug "Packaging gem file: #{relative}"
|
47
|
+
dest = File.join(@dest_dir, relative)
|
48
|
+
FileUtils.mkdir_p File.dirname(dest)
|
49
|
+
FileUtils.cp_r source, dest
|
50
|
+
end
|
51
|
+
|
52
|
+
setup_rb_path = File.join(bundle_relative_path, "setup.rb")
|
53
|
+
RubyWasm.logger.info "Packaging setup.rb: #{setup_rb_path}"
|
54
|
+
full_setup_rb_path = File.join(@dest_dir, setup_rb_path)
|
55
|
+
FileUtils.mkdir_p File.dirname(full_setup_rb_path)
|
56
|
+
File.write(full_setup_rb_path, setup_rb_content)
|
57
|
+
end
|
58
|
+
|
59
|
+
def setup_rb_content
|
60
|
+
content = ""
|
61
|
+
self.each_gem_require_path do |relative, _|
|
62
|
+
content << %Q[$:.unshift File.expand_path("#{File.join("/", relative)}")\n]
|
63
|
+
end
|
64
|
+
content
|
65
|
+
end
|
66
|
+
|
67
|
+
def remove_non_runtime_files(executor)
|
68
|
+
%w[
|
69
|
+
**/*.so
|
70
|
+
usr/local/lib/libruby-static.a
|
71
|
+
usr/local/bin/ruby
|
72
|
+
usr/local/include
|
73
|
+
].each do |pattern|
|
74
|
+
Dir
|
75
|
+
.glob(File.join(@dest_dir, pattern))
|
76
|
+
.each do |entry|
|
77
|
+
RubyWasm.logger.debug do
|
78
|
+
relative_entry = Pathname.new(entry).relative_path_from(@dest_dir)
|
79
|
+
"Removing non-runtime file: #{relative_entry}"
|
80
|
+
end
|
81
|
+
executor.rm_rf entry
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def bundle_dir
|
87
|
+
File.join(@dest_dir, bundle_relative_path)
|
88
|
+
end
|
89
|
+
|
90
|
+
def ruby_root
|
91
|
+
@ruby_root
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
# Iterates over each gem's require path and extension path.
|
97
|
+
# Yields the installation relative path and the source path.
|
98
|
+
def each_gem_require_path(&block)
|
99
|
+
each_gem_extension_path(&block)
|
100
|
+
@packager.specs.each do |spec|
|
101
|
+
# Use raw_require_paths to exclude extensions
|
102
|
+
spec.raw_require_paths.each do |require_path|
|
103
|
+
source = File.expand_path(require_path, spec.full_gem_path)
|
104
|
+
next unless File.exist?(source)
|
105
|
+
relative =
|
106
|
+
File.join(bundle_relative_path, "gems", spec.full_name, require_path)
|
107
|
+
yield relative, source
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def each_gem_content_path(&block)
|
113
|
+
each_gem_extension_path(&block)
|
114
|
+
|
115
|
+
@packager.specs.each do |spec|
|
116
|
+
next unless File.exist?(spec.full_gem_path)
|
117
|
+
|
118
|
+
# spec.files is only valid before the gem is packaged.
|
119
|
+
if spec.source.path?
|
120
|
+
relative_paths = spec.files
|
121
|
+
else
|
122
|
+
# All files in .gem are required.
|
123
|
+
relative_paths = Dir.children(spec.full_gem_path)
|
124
|
+
end
|
125
|
+
relative_paths.each do |require_path|
|
126
|
+
source = File.expand_path(require_path, spec.full_gem_path)
|
127
|
+
next unless File.exist?(source)
|
128
|
+
relative =
|
129
|
+
File.join(bundle_relative_path, "gems", spec.full_name, require_path)
|
130
|
+
yield relative, source
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def each_gem_extension_path
|
136
|
+
@packager.specs.each do |spec|
|
137
|
+
if !spec.extensions.empty? && File.exist?(spec.extension_dir)
|
138
|
+
relative = File.join(bundle_relative_path, "extensions", spec.full_name)
|
139
|
+
yield relative, spec.extension_dir
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def bundle_relative_path
|
145
|
+
"bundle"
|
146
|
+
end
|
147
|
+
|
148
|
+
def ruby_version
|
149
|
+
rubyarchdir = self.rubyarchdir
|
150
|
+
File.basename(File.dirname(rubyarchdir))
|
151
|
+
end
|
152
|
+
|
153
|
+
def rubyarchdir
|
154
|
+
maybe =
|
155
|
+
Dir.glob(File.join(@ruby_root, "lib", "ruby", "*", "wasm32-wasi")).first
|
156
|
+
maybe || raise("Cannot find rubyarchdir")
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
# A class responsible for packaging whole Ruby project
|
2
|
+
class RubyWasm::Packager
|
3
|
+
# Initializes a new instance of the RubyWasm::Packager class.
|
4
|
+
#
|
5
|
+
# @param config [Hash] The build config used for building Ruby.
|
6
|
+
# @param definition [Bundler::Definition] The Bundler definition.
|
7
|
+
def initialize(config = nil, definition = nil)
|
8
|
+
@definition = definition
|
9
|
+
@config = config
|
10
|
+
end
|
11
|
+
|
12
|
+
# Packages the Ruby code into a Wasm binary. (including extensions)
|
13
|
+
#
|
14
|
+
# @param executor [RubyWasm::BuildExecutor] The executor for building the Wasm binary.
|
15
|
+
# @param dest_dir [String] The destination used to construct the filesystem.
|
16
|
+
# @param options [Hash] The packaging options.
|
17
|
+
# @return [Array<Integer>] The bytes of the packaged Wasm binary.
|
18
|
+
def package(executor, dest_dir, options)
|
19
|
+
ruby_core = self.ruby_core_build()
|
20
|
+
tarball = ruby_core.build(executor, options)
|
21
|
+
|
22
|
+
fs = RubyWasm::Packager::FileSystem.new(dest_dir, self)
|
23
|
+
fs.package_ruby_root(tarball, executor)
|
24
|
+
|
25
|
+
ruby_wasm_bin = File.expand_path("bin/ruby", fs.ruby_root)
|
26
|
+
wasm_bytes = File.binread(ruby_wasm_bin).bytes
|
27
|
+
|
28
|
+
fs.package_gems
|
29
|
+
fs.remove_non_runtime_files(executor)
|
30
|
+
fs.remove_stdlib(executor) unless options[:stdlib]
|
31
|
+
|
32
|
+
if full_build_options[:target] == "wasm32-unknown-wasi"
|
33
|
+
# wasi-vfs supports only WASI target
|
34
|
+
wasi_vfs = RubyWasmExt::WasiVfs.new
|
35
|
+
wasi_vfs.map_dir("/bundle", fs.bundle_dir)
|
36
|
+
wasi_vfs.map_dir("/usr", File.dirname(fs.ruby_root))
|
37
|
+
|
38
|
+
wasm_bytes = wasi_vfs.pack(wasm_bytes)
|
39
|
+
end
|
40
|
+
|
41
|
+
wasm_bytes = RubyWasmExt.preinitialize(wasm_bytes) if options[:optimize]
|
42
|
+
wasm_bytes
|
43
|
+
end
|
44
|
+
|
45
|
+
def ruby_core_build
|
46
|
+
@ruby_core_build ||= RubyWasm::Packager::Core.new(self)
|
47
|
+
end
|
48
|
+
|
49
|
+
# The list of excluded gems from the Bundler definition.
|
50
|
+
EXCLUDED_GEMS = %w[ruby_wasm bundler]
|
51
|
+
|
52
|
+
# Retrieves the specs from the Bundler definition, excluding the excluded gems.
|
53
|
+
def specs
|
54
|
+
return [] unless @definition
|
55
|
+
@definition.specs.reject { |spec| EXCLUDED_GEMS.include?(spec.name) }
|
56
|
+
end
|
57
|
+
|
58
|
+
# Checks if dynamic linking is supported.
|
59
|
+
def support_dynamic_linking?
|
60
|
+
@ruby_channel == "head"
|
61
|
+
end
|
62
|
+
|
63
|
+
# Retrieves the root directory of the Ruby project.
|
64
|
+
# The root directory contains the following stuff:
|
65
|
+
# * patches/*.patch
|
66
|
+
# * build_manifest.json
|
67
|
+
# * rubies
|
68
|
+
# * build
|
69
|
+
def root
|
70
|
+
__skip__ =
|
71
|
+
@root ||=
|
72
|
+
begin
|
73
|
+
if explicit = ENV["RUBY_WASM_ROOT"]
|
74
|
+
File.expand_path(explicit)
|
75
|
+
elsif defined?(Bundler)
|
76
|
+
Bundler.root
|
77
|
+
else
|
78
|
+
Dir.pwd
|
79
|
+
end
|
80
|
+
rescue Bundler::GemfileNotFound
|
81
|
+
Dir.pwd
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Retrieves the alias definitions for the Ruby sources.
|
86
|
+
def self.build_source_aliases(root)
|
87
|
+
patches = Dir[File.join(root, "patches", "*.patch")]
|
88
|
+
sources = {
|
89
|
+
"head" => {
|
90
|
+
type: "github",
|
91
|
+
repo: "ruby/ruby",
|
92
|
+
rev: "master",
|
93
|
+
patches: patches.map { |p| File.expand_path(p) }
|
94
|
+
},
|
95
|
+
"3.3" => {
|
96
|
+
type: "tarball",
|
97
|
+
url: "https://cache.ruby-lang.org/pub/ruby/3.3/ruby-3.3.0.tar.gz"
|
98
|
+
},
|
99
|
+
"3.2" => {
|
100
|
+
type: "tarball",
|
101
|
+
url: "https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.3.tar.gz"
|
102
|
+
}
|
103
|
+
}
|
104
|
+
sources.each { |name, source| source[:name] = name }
|
105
|
+
|
106
|
+
build_manifest = File.join(root, "build_manifest.json")
|
107
|
+
if File.exist?(build_manifest)
|
108
|
+
begin
|
109
|
+
manifest = JSON.parse(File.read(build_manifest))
|
110
|
+
manifest["ruby_revisions"].each do |name, rev|
|
111
|
+
sources[name][:rev] = rev
|
112
|
+
end
|
113
|
+
rescue StandardError => e
|
114
|
+
RubyWasm.logger.warn "Failed to load build_manifest.json: #{e}"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
sources
|
118
|
+
end
|
119
|
+
|
120
|
+
ALL_DEFAULT_EXTS =
|
121
|
+
"bigdecimal,cgi/escape,continuation,coverage,date,dbm,digest/bubblebabble,digest,digest/md5,digest/rmd160,digest/sha1,digest/sha2,etc,fcntl,fiber,gdbm,json,json/generator,json/parser,nkf,objspace,pathname,psych,racc/cparse,rbconfig/sizeof,ripper,stringio,strscan,monitor,zlib,openssl"
|
122
|
+
|
123
|
+
# Retrieves the build options used for building Ruby itself.
|
124
|
+
def build_options
|
125
|
+
default = {
|
126
|
+
target: "wasm32-unknown-wasi",
|
127
|
+
src: "3.3",
|
128
|
+
default_exts: ALL_DEFAULT_EXTS
|
129
|
+
}
|
130
|
+
override = @config || {}
|
131
|
+
# Merge the default options with the config options
|
132
|
+
default.merge(override)
|
133
|
+
end
|
134
|
+
|
135
|
+
# Retrieves the resolved build options
|
136
|
+
def full_build_options
|
137
|
+
options = build_options
|
138
|
+
build_dir = File.join(root, "build")
|
139
|
+
rubies_dir = File.join(root, "rubies")
|
140
|
+
toolchain = RubyWasm::Toolchain.get(options[:target], build_dir)
|
141
|
+
src =
|
142
|
+
if options[:src].is_a?(Hash)
|
143
|
+
options[:src]
|
144
|
+
else
|
145
|
+
src_name = options[:src]
|
146
|
+
aliases = self.class.build_source_aliases(root)
|
147
|
+
aliases[src_name] ||
|
148
|
+
raise(
|
149
|
+
"Unknown Ruby source: #{src_name} (available: #{aliases.keys.join(", ")})"
|
150
|
+
)
|
151
|
+
end
|
152
|
+
options.merge(
|
153
|
+
toolchain: toolchain,
|
154
|
+
build_dir: build_dir,
|
155
|
+
rubies_dir: rubies_dir,
|
156
|
+
src: src
|
157
|
+
)
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "rake/tasklib"
|
2
|
+
require_relative "./util"
|
3
|
+
require_relative "./build"
|
4
|
+
|
5
|
+
class RubyWasm::BuildTask < ::Rake::TaskLib
|
6
|
+
# Name of the task.
|
7
|
+
attr_accessor :name
|
8
|
+
|
9
|
+
def initialize(
|
10
|
+
name,
|
11
|
+
target:,
|
12
|
+
src:,
|
13
|
+
toolchain: nil,
|
14
|
+
build_dir: nil,
|
15
|
+
rubies_dir: nil,
|
16
|
+
**options,
|
17
|
+
&block
|
18
|
+
)
|
19
|
+
@build =
|
20
|
+
RubyWasm::Build.new(
|
21
|
+
name,
|
22
|
+
target: target,
|
23
|
+
src: src,
|
24
|
+
toolchain: toolchain,
|
25
|
+
build_dir: build_dir || File.join(Dir.pwd, "build"),
|
26
|
+
rubies_dir: rubies_dir || File.join(Dir.pwd, "rubies"),
|
27
|
+
**options,
|
28
|
+
&block
|
29
|
+
)
|
30
|
+
yield @build if block_given?
|
31
|
+
@crossruby = @build.crossruby
|
32
|
+
# Rake.verbose can be Object.new by default, so compare with true explicitly.
|
33
|
+
executor = RubyWasm::BuildExecutor.new(verbose: Rake.verbose == true)
|
34
|
+
|
35
|
+
desc "Cross-build Ruby for #{@target}"
|
36
|
+
task name do
|
37
|
+
next if File.exist? @crossruby.artifact
|
38
|
+
@crossruby.build(executor)
|
39
|
+
end
|
40
|
+
namespace name do
|
41
|
+
task :remake do
|
42
|
+
@crossruby.build(executor, remake: true)
|
43
|
+
end
|
44
|
+
task :reconfigure do
|
45
|
+
@crossruby.build(executor, reconfigure: true)
|
46
|
+
end
|
47
|
+
task :clean do
|
48
|
+
@crossruby.clean(executor)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def hexdigest
|
54
|
+
require "digest"
|
55
|
+
digest = Digest::SHA256.new
|
56
|
+
@build.cache_key(digest)
|
57
|
+
digest.hexdigest
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module RubyWasm
|
2
|
+
module SizeFormatter
|
3
|
+
def format(size)
|
4
|
+
units = %w[B KB MB GB TB]
|
5
|
+
unit = 0
|
6
|
+
while size > 1024 and unit < units.size - 1
|
7
|
+
size /= 1024.0
|
8
|
+
unit += 1
|
9
|
+
end
|
10
|
+
"%s #{units[unit]}" % size.round(2)
|
11
|
+
end
|
12
|
+
|
13
|
+
module_function :format
|
14
|
+
end
|
15
|
+
end
|
data/lib/ruby_wasm.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require "logger"
|
2
|
+
|
3
|
+
require_relative "ruby_wasm/version"
|
4
|
+
require_relative "ruby_wasm/util"
|
5
|
+
require_relative "ruby_wasm/build"
|
6
|
+
require_relative "ruby_wasm/packager"
|
7
|
+
require_relative "ruby_wasm/packager/file_system"
|
8
|
+
require_relative "ruby_wasm/packager/core"
|
9
|
+
|
10
|
+
module RubyWasm
|
11
|
+
class << self
|
12
|
+
attr_accessor :log_level
|
13
|
+
|
14
|
+
def logger
|
15
|
+
@logger ||=
|
16
|
+
begin
|
17
|
+
logger =
|
18
|
+
Logger.new(
|
19
|
+
$stderr,
|
20
|
+
level: @log_level || Logger::INFO,
|
21
|
+
progname: "rbwasm"
|
22
|
+
)
|
23
|
+
logger.formatter =
|
24
|
+
proc { |severity, datetime, progname, msg| "#{severity}: #{msg}\n" }
|
25
|
+
logger
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def logger=(logger)
|
30
|
+
@logger = logger
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|