From badc3585fb58ff89a56d77d0eb0e0559d41d23f4 Mon Sep 17 00:00:00 2001 From: Kleis Auke Wolthuizen Date: Mon, 4 Mar 2024 15:48:35 +0100 Subject: [PATCH 1/4] Ensure compatibility with a single shared libvips library See: #372. --- lib/vips.rb | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/vips.rb b/lib/vips.rb index f0e7461..b260850 100644 --- a/lib/vips.rb +++ b/lib/vips.rb @@ -42,7 +42,19 @@ class << self extend FFI::Library - ffi_lib library_name("glib-2.0", 0) + if FFI::Platform.windows? + # On Windows, `GetProcAddress()` can only search in a specified DLL and + # doesn't look into its dependent libraries for symbols. Therefore, we + # check if the GLib DLLs are available. If these can not be found, we + # assume that GLib is statically linked into libvips. + ffi_lib ["libglib-2.0-0.dll", "libvips-42.dll"] + else + # macOS and *nix uses `dlsym()`, which also searches for named symbols + # in the dependencies of the shared library. Therefore, we can support + # a single shared libvips library with all dependencies statically + # linked. + ffi_lib library_name("vips", 42) + end attach_function :g_malloc, [:size_t], :pointer @@ -134,7 +146,11 @@ def self.set_log_domain domain module GObject extend FFI::Library - ffi_lib library_name("gobject-2.0", 0) + if FFI::Platform.windows? + ffi_lib ["libgobject-2.0-0.dll", "libvips-42.dll"] + else + ffi_lib library_name("vips", 42) + end # we can't just use ulong, windows has different int sizing rules if FFI::Platform::ADDRESS_SIZE == 64 From 2c55d8bb5e095c9c7a4b20e36841350412c653f8 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 5 Mar 2024 12:53:16 +0000 Subject: [PATCH 2/4] fix compat with semistatic libvips we must fetch `g_*()` funcs from libvips if we can --- CHANGELOG.md | 2 ++ lib/vips.rb | 50 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c3c1d6..38a12a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## master +* fix compat with unified (semistatic) libvips binaries [kleisauke] + ## Version 2.2.1 (2024-02-21) * add `Vips.block_untrusted` method to block all untrusted operations. Only for libvips >= 8.13. [Docs](https://www.libvips.org/API/current/libvips-vips.html#vips-block-untrusted-set). [#382](https://github.com/libvips/ruby-vips/pull/382) [aglushkov](https://github.com/aglushkov) diff --git a/lib/vips.rb b/lib/vips.rb index b260850..45c103d 100644 --- a/lib/vips.rb +++ b/lib/vips.rb @@ -33,6 +33,30 @@ def library_name(name, abi_number) end end +# we can sometimes get dependent libraries from libvips -- either the platform +# will open dependencies for us automatically, or the libvips binary has been +# built to includes all main dependencies (common on windows, can happen +# elsewhere) +# +# we must get glib functions from libvips if we can, since it will be the +# one that libvips itself is using, and they will share runtime types +module Vips + extend FFI::Library + + ffi_lib library_name("vips", 42) + + begin + attach_function :g_malloc, [:size_t], :pointer + @@is_unified = true + rescue => e + @@is_unified = false + end + + def self.unified? + @@is_unified + end +end + module GLib class << self attr_accessor :logger @@ -42,18 +66,10 @@ class << self extend FFI::Library - if FFI::Platform.windows? - # On Windows, `GetProcAddress()` can only search in a specified DLL and - # doesn't look into its dependent libraries for symbols. Therefore, we - # check if the GLib DLLs are available. If these can not be found, we - # assume that GLib is statically linked into libvips. - ffi_lib ["libglib-2.0-0.dll", "libvips-42.dll"] - else - # macOS and *nix uses `dlsym()`, which also searches for named symbols - # in the dependencies of the shared library. Therefore, we can support - # a single shared libvips library with all dependencies statically - # linked. + if Vips::unified? ffi_lib library_name("vips", 42) + else + ffi_lib library_name("glib-2.0", 0) end attach_function :g_malloc, [:size_t], :pointer @@ -146,10 +162,10 @@ def self.set_log_domain domain module GObject extend FFI::Library - if FFI::Platform.windows? - ffi_lib ["libgobject-2.0-0.dll", "libvips-42.dll"] - else + if Vips::unified? ffi_lib library_name("vips", 42) + else + ffi_lib library_name("gobject-2.0", 0) end # we can't just use ulong, windows has different int sizing rules @@ -584,10 +600,8 @@ module GObject # {Image#median}. module Vips - extend FFI::Library - - ffi_lib library_name("vips", 42) - + # we've already opened the libvips library + LOG_DOMAIN = "VIPS" GLib.set_log_domain LOG_DOMAIN From 491d7d9d176f6baaa656d6126b358daf5b27d124 Mon Sep 17 00:00:00 2001 From: Kleis Auke Wolthuizen Date: Thu, 7 Mar 2024 10:53:03 +0100 Subject: [PATCH 3/4] Fix compat with shared Windows builds --- lib/vips.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/vips.rb b/lib/vips.rb index 45c103d..3d55024 100644 --- a/lib/vips.rb +++ b/lib/vips.rb @@ -48,7 +48,7 @@ module Vips begin attach_function :g_malloc, [:size_t], :pointer @@is_unified = true - rescue => e + rescue FFI::NotFoundError @@is_unified = false end From 2cb995d56ca9023a69d487dc83b499ea7759759a Mon Sep 17 00:00:00 2001 From: Kleis Auke Wolthuizen Date: Thu, 7 Mar 2024 10:56:45 +0100 Subject: [PATCH 4/4] Fix lint --- lib/vips.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/vips.rb b/lib/vips.rb index 3d55024..92af2e2 100644 --- a/lib/vips.rb +++ b/lib/vips.rb @@ -66,7 +66,7 @@ class << self extend FFI::Library - if Vips::unified? + if Vips.unified? ffi_lib library_name("vips", 42) else ffi_lib library_name("glib-2.0", 0) @@ -162,7 +162,7 @@ def self.set_log_domain domain module GObject extend FFI::Library - if Vips::unified? + if Vips.unified? ffi_lib library_name("vips", 42) else ffi_lib library_name("gobject-2.0", 0) @@ -601,7 +601,7 @@ module GObject module Vips # we've already opened the libvips library - + LOG_DOMAIN = "VIPS" GLib.set_log_domain LOG_DOMAIN