lib/ffi/library_path.rb
# # Copyright (C) 2023 Lars Kanis # # This file is part of ruby-ffi. # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # * 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. # * Neither the name of the Ruby FFI project nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # 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 OWNER 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 # Transform a generic library name and ABI number to a platform library name # # Example: # module LibVips # extend FFI::Library # ffi_lib LibraryPath.new("vips", abi_number: 42) # end # # This translates to the following library file names: # libvips-42.dll on Windows # libvips.so.42 on Linux # libvips.42.dylib on Macos # # See https://packaging.ubuntu.com/html/libraries.html for more information about library naming. class LibraryPath attr_reader :name attr_reader :abi_number attr_reader :root # Build a new library path # # * <tt>name</tt> : The name of the library without file prefix or suffix. # * <tt>abi_number</tt> : The ABI number of the library. # * <tt>root</tt> : An optional base path prepended to the library name. def initialize(name, abi_number: nil, root: nil) @name = name @abi_number = abi_number @root = root end def self.wrap(value) # We allow instances of LibraryPath to pass through transparently: return value if value.is_a?(self) # We special case a library named 'c' to be the standard C library: return Library::LIBC if value == 'c' # If provided a relative file name we convert it into a library path: if value && File.basename(value) == value return self.new(value) end # Otherwise, we assume it's a full path to a library: return value end def full_name # If the abi_number is given, we format it specifically according to platform rules: if abi_number if Platform.windows? "#{Platform::LIBPREFIX}#{name}-#{abi_number}.#{Platform::LIBSUFFIX}" elsif Platform.mac? "#{Platform::LIBPREFIX}#{name}.#{abi_number}.#{Platform::LIBSUFFIX}" else # Linux? BSD? etc. "#{Platform::LIBPREFIX}#{name}.#{Platform::LIBSUFFIX}.#{abi_number}" end else # Otherwise we just add prefix and suffix: lib = name # Add library prefix if missing lib = Platform::LIBPREFIX + lib unless lib =~ /^#{Platform::LIBPREFIX}/ # Add library extension if missing r = Platform.windows? || Platform.mac? ? "\\.#{Platform::LIBSUFFIX}$" : "\\.so($|\\.[1234567890]+)" lib += ".#{Platform::LIBSUFFIX}" unless lib =~ /#{r}/ lib end end def to_s if root # If the root path is given, we generate the full path: File.join(root, full_name) else full_name end end end end