Skip to content

Commit efc25a6

Browse files
Install gem extension libraries in the GEM_HOME
instead of ruby installation directory.
1 parent 3ed0131 commit efc25a6

File tree

5 files changed

+55
-27
lines changed

5 files changed

+55
-27
lines changed

lib/ruby_wasm/build/product/crossruby.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def make_args(crossruby)
4242
make_args
4343
end
4444

45-
def build(executor, crossruby)
45+
def build(executor, crossruby, extra_mkargs = [])
4646
objdir = product_build_dir crossruby
4747
executor.mkdir_p objdir
4848
do_extconf executor, crossruby
@@ -54,7 +54,8 @@ def build(executor, crossruby)
5454
"-C",
5555
"#{objdir}",
5656
*make_args(crossruby),
57-
build_target
57+
build_target,
58+
*extra_mkargs
5859
# A ext can provide link args by link.filelist. It contains only built archive file by default.
5960
unless File.exist?(linklist(crossruby))
6061
executor.write(
@@ -187,7 +188,7 @@ def need_extinit_obj?
187188
def build_exts(executor)
188189
@user_exts.each do |prod|
189190
executor.begin_section prod.class, prod.name, "Building"
190-
prod.build(executor, self)
191+
prod.build(executor, self, [])
191192
executor.end_section prod.class, prod.name
192193
end
193194
end

lib/ruby_wasm/packager.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ def package(executor, dest_dir, options)
3232

3333
wasm_bytes = File.binread(File.join(fs.ruby_root, "bin", "ruby"))
3434

35+
ruby_core.build_gem_exts(executor, fs.bundle_dir)
36+
3537
fs.package_gems
3638
fs.remove_non_runtime_files(executor)
3739
fs.remove_stdlib(executor) unless options[:stdlib]
@@ -44,7 +46,7 @@ def package(executor, dest_dir, options)
4446

4547
wasm_bytes = wasi_vfs.pack(wasm_bytes)
4648
end
47-
wasm_bytes = ruby_core.build_and_link_exts(executor, wasm_bytes)
49+
wasm_bytes = ruby_core.link_gem_exts(executor, fs.bundle_dir, wasm_bytes)
4850

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

lib/ruby_wasm/packager/core.rb

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def build(executor, options)
1212

1313
extend Forwardable
1414

15-
def_delegators :build_strategy, :cache_key, :artifact, :build_and_link_exts
15+
def_delegators :build_strategy, :cache_key, :artifact, :build_gem_exts, :link_gem_exts
1616

1717
private
1818

@@ -37,7 +37,11 @@ def build(executor, options)
3737
raise NotImplementedError
3838
end
3939

40-
def build_and_link_exts(executor, module_bytes)
40+
def build_gem_exts(executor, gem_home)
41+
raise NotImplementedError
42+
end
43+
44+
def link_gem_exts(executor, gem_home, module_bytes)
4145
raise NotImplementedError
4246
end
4347

@@ -93,13 +97,17 @@ def build(executor, options)
9397
build.crossruby.artifact
9498
end
9599

96-
def build_and_link_exts(executor, module_bytes)
100+
def build_gem_exts(executor, gem_home)
97101
build = derive_build
98-
self.build_exts(executor, build)
99-
self.link_exts(executor, build)
102+
self._build_gem_exts(executor, build, gem_home)
100103
end
101104

102-
def link_exts(executor, build)
105+
def link_gem_exts(executor, gem_home, module_bytes)
106+
build = derive_build
107+
self._link_gem_exts(executor, build, gem_home)
108+
end
109+
110+
def _link_gem_exts(executor, build, gem_home)
103111
ruby_root = build.crossruby.dest_dir
104112

105113
libraries = [File.join(ruby_root, "usr", "local", "bin", "ruby")]
@@ -121,7 +129,10 @@ def link_exts(executor, build)
121129
end
122130
wasi_adapter = RubyWasm::Packager::ComponentAdapter.wasi_snapshot_preview1("command")
123131
adapters = [wasi_adapter]
124-
dl_openable_libs = Dir.glob(File.join(ruby_root, "usr", "local", "lib", "ruby", "**", "*.so"))
132+
dl_openable_libs = []
133+
dl_openable_libs << [File.join(ruby_root, "usr"), Dir.glob(File.join(ruby_root, "usr", "local", "lib", "ruby", "**", "*.so"))]
134+
dl_openable_libs << [gem_home, Dir.glob(File.join(gem_home, "gems", "**", "*.so"))]
135+
125136
linker = RubyWasmExt::ComponentLink.new
126137
linker.use_built_in_libdl(true)
127138
linker.stub_missing_functions(false)
@@ -135,12 +146,14 @@ def link_exts(executor, build)
135146
linker.library(lib_name, module_bytes, false)
136147
end
137148

138-
dl_openable_libs.each do |lib|
139-
# DL openable lib_name should be a relative path from ruby_root
140-
lib_name = "/" + Pathname.new(lib).relative_path_from(Pathname.new(ruby_root)).to_s
141-
module_bytes = File.binread(lib)
142-
RubyWasm.logger.info "Linking #{lib_name} (#{module_bytes.size} bytes)"
143-
linker.library(lib_name, module_bytes, true)
149+
dl_openable_libs.each do |root, libs|
150+
libs.each do |lib|
151+
# DL openable lib_name should be a relative path from ruby_root
152+
lib_name = "/" + Pathname.new(lib).relative_path_from(Pathname.new(File.dirname(root))).to_s
153+
module_bytes = File.binread(lib)
154+
RubyWasm.logger.info "Linking #{lib_name} (#{module_bytes.size} bytes)"
155+
linker.library(lib_name, module_bytes, true)
156+
end
144157
end
145158

146159
adapters.each do |adapter|
@@ -153,24 +166,30 @@ def link_exts(executor, build)
153166
return linker.encode()
154167
end
155168

156-
def build_exts(executor, build)
169+
def _build_gem_exts(executor, build, gem_home)
157170
exts = specs_with_extensions.flat_map do |spec, exts|
158171
exts.map do |ext|
159172
ext_feature = File.dirname(ext) # e.g. "ext/cgi/escape"
160173
ext_srcdir = File.join(spec.full_gem_path, ext_feature)
161174
ext_relative_path = File.join(spec.full_name, ext_feature)
162-
RubyWasm::CrossRubyExtProduct.new(
175+
prod = RubyWasm::CrossRubyExtProduct.new(
163176
ext_srcdir,
164177
build.toolchain,
165178
features: @packager.features,
166179
ext_relative_path: ext_relative_path
167180
)
181+
[prod, spec]
168182
end
169183
end
170184

171-
exts.each do |prod|
185+
exts.each do |prod, spec|
186+
libdir = File.join(gem_home, "gems", spec.full_name, spec.raw_require_paths.first)
187+
extra_mkargs = [
188+
"sitearchdir=#{libdir}",
189+
"sitelibdir=#{libdir}",
190+
]
172191
executor.begin_section prod.class, prod.name, "Building"
173-
prod.build(executor, build.crossruby)
192+
prod.build(executor, build.crossruby, extra_mkargs)
174193
executor.end_section prod.class, prod.name
175194
end
176195
end
@@ -301,7 +320,11 @@ def derive_build
301320
build
302321
end
303322

304-
def build_and_link_exts(executor, module_bytes)
323+
def build_gem_exts(executor, gem_home)
324+
# No-op because we already built extensions as part of the Ruby build
325+
end
326+
327+
def link_gem_exts(executor, gem_home, module_bytes)
305328
return module_bytes unless @packager.features.support_component_model?
306329

307330
linker = RubyWasmExt::ComponentEncode.new

sig/ruby_wasm/build.rbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ module RubyWasm
168168
def feature_name: (CrossRubyProduct crossruby) -> String
169169

170170
def make_args: (CrossRubyProduct crossruby) -> Array[String]
171-
def build: (BuildExecutor executor, CrossRubyProduct crossruby) -> void
171+
def build: (BuildExecutor executor, CrossRubyProduct crossruby, Array[String] extra_mkargs) -> void
172172
def do_extconf: (BuildExecutor executor, CrossRubyProduct crossruby) -> void
173173
def do_install_rb: (BuildExecutor executor, CrossRubyProduct crossruby) -> void
174174

sig/ruby_wasm/packager.rbs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ class RubyWasm::Packager
5656
@packager: RubyWasm::Packager
5757
def initialize: (RubyWasm::Packager) -> void
5858
def build: (RubyWasm::BuildExecutor, untyped options) -> String
59-
def build_and_link_exts: (RubyWasm::BuildExecutor, bytes module_bytes) -> bytes
59+
def build_gem_exts: (RubyWasm::BuildExecutor, string gem_home) -> void
60+
def link_gem_exts: (RubyWasm::BuildExecutor, string gem_home, bytes module_bytes) -> bytes
6061

6162
extend Forwardable
6263

@@ -72,16 +73,17 @@ class RubyWasm::Packager
7273
def initialize: (RubyWasm::Packager) -> void
7374
def build: (RubyWasm::BuildExecutor, untyped options) -> String
7475
def specs_with_extensions: () -> Array[[untyped, Array[string]]]
75-
def build_and_link_exts: (RubyWasm::BuildExecutor, bytes module_bytes) -> bytes
76+
def build_gem_exts: (RubyWasm::BuildExecutor, string gem_home) -> void
77+
def link_gem_exts: (RubyWasm::BuildExecutor, string gem_home, bytes module_bytes) -> bytes
7678
end
7779

7880
class DynamicLinking < RubyWasm::Packager::Core::BuildStrategy
7981
@build: RubyWasm::Build
8082
def derive_build: () -> RubyWasm::Build
81-
def build_exts: (RubyWasm::BuildExecutor, RubyWasm::Build) -> void
8283
def name: () -> string
8384

84-
private def link_exts: (RubyWasm::BuildExecutor, RubyWasm::Build) -> bytes
85+
private def _build_gem_exts: (RubyWasm::BuildExecutor, RubyWasm::Build, string gem_home) -> void
86+
private def _link_gem_exts: (RubyWasm::BuildExecutor, RubyWasm::Build, string gem_home) -> bytes
8587
end
8688

8789
class StaticLinking < RubyWasm::Packager::Core::BuildStrategy

0 commit comments

Comments
 (0)