class PackageConfig

Constants

IDENTIFIER_RE
SEPARATOR

Attributes

msvc_syntax[RW]
paths[R]

Public Class Methods

clear_configure_args_cache() click to toggle source
# File lib/pkg-config.rb, line 42
def clear_configure_args_cache
  @native_pkg_config = nil
  @custom_override_variables = nil
end
custom_override_variables() click to toggle source
# File lib/pkg-config.rb, line 38
def custom_override_variables
  @custom_override_variables ||= with_config("override-variables", "")
end
native_pkg_config() click to toggle source
# File lib/pkg-config.rb, line 33
def native_pkg_config
  @native_pkg_config ||= guess_native_pkg_config
end
new(name, options={}) click to toggle source
# File lib/pkg-config.rb, line 117
def initialize(name, options={})
  @name = name
  @options = options
  path = @options[:path] || ENV["PKG_CONFIG_PATH"]
  @paths = [path, guess_default_path].compact.join(SEPARATOR).split(SEPARATOR)
  @paths.unshift(*(@options[:paths] || []))
  @paths = normalize_paths(@paths)
  @msvc_syntax = @options[:msvc_syntax]
  @variables = @declarations = nil
  override_variables = self.class.custom_override_variables
  @override_variables = parse_override_variables(override_variables)
  default_override_variables = @options[:override_variables] || {}
  @override_variables = default_override_variables.merge(@override_variables)
end

Private Class Methods

guess_native_pkg_config() click to toggle source
# File lib/pkg-config.rb, line 56
def guess_native_pkg_config
  pkg_config = with_config("pkg-config", ENV["PKG_CONFIG"] || "pkg-config")
  pkg_config = Pathname.new(pkg_config)
  unless pkg_config.absolute?
    found_pkg_config = search_pkg_config_from_path(pkg_config)
    pkg_config = found_pkg_config if found_pkg_config
  end
  unless pkg_config.absolute?
    found_pkg_config = search_pkg_config_by_dln_find_exe(pkg_config)
    pkg_config = found_pkg_config if found_pkg_config
  end
  pkg_config
end
search_pkg_config_by_dln_find_exe(pkg_config) click to toggle source
# File lib/pkg-config.rb, line 78
def search_pkg_config_by_dln_find_exe(pkg_config)
  begin
    require "dl/import"
  rescue LoadError
    return nil
  end
  dln = Module.new
  dln.module_eval do
    if DL.const_defined?(:Importer)
      extend DL::Importer
    else
      extend DL::Importable
    end
    begin
      dlload RbConfig::CONFIG["LIBRUBY"]
    rescue RuntimeError
      return nil if $!.message == "unknown error"
      return nil if /: image not found\z/ =~ $!.message
      raise
    rescue DL::DLError
      return nil
    end
    begin
      extern "const char *dln_find_exe(const char *, const char *)"
    rescue DL::DLError
      return nil
    end
  end
  path = dln.dln_find_exe(pkg_config.to_s, nil)
  if path.nil? or path.size.zero?
    nil
  else
    Pathname(path.to_s)
  end
end
search_pkg_config_from_path(pkg_config) click to toggle source
# File lib/pkg-config.rb, line 70
def search_pkg_config_from_path(pkg_config)
  (ENV["PATH"] || "").split(SEPARATOR).each do |path|
    try_pkg_config = Pathname(path) + pkg_config
    return try_pkg_config if try_pkg_config.exist?
  end
  nil
end
with_config(config, default=nil) click to toggle source
Calls superclass method
# File lib/pkg-config.rb, line 48
def with_config(config, default=nil)
  if defined?(super)
    super
  else
    default
  end
end

Public Instance Methods

cflags() click to toggle source
# File lib/pkg-config.rb, line 144
def cflags
  path_flags, other_flags = collect_cflags
  (other_flags + path_flags).join(" ")
end
cflags_only_I() click to toggle source
# File lib/pkg-config.rb, line 149
def cflags_only_I
  collect_cflags[0].join(" ")
end
cflags_only_other() click to toggle source
# File lib/pkg-config.rb, line 153
def cflags_only_other
  collect_cflags[1].join(" ")
end
declaration(name) click to toggle source
# File lib/pkg-config.rb, line 195
def declaration(name)
  parse_pc if @declarations.nil?
  expand_value(@declarations[name])
end
description() click to toggle source
# File lib/pkg-config.rb, line 186
def description
  declaration("Description")
end
exist?() click to toggle source
# File lib/pkg-config.rb, line 132
def exist?
  not pc_path.nil?
end
libs() click to toggle source
# File lib/pkg-config.rb, line 157
def libs
  path_flags, other_flags = collect_libs
  (path_flags + other_flags).join(" ")
end
libs_only_L() click to toggle source
# File lib/pkg-config.rb, line 172
def libs_only_L
  collect_libs[0].find_all do |arg|
    if @msvc_syntax
      /\A\/libpath:/ =~ arg
    else
      /\A-L/ =~ arg
    end
  end.join(" ")
end
libs_only_l() click to toggle source
# File lib/pkg-config.rb, line 162
def libs_only_l
  collect_libs[1].find_all do |arg|
    if @msvc_syntax
      /\.lib\z/ =~ arg
    else
      /\A-l/ =~ arg
    end
  end.join(" ")
end
pc_path() click to toggle source
# File lib/pkg-config.rb, line 200
def pc_path
  @paths.each do |path|
    _pc_path = File.join(path, "#{@name}.pc")
    return _pc_path if File.exist?(_pc_path)
  end
  nil
end
requires() click to toggle source
# File lib/pkg-config.rb, line 136
def requires
  parse_requires(declaration("Requires"))
end
requires_private() click to toggle source
# File lib/pkg-config.rb, line 140
def requires_private
  parse_requires(declaration("Requires.private"))
end
variable(name) click to toggle source
# File lib/pkg-config.rb, line 190
def variable(name)
  parse_pc if @variables.nil?
  expand_value(@override_variables[name] || @variables[name])
end
version() click to toggle source
# File lib/pkg-config.rb, line 182
def version
  declaration("Version")
end

Private Instance Methods

all_required_packages() click to toggle source
# File lib/pkg-config.rb, line 410
def all_required_packages
  (requires_private + requires.reverse).reject do |package|
    @name == package
  end.uniq
end
collect_cflags() click to toggle source
# File lib/pkg-config.rb, line 209
def collect_cflags
  cflags_set = [declaration("Cflags")]
  cflags_set += required_packages.collect do |package|
    self.class.new(package, @options).cflags
  end
  cflags_set += private_required_packages.collect do |package|
    self.class.new(package, @options).cflags
  end
  all_cflags = normalize_cflags(Shellwords.split(cflags_set.join(" ")))
  path_flags, other_flags = all_cflags.partition {|flag| /\A-I/ =~ flag}
  path_flags = normalize_path_flags(path_flags, "-I")
  path_flags = remove_duplicated_include_paths(path_flags)
  path_flags = path_flags.reject do |flag|
    flag == "-I/usr/include"
  end
  if @msvc_syntax
    path_flags = path_flags.collect do |flag|
      flag.gsub(/\A-I/, "/I")
    end
  end
  [path_flags, other_flags]
end
collect_libs() click to toggle source
# File lib/pkg-config.rb, line 271
def collect_libs
  all_libs = required_packages.collect do |package|
    self.class.new(package, @options).libs
  end
  all_libs = [declaration("Libs")] + all_libs
  all_libs = all_libs.join(" ").gsub(/-([Ll]) /, '\1').split.uniq
  path_flags, other_flags = all_libs.partition {|flag| /\A-L/ =~ flag}
  path_flags = normalize_path_flags(path_flags, "-L")
  path_flags = path_flags.reject do |flag|
    /\A-L\/usr\/lib(?:64|x32)?\z/ =~ flag
  end
  if @msvc_syntax
    path_flags = path_flags.collect do |flag|
      flag.gsub(/\A-L/, "/libpath:")
    end
    other_flags = other_flags.collect do |flag|
      if /\A-l/ =~ flag
        "#{$POSTMATCH}.lib"
      else
        flag
      end
    end
  end
  [path_flags, other_flags]
end
expand_value(value) click to toggle source
# File lib/pkg-config.rb, line 331
def expand_value(value)
  return nil if value.nil?
  value.gsub(/\$\{(#{IDENTIFIER_RE})\}/) do
    variable($1)
  end
end
guess_default_path() click to toggle source
# File lib/pkg-config.rb, line 338
def guess_default_path
  arch_depended_path = Dir.glob("/usr/lib/*/pkgconfig")
  default_paths = [
    "/usr/local/lib64/pkgconfig",
    "/usr/local/libx32/pkgconfig",
    "/usr/local/lib/pkgconfig",
    "/usr/local/libdata/pkgconfig",
    "/opt/local/lib/pkgconfig",
    *arch_depended_path,
    "/usr/lib64/pkgconfig",
    "/usr/libx32/pkgconfig",
    "/usr/lib/pkgconfig",
    "/usr/libdata/pkgconfig",
    "/usr/X11/lib/pkgconfig",
    "/opt/X11/lib/pkgconfig",
    "/usr/share/pkgconfig",
  ]
  case RUBY_PLATFORM
  when "x86-mingw32"
    default_paths.concat(Dir.glob("c:/msys*/mingw32/lib/pkgconfig"))
  when "x64-mingw32"
    default_paths.concat(Dir.glob("c:/msys*/mingw64/lib/pkgconfig"))
  end
  libdir = ENV["PKG_CONFIG_LIBDIR"]
  default_paths.unshift(libdir) if libdir

  pkg_config = self.class.native_pkg_config
  return default_paths.join(SEPARATOR) unless pkg_config.absolute?

  pkg_config_prefix = pkg_config.parent.parent
  pkg_config_arch_depended_paths =
    Dir.glob((pkg_config_prefix + "lib/*/pkgconfig").to_s)
  paths = []
  paths.concat(pkg_config_arch_depended_paths)
  paths << (pkg_config_prefix + "lib64/pkgconfig").to_s
  paths << (pkg_config_prefix + "libx32/pkgconfig").to_s
  paths << (pkg_config_prefix + "lib/pkgconfig").to_s
  paths << (pkg_config_prefix + "libdata/pkgconfig").to_s
  if /-darwin\d+\z/ =~ RUBY_PLATFORM and
      /\A(\d+\.\d+)/ =~ %x`sw_vers -productVersion`
    mac_os_version = $1
    homebrew_repository_candidates = []
    brew_path = pkg_config_prefix + "bin" + "brew"
    if brew_path.exist?
      escaped_brew_path = Shellwords.escape(brew_path.to_s)
      homebrew_repository = %x`#{escaped_brew_path} --repository`.chomp
      homebrew_repository_candidates << Pathname.new(homebrew_repository)
    else
      homebrew_repository_candidates << pkg_config_prefix + "Homebrew"
      homebrew_repository_candidates << pkg_config_prefix
    end
    homebrew_repository_candidates.each do |candidate|
      path = candidate + "Library/Homebrew/os/mac/pkgconfig/#{mac_os_version}"
      paths << path.to_s if path.exist?
    end
  end
  paths.concat(default_paths)
  paths.join(SEPARATOR)
end
normalize_cflags(cflags) click to toggle source
# File lib/pkg-config.rb, line 250
def normalize_cflags(cflags)
  normalized_cflags = []
  enumerator = cflags.to_enum
  begin
    loop do
      cflag = enumerator.next
      normalized_cflags << cflag
      case cflag
      when "-I"
        normalized_cflags << enumerator.next
      end
    end
  rescue StopIteration
  end
  normalized_cflags
end
normalize_path_flags(path_flags, flag_option) click to toggle source
# File lib/pkg-config.rb, line 232
def normalize_path_flags(path_flags, flag_option)
  path_flags.collect do |path_flag|
    path = path_flag.sub(flag_option, "")
    prefix = ""
    case RUBY_PLATFORM
    when "x86-mingw32"
      prefix = Dir.glob("c:/msys{32,64,*}").first
    when "x64-mingw32"
      prefix = Dir.glob("c:/msys{64,*}").first
    end
    if /\A[a-z]:/i === path
      "#{flag_option}#{path}"
    else
      "#{flag_option}#{prefix}#{path}"
    end
  end
end
normalize_paths(paths) click to toggle source
# File lib/pkg-config.rb, line 416
def normalize_paths(paths)
  paths.reject do |path|
    path.empty? or !File.exist?(path)
  end
end
parse_override_variables(override_variables) click to toggle source
# File lib/pkg-config.rb, line 322
def parse_override_variables(override_variables)
  variables = {}
  override_variables.split(",").each do |variable|
    name, value = variable.split("=", 2)
    variables[name] = value
  end
  variables
end
parse_pc() click to toggle source
# File lib/pkg-config.rb, line 298
def parse_pc
  raise ".pc for #{@name} doesn't exist." unless exist?
  @variables = {}
  @declarations = {}
  File.open(pc_path) do |input|
    input.each_line do |line|
      line = line.gsub(/#.*/, '').strip
      next if line.empty?
      case line
      when /^(#{IDENTIFIER_RE})=/
        @variables[$1] = $POSTMATCH.strip
      when /^(#{IDENTIFIER_RE}):/
        @declarations[$1] = $POSTMATCH.strip
      end
    end
  end
end
parse_requires(requires) click to toggle source
# File lib/pkg-config.rb, line 316
def parse_requires(requires)
  return [] if requires.nil?
  requires_without_version = requires.gsub(/[<>]?=\s*[\d.]+\s*/, '')
  requires_without_version.split(/[,\s]+/)
end
private_required_packages() click to toggle source
# File lib/pkg-config.rb, line 404
def private_required_packages
  requires_private.reject do |package|
    @name == package
  end.uniq
end
remove_duplicated_include_paths(path_flags) click to toggle source
# File lib/pkg-config.rb, line 267
def remove_duplicated_include_paths(path_flags)
  path_flags.uniq
end
required_packages() click to toggle source
# File lib/pkg-config.rb, line 398
def required_packages
  requires.reject do |package|
    @name == package
  end.uniq
end