Class: Utilrb::PkgConfig
Overview
Access to information from pkg-config(1)
This class allows to enumerate the pkg-config packages available, and create a PkgConfig object that allows to get access to the pkgconfig information.
Create a new pkgconfig object with
pkg = PkgConfig.new(name)
It raises PkgConfig::NotFound if the package is not available.
Then, the classical include directory and library directory flags can be listed with
pkg.include_dirs
pkg.library_dirs
Standard fields are available with
pkg.cflags
pkg.cflags_only_I
pkg.cflags_only_other
pkg.libs
pkg.libs_only_L
pkg.libs_only_l
pkg.libs_only_other
pkg.static
Arbitrary variables defined in the .pc file can be accessed with
pkg.prefix
pkg.libdir
Defined Under Namespace
Classes: DependencyLoop, Invalid, NotFound
Constant Summary collapse
- PACKAGE_NAME_RX =
/[\w\-\.]+/- VAR_NAME_RX =
/\w+/- FIELD_NAME_RX =
/[\w\.\-]+/- SHELL_VARS =
%w{Cflags Libs Libs.private}
- ACTIONS =
%w{cflags cflags-only-I cflags-only-other libs libs-only-L libs-only-l libs-only-other}
- PKGCONFIG_PATH_RX =
%r{.*/((?:lib|lib64|share)/.*)}.freeze
Instance Attribute Summary collapse
-
#description ⇒ Object
readonly
Returns the value of attribute description.
-
#fields ⇒ Object
readonly
Returns the value of attribute fields.
-
#name ⇒ Object
readonly
The module name.
-
#path ⇒ Object
readonly
Returns the value of attribute path.
-
#raw_fields ⇒ Object
readonly
Returns the value of attribute raw_fields.
-
#raw_version ⇒ Object
readonly
The module version as a string.
-
#requires ⇒ Array<PkgConfig>
readonly
The list of packages that are Require:‘d by this package.
-
#variables ⇒ Object
readonly
Information extracted from the file.
-
#version ⇒ Object
readonly
The module version, as an array of integers.
Class Method Summary collapse
- .arch_dir ⇒ Object
- .available_package_names(pkg_config_path: self.pkg_config_path) ⇒ Object
-
.clear_cache ⇒ Object
deprecated
Deprecated.
PkgConfig does not cache the packages anymore, so no need to call this method
-
.default_search_path ⇒ Object
Returns the system-wide search path that is embedded in pkg-config.
-
.default_search_path_I ⇒ Object
rubocop:disable Naming/MethodName.
-
.default_search_path_L ⇒ Object
rubocop:disable Naming/MethodName.
-
.default_search_suffixes ⇒ Object
Returns the system-wide standard suffixes that should be appended to new prefixes to find pkg-config files.
-
.define_pkgconfig_action(action) ⇒ Object
:nodoc:.
-
.each_package(regex = nil, pkg_config_path: self.pkg_config_path) ⇒ Object
Yields the package names of available packages.
- .each_pkgconfig_directory(pkg_config_path: self.pkg_config_path, &block) ⇒ Object
-
.find_all_package_files(name, pkg_config_path: self.pkg_config_path) ⇒ Object
Returns true if there is a package with this name.
-
.find_matching_version(candidates, version_spec) ⇒ Object
Returns the first package in
candidatesthat match the given version spec. -
.get(name, version_spec = nil, preset_variables = Hash.new, minimal: false, pkg_config_path: self.pkg_config_path, memo: Hash.new) ⇒ Object
Returns the pkg-config object that matches the given name, and optionally a version string.
-
.has_package?(name, pkg_config_path: self.pkg_config_path) ⇒ Boolean
Returns true if there is a package with this name.
- .load(path, preset_variables) ⇒ Object
- .load_minimal(path, preset_variables) ⇒ Object
-
.new(name, version_spec = nil, **options) ⇒ PkgConfig
Finds the provided package and optional version and returns its PkgConfig description.
- .parse_dependencies(string, allow_loops: false, memo: Hash.new) ⇒ Object
- .pkg_config_path ⇒ Object
Instance Method Summary collapse
-
#apply_sysrootdir(entries, flag_name) ⇒ Object
private
Apply #sysrootdir to all the given paths flags (-I or -L).
- #builtin_variables(path) ⇒ Object
- #cflags ⇒ Object
- #cflags_only_I ⇒ Object
- #cflags_only_other ⇒ Object
- #conflicts ⇒ Object
- #expand_field(name, field) ⇒ Object
- #expand_variables(raw_variables) ⇒ Object
-
#include_dirs ⇒ Object
Returns the list of include directories listed in the Cflags: section of the pkgconfig file.
-
#initialize(name) ⇒ PkgConfig
constructor
Create a PkgConfig object for the package
nameRaises PkgConfig::NotFound if the module does not exist. -
#library_dirs ⇒ Object
Returns the list of library directories listed in the Libs: section of the pkgconfig file.
- #libs(static = false) ⇒ Object
- #libs_only_L(static = false) ⇒ Object
- #libs_only_l(static = false) ⇒ Object
- #libs_only_other(static = false) ⇒ Object
-
#load(path, preset_variables = Hash.new) ⇒ Object
Loads the information contained in
path. - #load_fields(memo: Hash.new) ⇒ Object
- #load_minimal(path, preset_variables = Hash.new) ⇒ Object
- #load_variables(path, preset_variables = Hash.new) ⇒ Object
-
#method_missing(varname, *args, &proc) ⇒ Object
:nodoc:.
-
#normalize_field_name(name) ⇒ Object
private
Normalize a field name to be lowercase with only the first letter capitalized.
-
#parse(path) ⇒ (Hash,Hash)
Parse a pkg-config field and extracts the raw definition of variables and fields.
-
#perform_substitution(value, variables, current) ⇒ Object
Helper method that expands $word in
valueusing the name to value mapvariables. - #pkgconfig_variable(varname) ⇒ Object
- #raw_cflags ⇒ Object
- #raw_cflags_only_I ⇒ Object
- #raw_cflags_only_other ⇒ Object
- #raw_ldflags ⇒ Object
- #raw_ldflags_with_requires ⇒ Object
- #raw_libs(static = false) ⇒ Object
- #raw_libs_only_L(static = false) ⇒ Object
- #raw_libs_only_l(static = false) ⇒ Object
- #raw_libs_only_other(static = false) ⇒ Object
-
#sysrootdir ⇒ Object
A “new root” that should be prepended to -L and -I flags.
Constructor Details
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(varname, *args, &proc) ⇒ Object
:nodoc:
558 559 560 561 562 563 564 |
# File 'lib/utilrb/pkgconfig.rb', line 558 def method_missing(varname, *args, &proc) # :nodoc: if args.empty? variables[varname.to_s] else super(varname, *args, &proc) end end |
Instance Attribute Details
#description ⇒ Object (readonly)
Returns the value of attribute description.
153 154 155 |
# File 'lib/utilrb/pkgconfig.rb', line 153 def description @description end |
#fields ⇒ Object (readonly)
Returns the value of attribute fields.
165 166 167 |
# File 'lib/utilrb/pkgconfig.rb', line 165 def fields @fields end |
#name ⇒ Object (readonly)
The module name
152 153 154 |
# File 'lib/utilrb/pkgconfig.rb', line 152 def name @name end |
#path ⇒ Object (readonly)
Returns the value of attribute path.
149 150 151 |
# File 'lib/utilrb/pkgconfig.rb', line 149 def path @path end |
#raw_fields ⇒ Object (readonly)
Returns the value of attribute raw_fields.
161 162 163 |
# File 'lib/utilrb/pkgconfig.rb', line 161 def raw_fields @raw_fields end |
#raw_version ⇒ Object (readonly)
The module version as a string
156 157 158 |
# File 'lib/utilrb/pkgconfig.rb', line 156 def raw_version @raw_version end |
#requires ⇒ Array<PkgConfig> (readonly)
The list of packages that are Require:‘d by this package
170 171 172 |
# File 'lib/utilrb/pkgconfig.rb', line 170 def requires @requires end |
#variables ⇒ Object (readonly)
Information extracted from the file
164 165 166 |
# File 'lib/utilrb/pkgconfig.rb', line 164 def variables @variables end |
#version ⇒ Object (readonly)
The module version, as an array of integers
159 160 161 |
# File 'lib/utilrb/pkgconfig.rb', line 159 def version @version end |
Class Method Details
.arch_dir ⇒ Object
637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 |
# File 'lib/utilrb/pkgconfig.rb', line 637 def self.arch_dir return if @arch_dir == false unless @arch_dir suffix_with_arch = default_search_suffixes .find { |p| %r{^lib/[^/]+/pkgconfig} =~ p } @arch_dir = if suffix_with_arch suffix_with_arch.split("/")[1] else false end end @arch_dir end |
.available_package_names(pkg_config_path: self.pkg_config_path) ⇒ Object
589 590 591 592 593 594 595 596 597 |
# File 'lib/utilrb/pkgconfig.rb', line 589 def self.available_package_names(pkg_config_path: self.pkg_config_path) result = [] each_pkgconfig_directory(pkg_config_path: pkg_config_path) do |dir| Dir.glob(File.join(dir, "*.pc")) do |path| result << File.basename(path, ".pc") end end result end |
.clear_cache ⇒ Object
Utilrb::PkgConfig does not cache the packages anymore, so no need to call this method
60 61 |
# File 'lib/utilrb/pkgconfig.rb', line 60 def self.clear_cache end |
.default_search_path ⇒ Object
Returns the system-wide search path that is embedded in pkg-config
626 627 628 629 630 631 632 633 |
# File 'lib/utilrb/pkgconfig.rb', line 626 def self.default_search_path @default_search_path ||= `LANG=C pkg-config --variable pc_path pkg-config` .strip .split(":") .grep(PKGCONFIG_PATH_RX) .to_set end |
.default_search_path_I ⇒ Object
rubocop:disable Naming/MethodName
667 668 669 |
# File 'lib/utilrb/pkgconfig.rb', line 667 def self.default_search_path_I # rubocop:disable Naming/MethodName @default_search_path_I ||= ["-I/usr/include"] # rubocop:disable Naming/VariableName end |
.default_search_path_L ⇒ Object
rubocop:disable Naming/MethodName
656 657 658 659 660 661 662 663 664 665 |
# File 'lib/utilrb/pkgconfig.rb', line 656 def self.default_search_path_L # rubocop:disable Naming/MethodName unless @default_search_path_L arch_dir = self.arch_dir @default_search_path_L = # rubocop:disable Naming/VariableName ["-L/usr/lib", "-L/lib"] .flat_map { |p| [p, "#{p}/#{arch_dir}"] } end @default_search_path_L end |
.default_search_suffixes ⇒ Object
Returns the system-wide standard suffixes that should be appended to new prefixes to find pkg-config files
673 674 675 676 677 678 679 680 681 |
# File 'lib/utilrb/pkgconfig.rb', line 673 def self.default_search_suffixes @default_search_suffixes ||= `LANG=C pkg-config --variable pc_path pkg-config` .strip .split(":") .grep(PKGCONFIG_PATH_RX) .map { |l| l.gsub(PKGCONFIG_PATH_RX, '\1') } .to_set end |
.define_pkgconfig_action(action) ⇒ Object
:nodoc:
423 424 425 426 427 428 429 430 431 432 433 434 |
# File 'lib/utilrb/pkgconfig.rb', line 423 def self.define_pkgconfig_action(action) # :nodoc: class_eval <<-EOD, __FILE__, __LINE__+1 def pkgconfig_#{action.gsub(/-/, '_')}(static = false) if static `pkg-config --#{action} --static \#{name}`.strip else `pkg-config --#{action} \#{name}`.strip end end EOD nil end |
.each_package(regex = nil, pkg_config_path: self.pkg_config_path) ⇒ Object
Yields the package names of available packages. If regex is given, lists only the names that match the regular expression.
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 |
# File 'lib/utilrb/pkgconfig.rb', line 606 def self.each_package(regex = nil, pkg_config_path: self.pkg_config_path) return enum_for(__method__) if !block_given? seen = Set.new each_pkgconfig_directory(pkg_config_path: pkg_config_path) do |dir| Dir.glob(File.join(dir, '*.pc')) do |file| pkg_name = File.basename(file, ".pc") next if seen.include?(pkg_name) next if regex && pkg_name !~ regex seen << pkg_name yield(pkg_name) end end end |
.each_pkgconfig_directory(pkg_config_path: self.pkg_config_path, &block) ⇒ Object
570 571 572 573 574 575 |
# File 'lib/utilrb/pkgconfig.rb', line 570 def self.each_pkgconfig_directory(pkg_config_path: self.pkg_config_path, &block) return enum_for(__method__) if !block_given? pkg_config_path.split(':').each(&block) if pkg_config_path default_search_path.each(&block) end |
.find_all_package_files(name, pkg_config_path: self.pkg_config_path) ⇒ Object
Returns true if there is a package with this name
578 579 580 581 582 583 584 585 586 587 |
# File 'lib/utilrb/pkgconfig.rb', line 578 def self.find_all_package_files(name, pkg_config_path: self.pkg_config_path) result = [] each_pkgconfig_directory(pkg_config_path: pkg_config_path) do |dir| path = File.join(dir, "#{name}.pc") if File.exist?(path) result << path end end result end |
.find_matching_version(candidates, version_spec) ⇒ Object
Returns the first package in candidates that match the given version spec
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/utilrb/pkgconfig.rb', line 105 def self.find_matching_version(candidates, version_spec) if version_spec version_spec =~ /([<>=]+)\s*([\d\.]+)/ op, requested_version = $1, $2 requested_op = if op == "=" then [0] elsif op == ">" then [1] elsif op == "<" then [-1] elsif op == "<=" then [-1, 0] elsif op == ">=" then [1, 0] end requested_version = requested_version.split('.').map { |v| Integer(v) } result = candidates.find do |pkg| requested_op.include?(pkg.version <=> requested_version) end if !result name = candidates.first.name raise NotFound.new(name), "no version of #{name} match #{version_spec}. Available versions are: #{candidates.map(&:raw_version).join(", ")}" end result else candidates.first end end |
.get(name, version_spec = nil, preset_variables = Hash.new, minimal: false, pkg_config_path: self.pkg_config_path, memo: Hash.new) ⇒ Object
Returns the pkg-config object that matches the given name, and optionally a version string
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/utilrb/pkgconfig.rb', line 65 def self.get(name, version_spec = nil, preset_variables = Hash.new, minimal: false, pkg_config_path: self.pkg_config_path, memo: Hash.new) paths = find_all_package_files(name, pkg_config_path: pkg_config_path) if paths.empty? raise NotFound.new(name), "cannot find the pkg-config specification for #{name}" end candidates = paths.map do |p| PkgConfig.load_minimal(p, preset_variables) end # Now try to find a matching spec if match = find_matching_version(candidates, version_spec) memo[[name, version_spec]] = [false, match] else raise NotFound, "found #{candidates.size} packages for #{name},"\ " but none match the version specification #{version_spec}" end match.load_fields(memo: memo) unless minimal memo[[name, version_spec]] = [true, match] match end |
.has_package?(name, pkg_config_path: self.pkg_config_path) ⇒ Boolean
Returns true if there is a package with this name
600 601 602 |
# File 'lib/utilrb/pkgconfig.rb', line 600 def self.has_package?(name, pkg_config_path: self.pkg_config_path) !find_all_package_files(name, pkg_config_path: pkg_config_path).empty? end |
.load(path, preset_variables) ⇒ Object
44 45 46 47 48 49 |
# File 'lib/utilrb/pkgconfig.rb', line 44 def self.load(path, preset_variables) pkg_name = File.basename(path, ".pc") pkg = Class.instance_method(:new).bind(PkgConfig).call(pkg_name) pkg.load(path, preset_variables) pkg end |
.load_minimal(path, preset_variables) ⇒ Object
51 52 53 54 55 56 |
# File 'lib/utilrb/pkgconfig.rb', line 51 def self.load_minimal(path, preset_variables) pkg_name = File.basename(path, ".pc") pkg = Class.instance_method(:new).bind(PkgConfig).call(pkg_name) pkg.load_minimal(path, preset_variables) pkg end |
.new(name, version_spec = nil, **options) ⇒ PkgConfig
Finds the provided package and optional version and returns its PkgConfig description
number“, where op is < <= >= > or == and the version number X, X.y, …
99 100 101 |
# File 'lib/utilrb/pkgconfig.rb', line 99 def self.new(name, version_spec = nil, **) get(name, version_spec, **) end |
.parse_dependencies(string, allow_loops: false, memo: Hash.new) ⇒ Object
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/utilrb/pkgconfig.rb', line 201 def self.parse_dependencies(string, allow_loops: false, memo: Hash.new) string = string.gsub(',', ' ') packages = [] words = string.split(' ') while !words.empty? w = words.shift if w =~ /[<>=]/ version = words.shift if version =~ /[\d\.]+/ packages[-1][1] = "#{w} #{version}" else packages << [version, nil] end else packages << [w, nil] end end result = packages.map do |dep| finished, pkg = memo[dep] if pkg if allow_loops || finished pkg else raise DependencyLoop, "found a dependency loop" end else PkgConfig.get(*dep, memo: memo) end end result.compact end |
.pkg_config_path ⇒ Object
566 567 568 |
# File 'lib/utilrb/pkgconfig.rb', line 566 def self.pkg_config_path ENV['PKG_CONFIG_PATH'] end |
Instance Method Details
#apply_sysrootdir(entries, flag_name) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Apply #sysrootdir to all the given paths flags (-I or -L)
470 471 472 473 474 475 476 477 478 479 480 481 |
# File 'lib/utilrb/pkgconfig.rb', line 470 def apply_sysrootdir(entries, flag_name) sysrootdir = self.sysrootdir return entries if sysrootdir == "/" entries.map do |v| if v.start_with?(flag_name) "#{flag_name}#{sysrootdir}#{v[2..-1]}" else v end end end |
#builtin_variables(path) ⇒ Object
323 324 325 326 327 328 |
# File 'lib/utilrb/pkgconfig.rb', line 323 def builtin_variables(path) { "pcfiledir" => File.dirname(path), "pc_sysrootdir" => sysrootdir } end |
#cflags ⇒ Object
503 504 505 |
# File 'lib/utilrb/pkgconfig.rb', line 503 def cflags raw_cflags.join(" ") end |
#cflags_only_I ⇒ Object
507 508 509 |
# File 'lib/utilrb/pkgconfig.rb', line 507 def cflags_only_I raw_cflags_only_I.join(" ") end |
#cflags_only_other ⇒ Object
511 512 513 |
# File 'lib/utilrb/pkgconfig.rb', line 511 def cflags_only_other raw_cflags_only_other.join(" ") end |
#conflicts ⇒ Object
487 488 489 |
# File 'lib/utilrb/pkgconfig.rb', line 487 def conflicts @conflicts end |
#expand_field(name, field) ⇒ Object
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 |
# File 'lib/utilrb/pkgconfig.rb', line 302 def (name, field) if SHELL_VARS.include?(name) value = Shellwords.shellsplit(field) resolved = Array.new while !value.empty? value = value.flat_map do |v| = perform_substitution(v, variables, name) if == v resolved << v nil else Shellwords.shellsplit() end end.compact end resolved else perform_substitution(field, variables, name) end end |
#expand_variables(raw_variables) ⇒ Object
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 |
# File 'lib/utilrb/pkgconfig.rb', line 285 def (raw_variables) raw_variables = raw_variables.dup variables = Hash.new # Resolve the variables while variables.size != raw_variables.size raw_variables.each do |name, value| value = perform_substitution(value, raw_variables, name) raw_variables[name] = value if value !~ /\$\{#{VAR_NAME_RX}\}/ variables[name] = value end end end variables end |
#include_dirs ⇒ Object
Returns the list of include directories listed in the Cflags: section of the pkgconfig file
442 443 444 445 446 447 448 449 |
# File 'lib/utilrb/pkgconfig.rb', line 442 def include_dirs result = raw_cflags_only_I.map { |v| v[2..-1] } if result.any?(&:empty?) raise Invalid.new(name), "empty include directory (-I without argument) found in pkg-config package #{name}" end result end |
#library_dirs ⇒ Object
Returns the list of library directories listed in the Libs: section of the pkgconfig file
453 454 455 456 457 458 459 460 |
# File 'lib/utilrb/pkgconfig.rb', line 453 def library_dirs result = raw_libs_only_L.map { |v| v[2..-1] } if result.any?(&:empty?) raise Invalid.new(name), "empty link directory (-L without argument) found in pkg-config package #{name}" end result end |
#libs(static = false) ⇒ Object
542 543 544 |
# File 'lib/utilrb/pkgconfig.rb', line 542 def libs(static = false) raw_libs(static).join(" ") end |
#libs_only_L(static = false) ⇒ Object
546 547 548 |
# File 'lib/utilrb/pkgconfig.rb', line 546 def libs_only_L(static = false) raw_libs_only_L(static).join(" ") end |
#libs_only_l(static = false) ⇒ Object
550 551 552 |
# File 'lib/utilrb/pkgconfig.rb', line 550 def libs_only_l(static = false) raw_libs_only_l(static).join(" ") end |
#libs_only_other(static = false) ⇒ Object
554 555 556 |
# File 'lib/utilrb/pkgconfig.rb', line 554 def libs_only_other(static = false) raw_libs_only_other(static).join(" ") end |
#load(path, preset_variables = Hash.new) ⇒ Object
Loads the information contained in path
416 417 418 419 420 421 |
# File 'lib/utilrb/pkgconfig.rb', line 416 def load(path, preset_variables = Hash.new) if !@raw_fields load_minimal(path, preset_variables) end load_fields end |
#load_fields(memo: Hash.new) ⇒ Object
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 |
# File 'lib/utilrb/pkgconfig.rb', line 357 def load_fields(memo: Hash.new) fields = Hash.new @raw_fields.each do |name, value| fields[name] = (name, value) end @fields = fields # Initialize the main flags @description = (fields['Description'] || '') # Get the requires/conflicts @requires = PkgConfig.parse_dependencies( fields['Requires'] || '', allow_loops: false, memo: memo) @requires_private = PkgConfig.parse_dependencies( fields['Requires.private'] || '', allow_loops: false, memo: memo) @conflicts = PkgConfig.parse_dependencies( fields['Conflicts'] || '', allow_loops: true, memo: memo) # And finally resolve the compilation flags cflags = fields['Cflags'] || [] cflags.uniq! cflags -= self.class.default_search_path_I cflags = apply_sysrootdir(cflags, "-I") @requires.each do |pkg| cflags.concat(pkg.raw_cflags) end @requires_private.each do |pkg| cflags.concat(pkg.raw_cflags) end @cflags = cflags ldflags_public = fields['Libs'] || [] ldflags_public.uniq! ldflags_private = ldflags_public + (fields['Libs.private'] || []) ldflags_private.uniq! ldflags_public -= self.class.default_search_path_L ldflags_public = apply_sysrootdir(ldflags_public, "-L") ldflags_private -= self.class.default_search_path_L ldflags_private = apply_sysrootdir(ldflags_private, "-L") @ldflags = { false => ldflags_public, true => ldflags_private } @ldflags_with_requires = { true => @ldflags[true].dup, false => @ldflags[false].dup } @requires.each do |pkg| @ldflags_with_requires[true].concat(pkg.raw_ldflags_with_requires[true]) @ldflags_with_requires[false].concat(pkg.raw_ldflags_with_requires[false]) end @requires_private.each do |pkg| @ldflags_with_requires[true].concat(pkg.raw_ldflags_with_requires[true]) end end |
#load_minimal(path, preset_variables = Hash.new) ⇒ Object
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 |
# File 'lib/utilrb/pkgconfig.rb', line 338 def load_minimal(path, preset_variables = Hash.new) raw_variables, raw_fields = parse(path) raw_variables = preset_variables.merge(raw_variables) @variables = ( raw_variables.merge(builtin_variables(path)) ) if raw_fields['Version'] @raw_version = ('Version', raw_fields['Version']) else @raw_version = '' end @version = raw_version.split('.').map { |v| Integer(v) if v =~ /^\d+$/ }.compact # To be used in the call to #load @raw_fields = raw_fields @path = path end |
#load_variables(path, preset_variables = Hash.new) ⇒ Object
330 331 332 333 334 335 336 |
# File 'lib/utilrb/pkgconfig.rb', line 330 def load_variables(path, preset_variables = Hash.new) raw_variables, raw_fields = parse(path) raw_variables = preset_variables.merge(raw_variables) ( raw_variables.merge(builtin_variables(path)) ) end |
#normalize_field_name(name) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Normalize a field name to be lowercase with only the first letter capitalized
239 240 241 242 243 |
# File 'lib/utilrb/pkgconfig.rb', line 239 def normalize_field_name(name) name = name.downcase name[0, 1] = name[0, 1].upcase name end |
#parse(path) ⇒ (Hash,Hash)
Parse a pkg-config field and extracts the raw definition of variables and fields
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
# File 'lib/utilrb/pkgconfig.rb', line 249 def parse(path) running_line = nil file = File.readlines(path).map do |line| line = line.gsub(/\s*#.*$/, '') line = line.strip next if line.empty? value = line.gsub(/\\$/, '') if running_line running_line << " " << value end if line =~ /\\$/ running_line ||= value elsif running_line running_line = nil else value end end.compact raw_variables, raw_fields = Hash.new, Hash.new file.each do |line| case line when /^(#{VAR_NAME_RX})\s*=(.*)/ raw_variables[$1] = $2.strip when /^(#{FIELD_NAME_RX}):\s*(.*)/ field_name = normalize_field_name($1) raw_fields[field_name] = $2.strip else raise NotImplementedError, "#{path}: cannot parse pkg-config line #{line.inspect}" end end return raw_variables, raw_fields end |
#perform_substitution(value, variables, current) ⇒ Object
Helper method that expands $word in value using the name to value map variables
current is a string that describes what we are expanding. It is used to detect recursion in expansion of variables, and to give meaningful errors to the user
186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/utilrb/pkgconfig.rb', line 186 def perform_substitution(value, variables, current) value = value.gsub(/\$\{(\w+)\}/) do |rx| = $1 if == current raise "error in pkg-config file #{path}: #{current} contains a reference to itself" elsif !( = variables[]) raise "error in pkg-config file #{path}: #{current} contains a reference to #{} but there is no such variable" end end value end |
#pkgconfig_variable(varname) ⇒ Object
436 437 438 |
# File 'lib/utilrb/pkgconfig.rb', line 436 def pkgconfig_variable(varname) `pkg-config --variable=#{varname}`.strip end |
#raw_cflags ⇒ Object
491 492 493 |
# File 'lib/utilrb/pkgconfig.rb', line 491 def raw_cflags @cflags end |
#raw_cflags_only_I ⇒ Object
495 496 497 |
# File 'lib/utilrb/pkgconfig.rb', line 495 def raw_cflags_only_I @cflags.grep(/^-I/) end |
#raw_cflags_only_other ⇒ Object
499 500 501 |
# File 'lib/utilrb/pkgconfig.rb', line 499 def raw_cflags_only_other @cflags.find_all { |s| s !~ /^-I/ } end |
#raw_ldflags ⇒ Object
516 517 518 |
# File 'lib/utilrb/pkgconfig.rb', line 516 def raw_ldflags @ldflags end |
#raw_ldflags_with_requires ⇒ Object
520 521 522 |
# File 'lib/utilrb/pkgconfig.rb', line 520 def raw_ldflags_with_requires @ldflags_with_requires end |
#raw_libs(static = false) ⇒ Object
525 526 527 |
# File 'lib/utilrb/pkgconfig.rb', line 525 def raw_libs(static = false) @ldflags_with_requires[static] end |
#raw_libs_only_L(static = false) ⇒ Object
529 530 531 |
# File 'lib/utilrb/pkgconfig.rb', line 529 def raw_libs_only_L(static = false) @ldflags_with_requires[static].grep(/^-L/) end |
#raw_libs_only_l(static = false) ⇒ Object
533 534 535 |
# File 'lib/utilrb/pkgconfig.rb', line 533 def raw_libs_only_l(static = false) @ldflags_with_requires[static].grep(/^-l/) end |
#raw_libs_only_other(static = false) ⇒ Object
537 538 539 |
# File 'lib/utilrb/pkgconfig.rb', line 537 def raw_libs_only_other(static = false) @ldflags_with_requires[static].find_all { |s| s !~ /^-[lL]/ } end |
#sysrootdir ⇒ Object
A “new root” that should be prepended to -L and -I flags
463 464 465 |
# File 'lib/utilrb/pkgconfig.rb', line 463 def sysrootdir ENV["PKG_CONFIG_SYSROOT_DIR"] || "/" end |