Skip to content

Commit

Permalink
Added deploy-time patching to support ffi-compiler/ffi-compiler2 gems (
Browse files Browse the repository at this point in the history
  • Loading branch information
maxirmx committed Jun 2, 2024
1 parent 879a820 commit 28fe76f
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 9 deletions.
36 changes: 30 additions & 6 deletions lib/tebako-runtime.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,42 @@ 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
# adapters to gems that shall be aware that they are running in tebako environment
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
102 changes: 102 additions & 0 deletions lib/tebako-runtime/pass-through/ffi-platform-stub.rb
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion lib/tebako-runtime/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@
# POSSIBILITY OF SUCH DAMAGE.

module TebakoRuntime
VERSION = "0.4.2"
VERSION = "0.5.0"
end
61 changes: 61 additions & 0 deletions spec/pass_through_spec.rb
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion spec/runtime_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion tebako-runtime.gemspec
Original file line number Diff line number Diff line change
@@ -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
#
Expand Down

0 comments on commit 28fe76f

Please sign in to comment.