110 lines
4.0 KiB
Ruby
110 lines
4.0 KiB
Ruby
#
|
|
# 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
|