pkg-config 1.4.0 → 1.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +12 -2
- data/NEWS.md +565 -0
- data/README.rdoc +2 -10
- data/Rakefile +7 -3
- data/lib/pkg-config.rb +377 -254
- data/test/{run-test.rb → run.rb} +0 -3
- data/test/test-pkg-config.rb +347 -0
- metadata +11 -58
- data/NEWS +0 -322
- data/lib/pkg-config/version.rb +0 -19
- data/test/test_pkg_config.rb +0 -217
data/lib/pkg-config.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2008-
|
|
1
|
+
# Copyright (C) 2008-2025 Sutou Kouhei <kou@cozmixng.org>
|
|
2
2
|
#
|
|
3
3
|
# This library is free software; you can redistribute it and/or
|
|
4
4
|
# modify it under the terms of the GNU Lesser General Public
|
|
@@ -14,18 +14,134 @@
|
|
|
14
14
|
# License along with this library; if not, write to the Free Software
|
|
15
15
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
require "pkg-config/version"
|
|
19
|
-
rescue LoadError
|
|
20
|
-
end
|
|
21
|
-
|
|
17
|
+
require "pathname"
|
|
22
18
|
require "rbconfig"
|
|
19
|
+
require "shellwords"
|
|
20
|
+
|
|
21
|
+
module PKGConfig
|
|
22
|
+
VERSION = "1.6.5"
|
|
23
|
+
|
|
24
|
+
@@paths = []
|
|
25
|
+
@@override_variables = {}
|
|
26
|
+
|
|
27
|
+
module_function
|
|
28
|
+
def add_path(path)
|
|
29
|
+
@@paths << path
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def set_override_variable(key, value)
|
|
33
|
+
@@override_variables[key] = value
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def msvc?
|
|
37
|
+
/mswin/.match(RUBY_PLATFORM) and /^cl\b/.match(RbConfig::CONFIG["CC"])
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def package_config(package)
|
|
41
|
+
PackageConfig.new(package,
|
|
42
|
+
:msvc_syntax => msvc?,
|
|
43
|
+
:override_variables => @@override_variables,
|
|
44
|
+
:paths => @@paths)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def exist?(pkg)
|
|
48
|
+
package_config(pkg).exist?
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def libs(pkg)
|
|
52
|
+
package_config(pkg).libs
|
|
53
|
+
end
|
|
23
54
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
55
|
+
def libs_only_l(pkg)
|
|
56
|
+
package_config(pkg).libs_only_l
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def libs_only_L(pkg)
|
|
60
|
+
package_config(pkg).libs_only_L
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def cflags(pkg)
|
|
64
|
+
package_config(pkg).cflags
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def cflags_only_I(pkg)
|
|
68
|
+
package_config(pkg).cflags_only_I
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def cflags_only_other(pkg)
|
|
72
|
+
package_config(pkg).cflags_only_other
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def modversion(pkg)
|
|
76
|
+
package_config(pkg).version
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def description(pkg)
|
|
80
|
+
package_config(pkg).description
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def variable(pkg, name)
|
|
84
|
+
package_config(pkg).variable(name)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def check_version?(pkg, major=0, minor=0, micro=0)
|
|
88
|
+
return false unless exist?(pkg)
|
|
89
|
+
ver = modversion(pkg).split(".").collect {|item| item.to_i}
|
|
90
|
+
(0..2).each {|i| ver[i] = 0 unless ver[i]}
|
|
91
|
+
|
|
92
|
+
(ver[0] > major ||
|
|
93
|
+
(ver[0] == major && ver[1] > minor) ||
|
|
94
|
+
(ver[0] == major && ver[1] == minor &&
|
|
95
|
+
ver[2] >= micro))
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def have_package(pkg, major=nil, minor=0, micro=0)
|
|
99
|
+
message = "#{pkg}"
|
|
100
|
+
unless major.nil?
|
|
101
|
+
message << " version (>= #{major}.#{minor}.#{micro})"
|
|
102
|
+
end
|
|
103
|
+
major ||= 0
|
|
104
|
+
result = checking_for(checking_message(message), "%s") do
|
|
105
|
+
if check_version?(pkg, major, minor, micro)
|
|
106
|
+
"yes (#{modversion(pkg)})"
|
|
107
|
+
else
|
|
108
|
+
if exist?(pkg)
|
|
109
|
+
"no (#{modversion(pkg)})"
|
|
110
|
+
else
|
|
111
|
+
"no (nonexistent)"
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
enough_version = result.start_with?("yes")
|
|
116
|
+
if enough_version
|
|
117
|
+
libraries = libs_only_l(pkg)
|
|
118
|
+
dldflags = libs(pkg)
|
|
119
|
+
dldflags = (Shellwords.shellwords(dldflags) -
|
|
120
|
+
Shellwords.shellwords(libraries))
|
|
121
|
+
dldflags = dldflags.map {|s| /\s/ =~ s ? "\"#{s}\"" : s }.join(" ")
|
|
122
|
+
$libs += " " + libraries
|
|
123
|
+
if /mswin/ =~ RUBY_PLATFORM
|
|
124
|
+
$DLDFLAGS += " " + dldflags
|
|
125
|
+
else
|
|
126
|
+
$LDFLAGS += " " + dldflags
|
|
127
|
+
end
|
|
128
|
+
$CFLAGS += " " + cflags_only_other(pkg)
|
|
129
|
+
if defined?($CXXFLAGS)
|
|
130
|
+
$CXXFLAGS += " " + cflags_only_other(pkg)
|
|
131
|
+
end
|
|
132
|
+
$INCFLAGS += " " + cflags_only_I(pkg)
|
|
133
|
+
end
|
|
134
|
+
enough_version
|
|
135
|
+
end
|
|
136
|
+
end
|
|
27
137
|
|
|
28
138
|
class PackageConfig
|
|
139
|
+
class Error < StandardError
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
class NotFoundError < Error
|
|
143
|
+
end
|
|
144
|
+
|
|
29
145
|
SEPARATOR = File::PATH_SEPARATOR
|
|
30
146
|
|
|
31
147
|
class << self
|
|
@@ -39,6 +155,11 @@ class PackageConfig
|
|
|
39
155
|
@native_pkg_config_prefix ||= compute_native_pkg_config_prefix
|
|
40
156
|
end
|
|
41
157
|
|
|
158
|
+
@default_path = nil
|
|
159
|
+
def default_path
|
|
160
|
+
@default_path ||= compute_default_path
|
|
161
|
+
end
|
|
162
|
+
|
|
42
163
|
@custom_override_variables = nil
|
|
43
164
|
def custom_override_variables
|
|
44
165
|
@custom_override_variables ||= with_config("override-variables", "")
|
|
@@ -47,6 +168,7 @@ class PackageConfig
|
|
|
47
168
|
def clear_configure_args_cache
|
|
48
169
|
@native_pkg_config = nil
|
|
49
170
|
@native_pkg_config_prefix = nil
|
|
171
|
+
@default_path = nil
|
|
50
172
|
@custom_override_variables = nil
|
|
51
173
|
end
|
|
52
174
|
|
|
@@ -61,18 +183,25 @@ class PackageConfig
|
|
|
61
183
|
|
|
62
184
|
def guess_native_pkg_config
|
|
63
185
|
exeext = RbConfig::CONFIG["EXEEXT"]
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
pkg_config
|
|
186
|
+
candidates = [
|
|
187
|
+
with_config("pkg-config"),
|
|
188
|
+
ENV["PKG_CONFIG"],
|
|
189
|
+
"pkgconf#{exeext}",
|
|
190
|
+
"pkg-config#{exeext}",
|
|
191
|
+
].compact
|
|
192
|
+
candidates.each do |pkg_config|
|
|
193
|
+
pkg_config = Pathname.new(pkg_config)
|
|
194
|
+
return pkg_config if pkg_config.absolute? and pkg_config.exist?
|
|
195
|
+
unless pkg_config.absolute?
|
|
196
|
+
found_pkg_config = search_executable_from_path(pkg_config)
|
|
197
|
+
return found_pkg_config if found_pkg_config
|
|
198
|
+
end
|
|
199
|
+
unless pkg_config.absolute?
|
|
200
|
+
found_pkg_config = search_pkg_config_by_dln_find_exe(pkg_config)
|
|
201
|
+
return found_pkg_config if found_pkg_config
|
|
202
|
+
end
|
|
74
203
|
end
|
|
75
|
-
|
|
204
|
+
Pathname.new(candidates[0])
|
|
76
205
|
end
|
|
77
206
|
|
|
78
207
|
def search_executable_from_path(name)
|
|
@@ -133,6 +262,129 @@ class PackageConfig
|
|
|
133
262
|
pkg_config_prefix
|
|
134
263
|
end
|
|
135
264
|
end
|
|
265
|
+
|
|
266
|
+
def compute_default_path
|
|
267
|
+
default_paths = nil
|
|
268
|
+
if native_pkg_config
|
|
269
|
+
pc_path = run_command(native_pkg_config.to_s,
|
|
270
|
+
"--variable=pc_path",
|
|
271
|
+
"pkg-config")
|
|
272
|
+
if pc_path
|
|
273
|
+
default_paths = pc_path.strip.split(SEPARATOR)
|
|
274
|
+
default_paths = nil if default_paths.empty?
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
if default_paths.nil?
|
|
278
|
+
arch_depended_path = Dir.glob("/usr/lib/*/pkgconfig")
|
|
279
|
+
default_paths = []
|
|
280
|
+
pkg_config_prefix = native_pkg_config_prefix
|
|
281
|
+
if pkg_config_prefix
|
|
282
|
+
pkg_config_arch_depended_paths =
|
|
283
|
+
Dir.glob((pkg_config_prefix + "lib/*/pkgconfig").to_s)
|
|
284
|
+
default_paths.concat(pkg_config_arch_depended_paths)
|
|
285
|
+
default_paths << (pkg_config_prefix + "lib64/pkgconfig").to_s
|
|
286
|
+
default_paths << (pkg_config_prefix + "libx32/pkgconfig").to_s
|
|
287
|
+
default_paths << (pkg_config_prefix + "lib/pkgconfig").to_s
|
|
288
|
+
default_paths << (pkg_config_prefix + "libdata/pkgconfig").to_s
|
|
289
|
+
default_paths << (pkg_config_prefix + "share/pkgconfig").to_s
|
|
290
|
+
end
|
|
291
|
+
conda_prefix = ENV["CONDA_PREFIX"]
|
|
292
|
+
if conda_prefix
|
|
293
|
+
default_paths << File.join(conda_prefix, "lib", "pkgconfig")
|
|
294
|
+
default_paths << File.join(conda_prefix, "share", "pkgconfig")
|
|
295
|
+
end
|
|
296
|
+
default_paths << "/usr/local/lib64/pkgconfig"
|
|
297
|
+
default_paths << "/usr/local/libx32/pkgconfig"
|
|
298
|
+
default_paths << "/usr/local/lib/pkgconfig"
|
|
299
|
+
default_paths << "/usr/local/libdata/pkgconfig"
|
|
300
|
+
default_paths << "/usr/local/share/pkgconfig"
|
|
301
|
+
default_paths << "/opt/local/lib/pkgconfig"
|
|
302
|
+
default_paths.concat(arch_depended_path)
|
|
303
|
+
default_paths << "/usr/lib64/pkgconfig"
|
|
304
|
+
default_paths << "/usr/libx32/pkgconfig"
|
|
305
|
+
default_paths << "/usr/lib/pkgconfig"
|
|
306
|
+
default_paths << "/usr/libdata/pkgconfig"
|
|
307
|
+
default_paths << "/usr/X11R6/lib/pkgconfig"
|
|
308
|
+
default_paths << "/usr/X11R6/share/pkgconfig"
|
|
309
|
+
default_paths << "/usr/X11/lib/pkgconfig"
|
|
310
|
+
default_paths << "/opt/X11/lib/pkgconfig"
|
|
311
|
+
default_paths << "/usr/share/pkgconfig"
|
|
312
|
+
end
|
|
313
|
+
if Object.const_defined?(:RubyInstaller)
|
|
314
|
+
mingw_bin_path = RubyInstaller::Runtime.msys2_installation.mingw_bin_path
|
|
315
|
+
mingw_pkgconfig_path = Pathname.new(mingw_bin_path) + "../lib/pkgconfig"
|
|
316
|
+
default_paths.unshift(mingw_pkgconfig_path.cleanpath.to_s)
|
|
317
|
+
end
|
|
318
|
+
libdir = ENV["PKG_CONFIG_LIBDIR"]
|
|
319
|
+
default_paths.unshift(libdir) if libdir
|
|
320
|
+
|
|
321
|
+
paths = []
|
|
322
|
+
if /-darwin\d[\d\.]*\z/ =~ RUBY_PLATFORM and
|
|
323
|
+
/\A(\d+\.\d+)/ =~ run_command("sw_vers", "-productVersion")
|
|
324
|
+
mac_os_version = $1
|
|
325
|
+
homebrew_repository_candidates = []
|
|
326
|
+
if pkg_config_prefix
|
|
327
|
+
brew_path = pkg_config_prefix + "bin" + "brew"
|
|
328
|
+
if brew_path.exist?
|
|
329
|
+
homebrew_repository = run_command(brew_path.to_s, "--repository")
|
|
330
|
+
if homebrew_repository
|
|
331
|
+
homebrew_repository_candidates <<
|
|
332
|
+
Pathname.new(homebrew_repository.strip)
|
|
333
|
+
end
|
|
334
|
+
else
|
|
335
|
+
homebrew_repository_candidates << pkg_config_prefix + "Homebrew"
|
|
336
|
+
homebrew_repository_candidates << pkg_config_prefix
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
brew = search_executable_from_path("brew")
|
|
340
|
+
if brew
|
|
341
|
+
homebrew_repository = run_command("brew", "--repository")
|
|
342
|
+
if homebrew_repository
|
|
343
|
+
homebrew_repository_candidates <<
|
|
344
|
+
Pathname(homebrew_repository.strip)
|
|
345
|
+
end
|
|
346
|
+
homebrew_prefix = run_command("brew", "--prefix")
|
|
347
|
+
if homebrew_prefix
|
|
348
|
+
homebrew_repository_candidates <<
|
|
349
|
+
Pathname(homebrew_prefix.strip)
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
homebrew_repository_candidates.uniq.each do |candidate|
|
|
353
|
+
mac_pkgconfig_base_path =
|
|
354
|
+
candidate + "Library/Homebrew/os/mac/pkgconfig"
|
|
355
|
+
mac_pkgconfig_path = mac_pkgconfig_base_path + mac_os_version
|
|
356
|
+
unless mac_pkgconfig_path.exist?
|
|
357
|
+
mac_pkgconfig_path =
|
|
358
|
+
mac_pkgconfig_base_path + mac_os_version.gsub(/\.\d+\z/, "")
|
|
359
|
+
end
|
|
360
|
+
paths << mac_pkgconfig_path.to_s if mac_pkgconfig_path.exist?
|
|
361
|
+
|
|
362
|
+
pkgconfig_path = candidate + "lib/pkgconfig"
|
|
363
|
+
paths << pkgconfig_path.to_s if pkgconfig_path.exist?
|
|
364
|
+
end
|
|
365
|
+
end
|
|
366
|
+
paths.concat(default_paths)
|
|
367
|
+
[
|
|
368
|
+
with_config("pkg-config-path") || ENV["PKG_CONFIG_PATH"],
|
|
369
|
+
*paths,
|
|
370
|
+
].compact.join(SEPARATOR)
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
def run_command(*command_line)
|
|
374
|
+
IO.pipe do |input, output|
|
|
375
|
+
begin
|
|
376
|
+
pid = spawn(*command_line,
|
|
377
|
+
out: output,
|
|
378
|
+
err: File::NULL)
|
|
379
|
+
output.close
|
|
380
|
+
_, status = Process.waitpid2(pid)
|
|
381
|
+
return nil unless status.success?
|
|
382
|
+
input.read
|
|
383
|
+
rescue SystemCallError
|
|
384
|
+
nil
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
end
|
|
136
388
|
end
|
|
137
389
|
|
|
138
390
|
attr_reader :name
|
|
@@ -149,8 +401,10 @@ class PackageConfig
|
|
|
149
401
|
@name = name
|
|
150
402
|
end
|
|
151
403
|
@options = options
|
|
152
|
-
|
|
153
|
-
|
|
404
|
+
@paths = [
|
|
405
|
+
@options[:path],
|
|
406
|
+
self.class.default_path,
|
|
407
|
+
].compact.join(SEPARATOR).split(SEPARATOR)
|
|
154
408
|
@paths.unshift(*(@options[:paths] || []))
|
|
155
409
|
@paths = normalize_paths(@paths)
|
|
156
410
|
@msvc_syntax = @options[:msvc_syntax]
|
|
@@ -161,6 +415,14 @@ class PackageConfig
|
|
|
161
415
|
@override_variables = default_override_variables.merge(@override_variables)
|
|
162
416
|
end
|
|
163
417
|
|
|
418
|
+
def eql?(other)
|
|
419
|
+
other.is_a?(self.class) and @name == other.name
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
def hash
|
|
423
|
+
@name.hash
|
|
424
|
+
end
|
|
425
|
+
|
|
164
426
|
def exist?
|
|
165
427
|
not pc_path.nil?
|
|
166
428
|
end
|
|
@@ -175,7 +437,7 @@ class PackageConfig
|
|
|
175
437
|
|
|
176
438
|
def cflags
|
|
177
439
|
path_flags, other_flags = collect_cflags
|
|
178
|
-
(
|
|
440
|
+
(path_flags + other_flags).join(" ")
|
|
179
441
|
end
|
|
180
442
|
|
|
181
443
|
def cflags_only_I
|
|
@@ -187,26 +449,25 @@ class PackageConfig
|
|
|
187
449
|
end
|
|
188
450
|
|
|
189
451
|
def libs
|
|
190
|
-
|
|
191
|
-
(path_flags + other_flags).join(" ")
|
|
452
|
+
collect_libs.join(" ")
|
|
192
453
|
end
|
|
193
454
|
|
|
194
455
|
def libs_only_l
|
|
195
|
-
collect_libs
|
|
456
|
+
collect_libs.find_all do |arg|
|
|
196
457
|
if @msvc_syntax
|
|
197
|
-
|
|
458
|
+
arg.end_with?(".lib")
|
|
198
459
|
else
|
|
199
|
-
|
|
460
|
+
arg.start_with?("-l")
|
|
200
461
|
end
|
|
201
462
|
end.join(" ")
|
|
202
463
|
end
|
|
203
464
|
|
|
204
465
|
def libs_only_L
|
|
205
|
-
collect_libs
|
|
466
|
+
collect_libs.find_all do |arg|
|
|
206
467
|
if @msvc_syntax
|
|
207
|
-
|
|
468
|
+
arg.start_with?("/libpath:")
|
|
208
469
|
else
|
|
209
|
-
|
|
470
|
+
arg.start_with?("-L")
|
|
210
471
|
end
|
|
211
472
|
end.join(" ")
|
|
212
473
|
end
|
|
@@ -250,37 +511,31 @@ class PackageConfig
|
|
|
250
511
|
end
|
|
251
512
|
|
|
252
513
|
def collect_requires(&block)
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
package =
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
package.name
|
|
514
|
+
dependencies = {}
|
|
515
|
+
pending_packages = yield(self).collect {|name| self.class.new(name, @options)}
|
|
516
|
+
until pending_packages.empty?
|
|
517
|
+
package = pending_packages.shift
|
|
518
|
+
next if dependencies.key?(package)
|
|
519
|
+
dependencies[package] = true
|
|
520
|
+
targets = yield(package)
|
|
521
|
+
targets.each do |name|
|
|
522
|
+
require_package = self.class.new(name, @options)
|
|
523
|
+
pending_packages.push(require_package)
|
|
524
|
+
end
|
|
265
525
|
end
|
|
526
|
+
dependencies.keys
|
|
266
527
|
end
|
|
267
528
|
|
|
268
529
|
private
|
|
269
|
-
def sort_packages(packages)
|
|
270
|
-
packages.sort_by.with_index do |package, i|
|
|
271
|
-
[package.path_position, i]
|
|
272
|
-
end
|
|
273
|
-
end
|
|
274
|
-
|
|
275
530
|
def collect_cflags
|
|
276
|
-
target_packages =
|
|
531
|
+
target_packages = [self, *all_required_packages]
|
|
277
532
|
cflags_set = []
|
|
278
533
|
target_packages.each do |package|
|
|
279
534
|
cflags_set << package.declaration("Cflags")
|
|
280
535
|
end
|
|
281
536
|
all_cflags = normalize_cflags(Shellwords.split(cflags_set.join(" ")))
|
|
282
537
|
path_flags, other_flags = all_cflags.partition {|flag| /\A-I/ =~ flag}
|
|
283
|
-
path_flags =
|
|
538
|
+
path_flags = path_flags.collect {|flag| normalize_path_flag(flag, "-I")}
|
|
284
539
|
path_flags = path_flags.reject do |flag|
|
|
285
540
|
flag == "-I/usr/include"
|
|
286
541
|
end
|
|
@@ -290,23 +545,22 @@ class PackageConfig
|
|
|
290
545
|
flag.gsub(/\A-I/, "/I")
|
|
291
546
|
end
|
|
292
547
|
end
|
|
548
|
+
other_flags = merge_back_cflags(other_flags)
|
|
293
549
|
[path_flags, other_flags]
|
|
294
550
|
end
|
|
295
551
|
|
|
296
|
-
def
|
|
297
|
-
return
|
|
552
|
+
def normalize_path_flag(path_flag, flag_option)
|
|
553
|
+
return path_flag unless /-mingw(?:32|-ucrt)\z/ === RUBY_PLATFORM
|
|
298
554
|
|
|
299
555
|
pkg_config_prefix = self.class.native_pkg_config_prefix
|
|
300
|
-
return
|
|
556
|
+
return path_flag unless pkg_config_prefix
|
|
301
557
|
|
|
302
558
|
mingw_dir = pkg_config_prefix.basename.to_s
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
pkg_config_prefix.to_s
|
|
307
|
-
end
|
|
308
|
-
"#{flag_option}#{path}"
|
|
559
|
+
path = path_flag.sub(/\A#{Regexp.escape(flag_option)}/, "")
|
|
560
|
+
path = path.sub(/\A\/#{Regexp.escape(mingw_dir)}/i) do
|
|
561
|
+
pkg_config_prefix.to_s
|
|
309
562
|
end
|
|
563
|
+
"#{flag_option}#{path}"
|
|
310
564
|
end
|
|
311
565
|
|
|
312
566
|
def normalize_cflags(cflags)
|
|
@@ -315,10 +569,10 @@ class PackageConfig
|
|
|
315
569
|
begin
|
|
316
570
|
loop do
|
|
317
571
|
cflag = enumerator.next
|
|
318
|
-
normalized_cflags << cflag
|
|
572
|
+
normalized_cflags << cflag.dup
|
|
319
573
|
case cflag
|
|
320
574
|
when "-I"
|
|
321
|
-
normalized_cflags << enumerator.next
|
|
575
|
+
normalized_cflags.last << enumerator.next
|
|
322
576
|
end
|
|
323
577
|
end
|
|
324
578
|
rescue StopIteration
|
|
@@ -326,39 +580,66 @@ class PackageConfig
|
|
|
326
580
|
normalized_cflags
|
|
327
581
|
end
|
|
328
582
|
|
|
583
|
+
# Implementing behavior compatible with pkgconf's pkgconf_fragment_copy().
|
|
584
|
+
# This is not a complete reproduction yet, but the goal is to stay compatible.
|
|
585
|
+
# https://github.com/pkgconf/pkgconf/blob/pkgconf-2.5.1/libpkgconf/fragment.c#L381-L416
|
|
586
|
+
def merge_back_cflags(cflags)
|
|
587
|
+
merge_backed_cflags = []
|
|
588
|
+
cflags.each do |cflag|
|
|
589
|
+
if mergeable_flag?(cflag)
|
|
590
|
+
# NOTE: This may be slow because this checks merge_back_cflags N times
|
|
591
|
+
# (where N is the number of mergeable flags).
|
|
592
|
+
merge_backed_cflags.delete(cflag)
|
|
593
|
+
end
|
|
594
|
+
merge_backed_cflags << cflag
|
|
595
|
+
end
|
|
596
|
+
merge_backed_cflags
|
|
597
|
+
end
|
|
598
|
+
|
|
599
|
+
def mergeable_flag?(flag)
|
|
600
|
+
return false unless flag.start_with?("-")
|
|
601
|
+
return true if flag.start_with?("-D")
|
|
602
|
+
if flag.start_with?("-W")
|
|
603
|
+
return false if flag.start_with?("-Wa,", "-Wl,", "-Wp,")
|
|
604
|
+
return true
|
|
605
|
+
end
|
|
606
|
+
false
|
|
607
|
+
end
|
|
608
|
+
|
|
329
609
|
def collect_libs
|
|
330
|
-
target_packages =
|
|
610
|
+
target_packages = [*required_packages, self]
|
|
331
611
|
libs_set = []
|
|
332
612
|
target_packages.each do |package|
|
|
333
613
|
libs_set << package.declaration("Libs")
|
|
334
614
|
end
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
615
|
+
flags = split_lib_flags(libs_set.join(" "))
|
|
616
|
+
flags = flags.collect do |flag|
|
|
617
|
+
flag = normalize_path_flag(flag, "-L") if flag.start_with?("-L")
|
|
618
|
+
flag
|
|
619
|
+
end
|
|
620
|
+
flags = flags.reject do |flag|
|
|
339
621
|
/\A-L\/usr\/lib(?:64|x32)?\z/ =~ flag
|
|
340
622
|
end
|
|
341
|
-
|
|
623
|
+
flags = flags.uniq
|
|
342
624
|
if @msvc_syntax
|
|
343
|
-
|
|
344
|
-
flag.
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
"#{$POSTMATCH}.lib"
|
|
625
|
+
flags = flags.collect do |flag|
|
|
626
|
+
if flag.start_with?("-L")
|
|
627
|
+
flag.gsub(/\A-L/, "/libpath:")
|
|
628
|
+
elsif flag.start_with?("-l")
|
|
629
|
+
"#{flag[2..-1]}.lib"
|
|
349
630
|
else
|
|
350
631
|
flag
|
|
351
632
|
end
|
|
352
633
|
end
|
|
353
634
|
end
|
|
354
|
-
|
|
635
|
+
flags
|
|
355
636
|
end
|
|
356
637
|
|
|
357
638
|
def split_lib_flags(libs_command_line)
|
|
358
639
|
all_flags = {}
|
|
359
640
|
flags = []
|
|
360
641
|
in_option = false
|
|
361
|
-
libs_command_line.gsub(/-([Ll]) /,
|
|
642
|
+
libs_command_line.gsub(/-([Ll]) /, "\\1").split.each do |arg|
|
|
362
643
|
if in_option
|
|
363
644
|
flags << arg
|
|
364
645
|
in_option = false
|
|
@@ -379,26 +660,37 @@ class PackageConfig
|
|
|
379
660
|
|
|
380
661
|
IDENTIFIER_RE = /[a-zA-Z\d_\.]+/
|
|
381
662
|
def parse_pc
|
|
382
|
-
raise ".pc
|
|
663
|
+
raise NotFoundError, ".pc doesn't exist: <#{@name}>" unless exist?
|
|
383
664
|
@variables = {}
|
|
384
665
|
@declarations = {}
|
|
385
666
|
File.open(pc_path) do |input|
|
|
667
|
+
current_line = +""
|
|
386
668
|
input.each_line do |line|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
669
|
+
if line.dup.force_encoding("UTF-8").valid_encoding?
|
|
670
|
+
line.force_encoding("UTF-8")
|
|
671
|
+
end
|
|
672
|
+
line = line.gsub(/#.*/, "").strip
|
|
673
|
+
if line.end_with?("\\")
|
|
674
|
+
current_line += line[0..-2]
|
|
675
|
+
next
|
|
394
676
|
end
|
|
677
|
+
current_line += line
|
|
678
|
+
case current_line
|
|
679
|
+
when /^(#{IDENTIFIER_RE})\s*=\s*/
|
|
680
|
+
match = Regexp.last_match
|
|
681
|
+
@variables[match[1]] = match.post_match.strip
|
|
682
|
+
when /^(#{IDENTIFIER_RE})\s*:\s*/
|
|
683
|
+
match = Regexp.last_match
|
|
684
|
+
@declarations[match[1]] = match.post_match.strip
|
|
685
|
+
end
|
|
686
|
+
current_line = +""
|
|
395
687
|
end
|
|
396
688
|
end
|
|
397
689
|
end
|
|
398
690
|
|
|
399
691
|
def parse_requires(requires)
|
|
400
692
|
return [] if requires.nil?
|
|
401
|
-
requires_without_version = requires.gsub(/
|
|
693
|
+
requires_without_version = requires.gsub(/(?:<|>|<=|>=|=)\s*[\d.a-zA-Z_-]+\s*/, "")
|
|
402
694
|
requires_without_version.split(/[,\s]+/)
|
|
403
695
|
end
|
|
404
696
|
|
|
@@ -418,69 +710,6 @@ class PackageConfig
|
|
|
418
710
|
end
|
|
419
711
|
end
|
|
420
712
|
|
|
421
|
-
def guess_default_path
|
|
422
|
-
arch_depended_path = Dir.glob("/usr/lib/*/pkgconfig")
|
|
423
|
-
default_paths = [
|
|
424
|
-
"/usr/local/lib64/pkgconfig",
|
|
425
|
-
"/usr/local/libx32/pkgconfig",
|
|
426
|
-
"/usr/local/lib/pkgconfig",
|
|
427
|
-
"/usr/local/libdata/pkgconfig",
|
|
428
|
-
"/usr/local/share/pkgconfig",
|
|
429
|
-
"/opt/local/lib/pkgconfig",
|
|
430
|
-
*arch_depended_path,
|
|
431
|
-
"/usr/lib64/pkgconfig",
|
|
432
|
-
"/usr/libx32/pkgconfig",
|
|
433
|
-
"/usr/lib/pkgconfig",
|
|
434
|
-
"/usr/libdata/pkgconfig",
|
|
435
|
-
"/usr/X11R6/lib/pkgconfig",
|
|
436
|
-
"/usr/X11R6/share/pkgconfig",
|
|
437
|
-
"/usr/X11/lib/pkgconfig",
|
|
438
|
-
"/opt/X11/lib/pkgconfig",
|
|
439
|
-
"/usr/share/pkgconfig",
|
|
440
|
-
]
|
|
441
|
-
libdir = ENV["PKG_CONFIG_LIBDIR"]
|
|
442
|
-
default_paths.unshift(libdir) if libdir
|
|
443
|
-
|
|
444
|
-
paths = []
|
|
445
|
-
pkg_config_prefix = self.class.native_pkg_config_prefix
|
|
446
|
-
if pkg_config_prefix
|
|
447
|
-
pkg_config_arch_depended_paths =
|
|
448
|
-
Dir.glob((pkg_config_prefix + "lib/*/pkgconfig").to_s)
|
|
449
|
-
paths.concat(pkg_config_arch_depended_paths)
|
|
450
|
-
paths << (pkg_config_prefix + "lib64/pkgconfig").to_s
|
|
451
|
-
paths << (pkg_config_prefix + "libx32/pkgconfig").to_s
|
|
452
|
-
paths << (pkg_config_prefix + "lib/pkgconfig").to_s
|
|
453
|
-
paths << (pkg_config_prefix + "libdata/pkgconfig").to_s
|
|
454
|
-
end
|
|
455
|
-
if /-darwin\d[\d\.]*\z/ =~ RUBY_PLATFORM and
|
|
456
|
-
/\A(\d+\.\d+)/ =~ `sw_vers -productVersion`
|
|
457
|
-
mac_os_version = $1
|
|
458
|
-
homebrew_repository_candidates = []
|
|
459
|
-
if pkg_config_prefix
|
|
460
|
-
brew_path = pkg_config_prefix + "bin" + "brew"
|
|
461
|
-
if brew_path.exist?
|
|
462
|
-
escaped_brew_path = Shellwords.escape(brew_path.to_s)
|
|
463
|
-
homebrew_repository = `#{escaped_brew_path} --repository`.chomp
|
|
464
|
-
homebrew_repository_candidates << Pathname.new(homebrew_repository)
|
|
465
|
-
else
|
|
466
|
-
homebrew_repository_candidates << pkg_config_prefix + "Homebrew"
|
|
467
|
-
homebrew_repository_candidates << pkg_config_prefix
|
|
468
|
-
end
|
|
469
|
-
end
|
|
470
|
-
brew = self.class.__send__(:search_executable_from_path, "brew")
|
|
471
|
-
if brew
|
|
472
|
-
homebrew_repository = `brew --repository`.chomp
|
|
473
|
-
homebrew_repository_candidates << Pathname(homebrew_repository)
|
|
474
|
-
end
|
|
475
|
-
homebrew_repository_candidates.uniq.each do |candidate|
|
|
476
|
-
path = candidate + "Library/Homebrew/os/mac/pkgconfig/#{mac_os_version}"
|
|
477
|
-
paths << path.to_s if path.exist?
|
|
478
|
-
end
|
|
479
|
-
end
|
|
480
|
-
paths.concat(default_paths)
|
|
481
|
-
paths.join(SEPARATOR)
|
|
482
|
-
end
|
|
483
|
-
|
|
484
713
|
def required_packages
|
|
485
714
|
collect_requires do |package|
|
|
486
715
|
package.requires
|
|
@@ -499,109 +728,3 @@ class PackageConfig
|
|
|
499
728
|
end
|
|
500
729
|
end
|
|
501
730
|
end
|
|
502
|
-
|
|
503
|
-
module PKGConfig
|
|
504
|
-
@@paths = []
|
|
505
|
-
@@override_variables = {}
|
|
506
|
-
|
|
507
|
-
module_function
|
|
508
|
-
def add_path(path)
|
|
509
|
-
@@paths << path
|
|
510
|
-
end
|
|
511
|
-
|
|
512
|
-
def set_override_variable(key, value)
|
|
513
|
-
@@override_variables[key] = value
|
|
514
|
-
end
|
|
515
|
-
|
|
516
|
-
def msvc?
|
|
517
|
-
/mswin/.match(RUBY_PLATFORM) and /^cl\b/.match(RbConfig::CONFIG['CC'])
|
|
518
|
-
end
|
|
519
|
-
|
|
520
|
-
def package_config(package)
|
|
521
|
-
PackageConfig.new(package,
|
|
522
|
-
:msvc_syntax => msvc?,
|
|
523
|
-
:override_variables => @@override_variables,
|
|
524
|
-
:paths => @@paths)
|
|
525
|
-
end
|
|
526
|
-
|
|
527
|
-
def exist?(pkg)
|
|
528
|
-
package_config(pkg).exist?
|
|
529
|
-
end
|
|
530
|
-
|
|
531
|
-
def libs(pkg)
|
|
532
|
-
package_config(pkg).libs
|
|
533
|
-
end
|
|
534
|
-
|
|
535
|
-
def libs_only_l(pkg)
|
|
536
|
-
package_config(pkg).libs_only_l
|
|
537
|
-
end
|
|
538
|
-
|
|
539
|
-
def libs_only_L(pkg)
|
|
540
|
-
package_config(pkg).libs_only_L
|
|
541
|
-
end
|
|
542
|
-
|
|
543
|
-
def cflags(pkg)
|
|
544
|
-
package_config(pkg).cflags
|
|
545
|
-
end
|
|
546
|
-
|
|
547
|
-
def cflags_only_I(pkg)
|
|
548
|
-
package_config(pkg).cflags_only_I
|
|
549
|
-
end
|
|
550
|
-
|
|
551
|
-
def cflags_only_other(pkg)
|
|
552
|
-
package_config(pkg).cflags_only_other
|
|
553
|
-
end
|
|
554
|
-
|
|
555
|
-
def modversion(pkg)
|
|
556
|
-
package_config(pkg).version
|
|
557
|
-
end
|
|
558
|
-
|
|
559
|
-
def description(pkg)
|
|
560
|
-
package_config(pkg).description
|
|
561
|
-
end
|
|
562
|
-
|
|
563
|
-
def variable(pkg, name)
|
|
564
|
-
package_config(pkg).variable(name)
|
|
565
|
-
end
|
|
566
|
-
|
|
567
|
-
def check_version?(pkg, major=0, minor=0, micro=0)
|
|
568
|
-
return false unless exist?(pkg)
|
|
569
|
-
ver = modversion(pkg).split(".").collect {|item| item.to_i}
|
|
570
|
-
(0..2).each {|i| ver[i] = 0 unless ver[i]}
|
|
571
|
-
|
|
572
|
-
(ver[0] > major ||
|
|
573
|
-
(ver[0] == major && ver[1] > minor) ||
|
|
574
|
-
(ver[0] == major && ver[1] == minor &&
|
|
575
|
-
ver[2] >= micro))
|
|
576
|
-
end
|
|
577
|
-
|
|
578
|
-
def have_package(pkg, major=nil, minor=0, micro=0)
|
|
579
|
-
message = "#{pkg}"
|
|
580
|
-
unless major.nil?
|
|
581
|
-
message << " version (>= #{major}.#{minor}.#{micro})"
|
|
582
|
-
end
|
|
583
|
-
major ||= 0
|
|
584
|
-
enough_version = checking_for(checking_message(message)) do
|
|
585
|
-
check_version?(pkg, major, minor, micro)
|
|
586
|
-
end
|
|
587
|
-
if enough_version
|
|
588
|
-
libraries = libs_only_l(pkg)
|
|
589
|
-
dldflags = libs(pkg)
|
|
590
|
-
dldflags = (Shellwords.shellwords(dldflags) -
|
|
591
|
-
Shellwords.shellwords(libraries))
|
|
592
|
-
dldflags = dldflags.map {|s| /\s/ =~ s ? "\"#{s}\"" : s }.join(' ')
|
|
593
|
-
$libs += ' ' + libraries
|
|
594
|
-
if /mswin/ =~ RUBY_PLATFORM
|
|
595
|
-
$DLDFLAGS += ' ' + dldflags
|
|
596
|
-
else
|
|
597
|
-
$LDFLAGS += ' ' + dldflags
|
|
598
|
-
end
|
|
599
|
-
$CFLAGS += ' ' + cflags_only_other(pkg)
|
|
600
|
-
if defined?($CXXFLAGS)
|
|
601
|
-
$CXXFLAGS += ' ' + cflags_only_other(pkg)
|
|
602
|
-
end
|
|
603
|
-
$INCFLAGS += ' ' + cflags_only_I(pkg)
|
|
604
|
-
end
|
|
605
|
-
enough_version
|
|
606
|
-
end
|
|
607
|
-
end
|