# Build mruby with a shared libmruby.so (in addition to the usual # libmruby.a / executables). # # Produces (in build/host/lib/): # libmruby.a the static archive (as in the default build) # libmruby.so the shared library, with SONAME=libmruby.so.. # libmruby.so.. symlink to libmruby.so (matches SONAME) # libmruby.map linker version script (MRUBY_) # # Also produces the matching libmruby_core.so + symlink for completeness. # # Symbol versioning ties to MRUBY_RELEASE_NO (e.g. MRUBY_40000 for 4.0.0). # mruby has historically had ABI breaks between TEENY versions, so the # version tag uses the full release number rather than just MAJOR.MINOR. # # The shared library is built FROM the static archive via # `-Wl,--whole-archive`, so the existing static-build pipeline (including # the test infrastructure) is unaffected. Executables in build/host/bin # remain statically linked; distros that want dynamically-linked # executables can rebuild them against the .so. # # NOTE: gcc/clang only — VisualC++ support requires a separate config. require "mruby/source" MRuby::Build.new do |conf| conf.toolchain # include the GEM box conf.gembox 'default' # -fPIC so the static archive's contents can be linked into the .so. conf.compilers.each do |cc| cc.flags << '-fPIC' end # Turn on `enable_debug` for better debugging conf.enable_debug conf.enable_bintest conf.enable_test end # Add the shared-library targets as a post-build pass, so the default # static-build pipeline remains untouched. MRuby.each_target do next unless name == "host" libdir = File.join(build_dir, libdir_name) vermap = File.join(build_dir, "libmruby.map") vertag = "MRUBY_#{MRuby::Source::MRUBY_RELEASE_NO}" # Generate the version script eagerly — it has no .o dependencies and is # tiny enough that lazy generation isn't worth the rake plumbing. mkdir_p File.dirname(vermap) File.write(vermap, <<~MAP) #{vertag} { global: *; local: *; }; MAP major = MRuby::Source::MRUBY_RELEASE_MAJOR minor = MRuby::Source::MRUBY_RELEASE_MINOR [ [libmruby_static, "libmruby"], [libmruby_core_static, "libmruby_core"], ].each do |archive, basename| so = File.join(libdir, "#{basename}.so") symlink = "#{so}.#{major}.#{minor}" soname = "#{basename}.so.#{major}.#{minor}" # Build .so from the static archive via --whole-archive. file so => [archive, vermap] do |t| _pp "LD", so.relative_path sh "#{cc.command} -shared -fPIC -o #{so}" \ " -Wl,-soname,#{soname}" \ " -Wl,--version-script=#{vermap}" \ " -Wl,--whole-archive #{archive} -Wl,--no-whole-archive" \ " -lm" end products << so # SONAME-matching symlink: needed so executables linked with -lmruby # (which embeds the SONAME as DT_NEEDED) can find the library at # runtime via standard search paths. file symlink => so do |t| _pp "LN", "#{symlink.relative_path} -> #{File.basename(so)}" rm_f symlink File.symlink(File.basename(so), symlink) end products << symlink end end