ruby_wasm 2.5.1-aarch64-linux-musl
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 +128 -0
- data/Gemfile +17 -0
- data/LICENSE +21 -0
- data/NOTICE +1293 -0
- data/README.md +154 -0
- data/Rakefile +164 -0
- data/Steepfile +24 -0
- data/benchmarks/vm_deep_call.rb +55 -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/3.3/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 +191 -0
- data/lib/ruby_wasm/build/product/baseruby.rb +37 -0
- data/lib/ruby_wasm/build/product/crossruby.rb +360 -0
- data/lib/ruby_wasm/build/product/libyaml.rb +70 -0
- data/lib/ruby_wasm/build/product/openssl.rb +93 -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 +70 -0
- data/lib/ruby_wasm/build/product.rb +8 -0
- data/lib/ruby_wasm/build/target.rb +24 -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 +92 -0
- data/lib/ruby_wasm/cli.rb +347 -0
- data/lib/ruby_wasm/packager/component_adapter/wasi_snapshot_preview1.command.wasm +0 -0
- data/lib/ruby_wasm/packager/component_adapter/wasi_snapshot_preview1.reactor.wasm +0 -0
- data/lib/ruby_wasm/packager/component_adapter.rb +14 -0
- data/lib/ruby_wasm/packager/core.rb +333 -0
- data/lib/ruby_wasm/packager/file_system.rb +160 -0
- data/lib/ruby_wasm/packager.rb +96 -0
- data/lib/ruby_wasm/rake_task.rb +60 -0
- data/lib/ruby_wasm/util.rb +15 -0
- data/lib/ruby_wasm/version.rb +3 -0
- data/lib/ruby_wasm.rb +34 -0
- data/package-lock.json +9777 -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 +165 -0
- data/rakelib/version.rake +40 -0
- data/sig/open_uri.rbs +4 -0
- data/sig/ruby_wasm/build.rbs +327 -0
- data/sig/ruby_wasm/cli.rbs +51 -0
- data/sig/ruby_wasm/ext.rbs +26 -0
- data/sig/ruby_wasm/packager.rbs +122 -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 +114 -0
@@ -0,0 +1,160 @@
|
|
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
|
+
patterns = %w[
|
69
|
+
usr/local/lib/libruby-static.a
|
70
|
+
usr/local/bin/ruby
|
71
|
+
usr/local/include
|
72
|
+
]
|
73
|
+
|
74
|
+
patterns << "**/*.so" unless @packager.support_dynamic_linking?
|
75
|
+
patterns.each do |pattern|
|
76
|
+
Dir
|
77
|
+
.glob(File.join(@dest_dir, pattern))
|
78
|
+
.each do |entry|
|
79
|
+
RubyWasm.logger.debug do
|
80
|
+
relative_entry = Pathname.new(entry).relative_path_from(@dest_dir)
|
81
|
+
"Removing non-runtime file: #{relative_entry}"
|
82
|
+
end
|
83
|
+
executor.rm_rf entry
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def bundle_dir
|
89
|
+
File.join(@dest_dir, bundle_relative_path)
|
90
|
+
end
|
91
|
+
|
92
|
+
def ruby_root
|
93
|
+
@ruby_root
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
# Iterates over each gem's require path and extension path.
|
99
|
+
# Yields the installation relative path and the source path.
|
100
|
+
def each_gem_require_path(&block)
|
101
|
+
each_gem_extension_path(&block)
|
102
|
+
@packager.specs.each do |spec|
|
103
|
+
# Use raw_require_paths to exclude extensions
|
104
|
+
spec.raw_require_paths.each do |require_path|
|
105
|
+
source = File.expand_path(require_path, spec.full_gem_path)
|
106
|
+
next unless File.exist?(source)
|
107
|
+
relative =
|
108
|
+
File.join(bundle_relative_path, "gems", spec.full_name, require_path)
|
109
|
+
yield relative, source
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def each_gem_content_path(&block)
|
115
|
+
each_gem_extension_path(&block)
|
116
|
+
|
117
|
+
@packager.specs.each do |spec|
|
118
|
+
next unless File.exist?(spec.full_gem_path)
|
119
|
+
|
120
|
+
# spec.files is only valid before the gem is packaged.
|
121
|
+
if spec.source.path?
|
122
|
+
relative_paths = spec.files
|
123
|
+
else
|
124
|
+
# All files in .gem are required.
|
125
|
+
relative_paths = Dir.children(spec.full_gem_path)
|
126
|
+
end
|
127
|
+
relative_paths.each do |require_path|
|
128
|
+
source = File.expand_path(require_path, spec.full_gem_path)
|
129
|
+
next unless File.exist?(source)
|
130
|
+
relative =
|
131
|
+
File.join(bundle_relative_path, "gems", spec.full_name, require_path)
|
132
|
+
yield relative, source
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def each_gem_extension_path
|
138
|
+
@packager.specs.each do |spec|
|
139
|
+
if !spec.extensions.empty? && File.exist?(spec.extension_dir)
|
140
|
+
relative = File.join(bundle_relative_path, "extensions", spec.full_name)
|
141
|
+
yield relative, spec.extension_dir
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def bundle_relative_path
|
147
|
+
"bundle"
|
148
|
+
end
|
149
|
+
|
150
|
+
def ruby_version
|
151
|
+
rubyarchdir = self.rubyarchdir
|
152
|
+
File.basename(File.dirname(rubyarchdir))
|
153
|
+
end
|
154
|
+
|
155
|
+
def rubyarchdir
|
156
|
+
maybe =
|
157
|
+
Dir.glob(File.join(@ruby_root, "lib", "ruby", "*", "wasm32-wasi")).first
|
158
|
+
maybe || raise("Cannot find rubyarchdir")
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,96 @@
|
|
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 root [String] The root directory of the Ruby project.
|
6
|
+
# The root directory (will) contain the following files:
|
7
|
+
# * build_manifest.json
|
8
|
+
# * rubies
|
9
|
+
# * build
|
10
|
+
# @param config [Hash] The build config used for building Ruby.
|
11
|
+
# @param definition [Bundler::Definition] The Bundler definition.
|
12
|
+
def initialize(root, config = nil, definition = nil)
|
13
|
+
@root = root
|
14
|
+
@definition = definition
|
15
|
+
@config = config
|
16
|
+
end
|
17
|
+
|
18
|
+
# Packages the Ruby code into a Wasm binary. (including extensions)
|
19
|
+
#
|
20
|
+
# @param executor [RubyWasm::BuildExecutor] The executor for building the Wasm binary.
|
21
|
+
# @param dest_dir [String] The destination used to construct the filesystem.
|
22
|
+
# @param options [Hash] The packaging options.
|
23
|
+
# @return [Array<Integer>] The bytes of the packaged Wasm binary.
|
24
|
+
def package(executor, dest_dir, options)
|
25
|
+
ruby_core = self.ruby_core_build()
|
26
|
+
tarball = ruby_core.build(executor, options)
|
27
|
+
|
28
|
+
fs = RubyWasm::Packager::FileSystem.new(dest_dir, self)
|
29
|
+
fs.package_ruby_root(tarball, executor)
|
30
|
+
wasm_bytes = ruby_core.build_and_link_exts(executor)
|
31
|
+
|
32
|
+
fs.package_gems
|
33
|
+
fs.remove_non_runtime_files(executor)
|
34
|
+
fs.remove_stdlib(executor) unless options[:stdlib]
|
35
|
+
|
36
|
+
if full_build_options[:target] == "wasm32-unknown-wasip1" && !support_dynamic_linking?
|
37
|
+
# wasi-vfs supports only WASI target
|
38
|
+
wasi_vfs = RubyWasmExt::WasiVfs.new
|
39
|
+
wasi_vfs.map_dir("/bundle", fs.bundle_dir)
|
40
|
+
wasi_vfs.map_dir("/usr", File.dirname(fs.ruby_root))
|
41
|
+
|
42
|
+
wasm_bytes = wasi_vfs.pack(wasm_bytes)
|
43
|
+
end
|
44
|
+
|
45
|
+
wasm_bytes = RubyWasmExt.preinitialize(wasm_bytes) if options[:optimize]
|
46
|
+
wasm_bytes
|
47
|
+
end
|
48
|
+
|
49
|
+
def ruby_core_build
|
50
|
+
@ruby_core_build ||= RubyWasm::Packager::Core.new(self)
|
51
|
+
end
|
52
|
+
|
53
|
+
# The list of excluded gems from the Bundler definition.
|
54
|
+
EXCLUDED_GEMS = %w[ruby_wasm bundler]
|
55
|
+
|
56
|
+
# Retrieves the specs from the Bundler definition, excluding the excluded gems.
|
57
|
+
def specs
|
58
|
+
return [] unless @definition
|
59
|
+
@specs ||= @definition.resolve.materialize(@definition.requested_dependencies)
|
60
|
+
.reject { |spec| EXCLUDED_GEMS.include?(spec.name) }
|
61
|
+
@specs
|
62
|
+
end
|
63
|
+
|
64
|
+
# Checks if dynamic linking is supported.
|
65
|
+
def support_dynamic_linking?
|
66
|
+
ENV["RUBY_WASM_EXPERIMENTAL_DYNAMIC_LINKING"] == "1"
|
67
|
+
end
|
68
|
+
|
69
|
+
ALL_DEFAULT_EXTS =
|
70
|
+
"cgi/escape,continuation,coverage,date,digest/bubblebabble,digest,digest/md5,digest/rmd160,digest/sha1,digest/sha2,etc,fcntl,json,json/generator,json/parser,objspace,pathname,psych,rbconfig/sizeof,ripper,stringio,strscan,monitor,zlib,openssl"
|
71
|
+
|
72
|
+
# Retrieves the build options used for building Ruby itself.
|
73
|
+
def build_options
|
74
|
+
default = {
|
75
|
+
target: RubyWasm::Target.new("wasm32-unknown-wasip1"),
|
76
|
+
default_exts: ALL_DEFAULT_EXTS
|
77
|
+
}
|
78
|
+
override = @config || {}
|
79
|
+
# Merge the default options with the config options
|
80
|
+
default.merge(override)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Retrieves the resolved build options
|
84
|
+
def full_build_options
|
85
|
+
options = build_options
|
86
|
+
build_dir = File.join(@root, "build")
|
87
|
+
rubies_dir = File.join(@root, "rubies")
|
88
|
+
toolchain = RubyWasm::Toolchain.get(options[:target], build_dir)
|
89
|
+
options.merge(
|
90
|
+
toolchain: toolchain,
|
91
|
+
build_dir: build_dir,
|
92
|
+
rubies_dir: rubies_dir,
|
93
|
+
src: options[:src]
|
94
|
+
)
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,60 @@
|
|
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
|
+
target = Target.new(target)
|
20
|
+
@build =
|
21
|
+
RubyWasm::Build.new(
|
22
|
+
name,
|
23
|
+
target: target,
|
24
|
+
src: src,
|
25
|
+
toolchain: toolchain,
|
26
|
+
build_dir: build_dir || File.join(Dir.pwd, "build"),
|
27
|
+
rubies_dir: rubies_dir || File.join(Dir.pwd, "rubies"),
|
28
|
+
**options,
|
29
|
+
&block
|
30
|
+
)
|
31
|
+
yield @build if block_given?
|
32
|
+
@crossruby = @build.crossruby
|
33
|
+
# Rake.verbose can be Object.new by default, so compare with true explicitly.
|
34
|
+
executor = RubyWasm::BuildExecutor.new(verbose: Rake.verbose == true)
|
35
|
+
|
36
|
+
desc "Cross-build Ruby for #{@target}"
|
37
|
+
task name do
|
38
|
+
next if File.exist? @crossruby.artifact
|
39
|
+
@crossruby.build(executor)
|
40
|
+
end
|
41
|
+
namespace name do
|
42
|
+
task :remake do
|
43
|
+
@crossruby.build(executor, remake: true)
|
44
|
+
end
|
45
|
+
task :reconfigure do
|
46
|
+
@crossruby.build(executor, reconfigure: true)
|
47
|
+
end
|
48
|
+
task :clean do
|
49
|
+
@crossruby.clean(executor)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def hexdigest
|
55
|
+
require "digest"
|
56
|
+
digest = Digest::SHA256.new
|
57
|
+
@build.cache_key(digest)
|
58
|
+
digest.hexdigest
|
59
|
+
end
|
60
|
+
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,34 @@
|
|
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/component_adapter"
|
8
|
+
require_relative "ruby_wasm/packager/file_system"
|
9
|
+
require_relative "ruby_wasm/packager/core"
|
10
|
+
|
11
|
+
module RubyWasm
|
12
|
+
class << self
|
13
|
+
attr_accessor :log_level
|
14
|
+
|
15
|
+
def logger
|
16
|
+
@logger ||=
|
17
|
+
begin
|
18
|
+
logger =
|
19
|
+
Logger.new(
|
20
|
+
$stderr,
|
21
|
+
level: @log_level || Logger::INFO,
|
22
|
+
progname: "rbwasm"
|
23
|
+
)
|
24
|
+
logger.formatter =
|
25
|
+
proc { |severity, datetime, progname, msg| "#{severity}: #{msg}\n" }
|
26
|
+
logger
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def logger=(logger)
|
31
|
+
@logger = logger
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|