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.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/.clang-format +8 -0
  3. data/CONTRIBUTING.md +128 -0
  4. data/Gemfile +17 -0
  5. data/LICENSE +21 -0
  6. data/NOTICE +1293 -0
  7. data/README.md +154 -0
  8. data/Rakefile +164 -0
  9. data/Steepfile +24 -0
  10. data/benchmarks/vm_deep_call.rb +55 -0
  11. data/docs/api.md +2 -0
  12. data/docs/cheat_sheet.md +195 -0
  13. data/docs/faq.md +25 -0
  14. data/exe/rbwasm +7 -0
  15. data/ext/.gitignore +2 -0
  16. data/ext/README.md +11 -0
  17. data/ext/extinit.c.erb +32 -0
  18. data/lib/ruby_wasm/3.1/ruby_wasm.so +0 -0
  19. data/lib/ruby_wasm/3.2/ruby_wasm.so +0 -0
  20. data/lib/ruby_wasm/3.3/ruby_wasm.so +0 -0
  21. data/lib/ruby_wasm/build/build_params.rb +3 -0
  22. data/lib/ruby_wasm/build/downloader.rb +18 -0
  23. data/lib/ruby_wasm/build/executor.rb +191 -0
  24. data/lib/ruby_wasm/build/product/baseruby.rb +37 -0
  25. data/lib/ruby_wasm/build/product/crossruby.rb +360 -0
  26. data/lib/ruby_wasm/build/product/libyaml.rb +70 -0
  27. data/lib/ruby_wasm/build/product/openssl.rb +93 -0
  28. data/lib/ruby_wasm/build/product/product.rb +39 -0
  29. data/lib/ruby_wasm/build/product/ruby_source.rb +103 -0
  30. data/lib/ruby_wasm/build/product/wasi_vfs.rb +45 -0
  31. data/lib/ruby_wasm/build/product/zlib.rb +70 -0
  32. data/lib/ruby_wasm/build/product.rb +8 -0
  33. data/lib/ruby_wasm/build/target.rb +24 -0
  34. data/lib/ruby_wasm/build/toolchain/wit_bindgen.rb +31 -0
  35. data/lib/ruby_wasm/build/toolchain.rb +193 -0
  36. data/lib/ruby_wasm/build.rb +92 -0
  37. data/lib/ruby_wasm/cli.rb +347 -0
  38. data/lib/ruby_wasm/packager/component_adapter/wasi_snapshot_preview1.command.wasm +0 -0
  39. data/lib/ruby_wasm/packager/component_adapter/wasi_snapshot_preview1.reactor.wasm +0 -0
  40. data/lib/ruby_wasm/packager/component_adapter.rb +14 -0
  41. data/lib/ruby_wasm/packager/core.rb +333 -0
  42. data/lib/ruby_wasm/packager/file_system.rb +160 -0
  43. data/lib/ruby_wasm/packager.rb +96 -0
  44. data/lib/ruby_wasm/rake_task.rb +60 -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 +34 -0
  48. data/package-lock.json +9777 -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 +165 -0
  56. data/rakelib/version.rake +40 -0
  57. data/sig/open_uri.rbs +4 -0
  58. data/sig/ruby_wasm/build.rbs +327 -0
  59. data/sig/ruby_wasm/cli.rbs +51 -0
  60. data/sig/ruby_wasm/ext.rbs +26 -0
  61. data/sig/ruby_wasm/packager.rbs +122 -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,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
@@ -0,0 +1,3 @@
1
+ module RubyWasm
2
+ VERSION = "2.5.1"
3
+ 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