-
Notifications
You must be signed in to change notification settings - Fork 60
/
Copy pathpackager.rb
122 lines (106 loc) · 4.26 KB
/
packager.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# A class responsible for packaging whole Ruby project
class RubyWasm::Packager
# Initializes a new instance of the RubyWasm::Packager class.
#
# @param root [String] The root directory of the Ruby project.
# The root directory (will) contain the following files:
# * build_manifest.json
# * rubies
# * build
# @param config [Hash] The build config used for building Ruby.
# @param definition [Bundler::Definition] The Bundler definition.
# @param features [RubyWasm::FeatureSet] The features used for packaging.
def initialize(root, config = nil, definition = nil, features: RubyWasm::FeatureSet.derive_from_env)
@root = root
@definition = definition
@config = config
@features = features
end
# Packages the Ruby code into a Wasm binary. (including extensions)
#
# @param executor [RubyWasm::BuildExecutor] The executor for building the Wasm binary.
# @param dest_dir [String] The destination used to construct the filesystem.
# @param options [Hash] The packaging options.
# @return [Array<Integer>] The bytes of the packaged Wasm binary.
def package(executor, dest_dir, options)
ruby_core = self.ruby_core_build()
tarball = ruby_core.build(executor, options)
fs = RubyWasm::Packager::FileSystem.new(dest_dir, self)
fs.package_ruby_root(tarball, executor)
wasm_bytes = File.binread(File.join(fs.ruby_root, "bin", "ruby"))
ruby_core.build_gem_exts(executor, fs.bundle_dir)
fs.package_gems unless features.support_component_model?
fs.remove_non_runtime_files(executor)
if options[:stdlib]
options[:without_stdlib_components].each do |component|
fs.remove_stdlib_component(executor, component)
end
else
fs.remove_stdlib(executor)
end
if full_build_options[:target] == "wasm32-unknown-wasip1" && !features.support_component_model?
# wasi-vfs supports only WASI target
wasi_vfs = RubyWasmExt::WasiVfs.new
wasi_vfs.map_dir("/bundle", fs.bundle_dir)
wasi_vfs.map_dir("/usr", File.dirname(fs.ruby_root))
wasm_bytes = wasi_vfs.pack(wasm_bytes)
end
wasm_bytes = ruby_core.link_gem_exts(executor, fs.ruby_root, fs.bundle_dir, wasm_bytes)
if features.support_component_model?
wasi_virt = RubyWasmExt::WasiVirt.new
wasi_virt.allow_all
[
{ guest: "/bundle", host: fs.bundle_dir },
{ guest: "/usr", host: File.dirname(fs.ruby_root) }
].each do |map|
map => { guest:, host: }
RubyWasm.logger.debug "Adding files into VFS: #{host} => #{guest}"
wasi_virt.map_dir(guest, host)
end
wasm_bytes = wasi_virt.compose(wasm_bytes)
end
wasm_bytes = RubyWasmExt.preinitialize(wasm_bytes) if options[:optimize]
wasm_bytes
end
def ruby_core_build
@ruby_core_build ||= RubyWasm::Packager::Core.new(self)
end
# The list of excluded gems from the Bundler definition.
EXCLUDED_GEMS = %w[ruby_wasm bundler]
# Retrieves the specs from the Bundler definition, excluding the excluded gems.
def specs
return [] unless @definition
__skip__ = @specs ||= @definition.resolve.materialize(@definition.requested_dependencies)
.reject { |spec| EXCLUDED_GEMS.include?(spec.name) }
.reject { |spec| spec.is_a?(Bundler::LazySpecification) }
@specs
end
def features
@features
end
ALL_DEFAULT_EXTS =
"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,io/console"
# Retrieves the build options used for building Ruby itself.
def build_options
default = {
target: RubyWasm::Target.new("wasm32-unknown-wasip1"),
default_exts: ALL_DEFAULT_EXTS
}
override = @config || {}
# Merge the default options with the config options
default.merge(override)
end
# Retrieves the resolved build options
def full_build_options
options = build_options
build_dir = File.join(@root, "build")
rubies_dir = File.join(@root, "rubies")
toolchain = RubyWasm::Toolchain.get(options[:target], build_dir)
options.merge(
toolchain: toolchain,
build_dir: build_dir,
rubies_dir: rubies_dir,
src: options[:src]
)
end
end