diff --git a/lib/tebako-runtime.rb b/lib/tebako-runtime.rb index f8aaaa8..14fa21e 100644 --- a/lib/tebako-runtime.rb +++ b/lib/tebako-runtime.rb @@ -65,6 +65,31 @@ def self.process(name, map, title) puts "Tebako runtime: skipped [#{name}]" if log_enabled && !res_inner log_enabled end + + def self.process_all(name) + f1 = process(name, PRE_REQUIRE_MAP, "pre") + res = original_require name + f2 = process(name, POST_REQUIRE_MAP, "post") + + puts "Tebako runtime: req [#{name}]" unless f1 || f2 + res + end + + # Very special deploy-time patching + # It targets ffi-compiler/ffi-compiler2 that use some functions of + # deployed ffi to process other gems + # THis approach is not compatible with tebako on Windows because ffi + # is deployed with (inplib) reference to target tebako package that is + # not available at deploy time + def self.process_pass_through(name) + if name == "ffi" && RUBY_PLATFORM =~ /msys|mingw|cygwin/ + puts "Replacing ffi ffi-platform-stub" if log_enabled + res = original_require "tebako-runtime/pass-through/ffi-platform-stub" + else + res = original_require name + end + res + end end # Some would call it 'monkey patching' but in reality we are adding @@ -72,11 +97,10 @@ def self.process(name, map, title) module Kernel alias original_require require def require(name) - f1 = TebakoRuntime.process(name, TebakoRuntime::PRE_REQUIRE_MAP, "pre") - res = original_require name - f2 = TebakoRuntime.process(name, TebakoRuntime::POST_REQUIRE_MAP, "post") - - puts "Tebako runtime: req [#{name}]" unless f1 || f2 - res + if ENV["TEBAKO_PASS_THROUGH"] + TebakoRuntime.process_pass_through name + else + TebakoRuntime.process_all name + end end end diff --git a/lib/tebako-runtime/pass-through/ffi-platform-stub.rb b/lib/tebako-runtime/pass-through/ffi-platform-stub.rb new file mode 100644 index 0000000..bee2405 --- /dev/null +++ b/lib/tebako-runtime/pass-through/ffi-platform-stub.rb @@ -0,0 +1,102 @@ +# frozen_string_literal: true + +# Copyright (c) 2024 [Ribose Inc](https://www.ribose.com). +# All rights reserved. +# This file is a part of tebako +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +module FFI + module Platform + ARCH = case RbConfig::CONFIG["host_cpu"].downcase + when /amd64|x86_64|x64/ + "x86_64" + when /i\d86|x86|i86pc/ + "i386" + when /ppc64|powerpc64/ + "powerpc64" + when /ppc|powerpc/ + "powerpc" + when /sparcv9|sparc64/ + "sparcv9" + when /arm64|aarch64/ # MacOS calls it "arm64", other operating systems "aarch64" + "aarch64" + when /^arm/ + if OS == "darwin" # Ruby before 3.0 reports "arm" instead of "arm64" as host_cpu on darwin + "aarch64" + else + "arm" + end + else + RbConfig::CONFIG["host_cpu"].downcase + end + + OS = + case RbConfig::CONFIG["host_os"].downcase + when /linux/ + "linux" + when /darwin/ + "darwin" + when /freebsd/ + "freebsd" + when /netbsd/ + "netbsd" + when /openbsd/ + "openbsd" + when /dragonfly/ + "dragonflybsd" + when /sunos|solaris/ + "solaris" + when /mingw|mswin/ + "windows" + else + RbConfig::CONFIG["host_os"].downcase + end + + LIBPREFIX = case OS + when /windows|msys/ + "" + when /cygwin/ + "cyg" + else + "lib" + end + + LIBSUFFIX = case OS + when /darwin/ + "dylib" + when /windows|cygwin|msys/ + "dll" + else + # Punt and just assume a sane unix (i.e. anything but AIX) + # when /linux|bsd|solaris/ + # "so" + "so" + end + + PASS_THROUGH = true + + def self.mac? + RUBY_PLATFORM =~ /darwin/ + end + end +end diff --git a/lib/tebako-runtime/version.rb b/lib/tebako-runtime/version.rb index 64e6755..284bf36 100644 --- a/lib/tebako-runtime/version.rb +++ b/lib/tebako-runtime/version.rb @@ -26,5 +26,5 @@ # POSSIBILITY OF SUCH DAMAGE. module TebakoRuntime - VERSION = "0.4.2" + VERSION = "0.5.0" end diff --git a/spec/pass_through_spec.rb b/spec/pass_through_spec.rb new file mode 100644 index 0000000..ffdd5c2 --- /dev/null +++ b/spec/pass_through_spec.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +# Copyright (c) 2024 [Ribose Inc](https://www.ribose.com). +# All rights reserved. +# This file is a part of tebako +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +# rubocop:disable Metrics/BlockLength +RSpec.describe TebakoRuntime do + it "provides a stub for ffi gem in pass through mode on Windows" do + if RUBY_PLATFORM =~ /msys|mingw|cygwin/ + if defined?(FFI) + FFI::Platform.send(:remove_const, :OS) + FFI::Platform.send(:remove_const, :ARCH) + FFI::Platform.send(:remove_const, :LIBPREFIX) + FFI::Platform.send(:remove_const, :LIBSUFFIX) + FFI::Platform.send(:remove_const, :PASS_THROUGH) + end + ENV["TEBAKO_PASS_THROUGH"] = "1" + require "ffi" + + expect(defined?(FFI::Platform::OS)).to_not be_nil + expect(defined?(FFI::Platform::ARCH)).to_not be_nil + expect(defined?(FFI::Platform::LIBPREFIX)).to_not be_nil + expect(defined?(FFI::Platform::LIBSUFFIX)).to_not be_nil + expect(FFI::Platform::PASS_THROUGH).to eq(true) + end + end + + after do + if RUBY_PLATFORM =~ /msys|mingw|cygwin/ + ENV.delete("TEBAKO_PASS_THROUGH") + FFI::Platform.send(:remove_const, :OS) + FFI::Platform.send(:remove_const, :ARCH) + FFI::Platform.send(:remove_const, :LIBPREFIX) + FFI::Platform.send(:remove_const, :LIBSUFFIX) + FFI::Platform.send(:remove_const, :PASS_THROUGH) + end + end +end +# rubocop:enable Metrics/BlockLength diff --git a/spec/runtime_spec.rb b/spec/runtime_spec.rb index e84ef52..a10b879 100644 --- a/spec/runtime_spec.rb +++ b/spec/runtime_spec.rb @@ -182,7 +182,7 @@ def tmpdir_name end it "provides a pre-processor for seven-zip gem" do - sevenz_libs = RUBY_PLATFORM.downcase.match(/mswin|msys|cygwin|mingw/) ? ["7z.dll", "7z64.dll"] : ["7z.so"] + sevenz_libs = RUBY_PLATFORM =~ /msys|mingw|cygwin/ ? ["7z.dll", "7z64.dll"] : ["7z.so"] sevenz_libs.each do |sevenz_lib| sevenz_path = File.join(TebakoRuntime.full_gem_path("seven-zip"), "lib", "seven_zip_ruby", sevenz_lib).to_s sevenz_new_folder = TebakoRuntime::COMPILER_MEMFS_LIB_CACHE / "seven_zip_ruby" diff --git a/tebako-runtime.gemspec b/tebako-runtime.gemspec index e3ce20c..e91e389 100644 --- a/tebako-runtime.gemspec +++ b/tebako-runtime.gemspec @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright (c) 2023 [Ribose Inc](https://www.ribose.com). +# Copyright (c) 2023-2024 [Ribose Inc](https://www.ribose.com). # All rights reserved. # This file is a part of tebako #