Class: RubyWasm::Packager

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

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.

%w[ruby_wasm bundler]
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"

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.



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_optionsObject

Retrieves the build options used for building Ruby itself.



84
85
86
87
88
89
90
91
92
# File 'lib/ruby_wasm/packager.rb', line 84

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

#featuresObject



76
77
78
# File 'lib/ruby_wasm/packager.rb', line 76

def features
  @features
end

#full_build_optionsObject

Retrieves the resolved build options



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

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

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

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

Parameters:

  • executor (RubyWasm::BuildExecutor)

    The executor for building the Wasm binary.

  • dest_dir (String)

    The destination used to construct the filesystem.

  • options (Hash)

    The packaging options.

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
# 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
  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_dynamic_linking?
    # 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)

  wasm_bytes = RubyWasmExt.preinitialize(wasm_bytes) if options[:optimize]
  wasm_bytes
end

#ruby_core_buildObject



61
62
63
# File 'lib/ruby_wasm/packager.rb', line 61

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

#specsObject

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



69
70
71
72
73
74
# File 'lib/ruby_wasm/packager.rb', line 69

def specs
  return [] unless @definition
  @specs ||= @definition.resolve.materialize(@definition.requested_dependencies)
    .reject { |spec| EXCLUDED_GEMS.include?(spec.name) }
  @specs
end