From 120ec8fa0c582e911845f325c8d144a967bee097 Mon Sep 17 00:00:00 2001 From: Oleksii Lozovskyi Date: Thu, 21 Apr 2022 19:26:16 +0900 Subject: [PATCH] rbthemis: Extra effort to locate Themis Core library (#917) Just like with PyThemis, migrate RbThemis to the same pattern of loading Themis Core library dynamically with more attention to versioning. Detect the platform and load properly versioned libraries first, reducing the chance for an ABI mismatch. However, keep the 'themis' as a fallback (and a default action for Windows). Ruby's "ffi_lib" is in some ways more smart than Python's find_library (it supports Apple M1 by accident, for example) but in some ways it's also dumber. Don't depend on ffi's maintainers and hardcode a list of absolute paths to try first in attempt to make things "just work". --- CHANGELOG.md | 4 +++ src/wrappers/themis/ruby/lib/rbthemis.rb | 45 +++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83b0b1fcf..62af20a16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,10 @@ _Code:_ - `pythemis.scomparator` and `pythemis.skeygen` are now imported with `from pythemis import *` ([#914](https://github.com/cossacklabs/themis/pull/914)). - Improved compatibility with non-Homebrew Python installations on Apple M1 ([#915](https://github.com/cossacklabs/themis/pull/915)). +- **Ruby** + + - Improved compatibility with non-standard installations on Apple M1 ([#917](https://github.com/cossacklabs/themis/pull/917)). + - **Rust** - `SecureSessionTransport` implementations are now required to be `Send` ([#898](https://github.com/cossacklabs/themis/pull/898)). diff --git a/src/wrappers/themis/ruby/lib/rbthemis.rb b/src/wrappers/themis/ruby/lib/rbthemis.rb index fc75be718..7e48b2cb3 100644 --- a/src/wrappers/themis/ruby/lib/rbthemis.rb +++ b/src/wrappers/themis/ruby/lib/rbthemis.rb @@ -32,7 +32,50 @@ def empty?(value) module ThemisImport extend FFI::Library - ffi_lib 'themis' + + def self.canonical_themis_paths + host_os = RbConfig::CONFIG['host_os'] + paths = [] + if host_os.start_with? 'linux' + # Default library installation path for "make install" + paths.append '/usr/local/lib/libthemis.so.0' + # Don't bother figuring out the "right" absolute path, since + # that depends on the distro and non-distro-provided Rubies + # don't know about the right paths at all. The ones installed + # via RVM certainly don't. Use soname and let ld figure it out. + paths.append 'libthemis.so.0' + end + if host_os.start_with? 'darwin' + # Default library installation path for "make install" + paths.append '/usr/local/lib/libthemis.0.dylib' + # These are install names of libraries installed via Homebrew + # Add both M1 and Intel paths so that x86 Ruby works on M1 + paths.append '/opt/homebrew/opt/libthemis/lib/libthemis.0.dylib' + paths.append '/usr/local/opt/libthemis/lib/libthemis.0.dylib' + # Last try, look for ABI-qualified name + paths.append 'libthemis.0.dylib' + end + return paths + end + + def self.load_themis + for path in canonical_themis_paths + begin + return ffi_lib path + rescue LoadError + next + end + end + warn <<~EOF + WARN: failed to load the canonical Themis Core library + + Proceeding to find 'themis' library in standard paths. + This might cause ABI mismatch and crash the process. + EOF + return ffi_lib 'themis' + end + + load_themis callback :get_pub_key_by_id_type, [:pointer, :int, :pointer, :int, :pointer], :int