Class: RubyWasm::Packager

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_wasm/packager.rb,
sig/ruby_wasm/packager.rbs

Overview

A class responsible for packaging whole Ruby project

Defined Under Namespace

Modules: ComponentAdapter Classes: Core, FileSystem

Constant Summary collapse

EXCLUDED_GEMS =

The list of excluded gems from the Bundler definition.

Returns:

  • (Array[string])
%w[ruby_wasm bundler]
ALL_DEFAULT_EXTS =

Returns:

  • (String)
"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"

Instance Method Summary collapse

Constructor Details

#initialize(root, config = nil, definition = nil, features: RubyWasm::FeatureSet.derive_from_env) ⇒ Packager

Initializes a new instance of the RubyWasm::Packager class.

Parameters:

  • root (String)

    The root directory of the Ruby project. The root directory (will) contain the following files:

    • build_manifest.json
    • rubies
    • build
  • config (Hash) (defaults to: nil)

    The build config used for building Ruby.

  • definition (Bundler::Definition) (defaults to: nil)

    The Bundler definition.

  • features (RubyWasm::FeatureSet) (defaults to: RubyWasm::FeatureSet.derive_from_env)

    The features used for packaging.

  • (build_config, nil)
  • features: (RubyWasm::FeatureSet) (defaults to: RubyWasm::FeatureSet.derive_from_env)


13
14
15
16
17
18
# File 'lib/ruby_wasm/packager.rb', line 13

def initialize(root, config = nil, definition = nil, features: RubyWasm::FeatureSet.derive_from_env)
  @root = root
  @definition = definition
  @config = config
  @features = features
end

Instance Method Details

#build_optionsHash[Symbol, untyped]

Retrieves the build options used for building Ruby itself.

Returns:

  • (Hash[Symbol, untyped])


98
99
100
101
102
103
104
105
106
# File 'lib/ruby_wasm/packager.rb', line 98

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

#featuresRubyWasm::FeatureSet



90
91
92
# File 'lib/ruby_wasm/packager.rb', line 90

def features
  @features
end

#full_build_optionsHash[Symbol, untyped]

Retrieves the resolved build options

Returns:

  • (Hash[Symbol, untyped])


109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/ruby_wasm/packager.rb', line 109

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], options, build_dir)
  options.merge(
    toolchain: toolchain,
    build_dir: build_dir,
    rubies_dir: rubies_dir,
    src: options[:src]
  )
end

#package(executor, dest_dir, options) ⇒ Array<Integer>

Packages the Ruby code into a Wasm binary. (including extensions)

Parameters:

Returns:

  • (Array<Integer>)

    The bytes of the packaged Wasm binary.



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
# File 'lib/ruby_wasm/packager.rb', line 26

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
end

#rootstring

Returns:

  • (string)


38
# File 'sig/ruby_wasm/packager.rbs', line 38

def root: () -> string

#ruby_core_buildRubyWasm::Packager::Core



74
75
76
# File 'lib/ruby_wasm/packager.rb', line 74

def ruby_core_build
  @ruby_core_build ||= RubyWasm::Packager::Core.new(self)
end

#specsArray[untyped]

Retrieves the specs from the Bundler definition, excluding the excluded gems.

Returns:

  • (Array[untyped])


82
83
84
85
86
87
88
# File 'lib/ruby_wasm/packager.rb', line 82

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