utilrb 3.0.1 → 3.2.0
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 +5 -5
- data/lib/utilrb/event_loop.rb +51 -49
- data/lib/utilrb/exception/full_message.rb +2 -1
- data/lib/utilrb/hash/slice.rb +2 -5
- data/lib/utilrb/kernel/arity.rb +11 -6
- data/lib/utilrb/kernel/load_dsl_file.rb +2 -2
- data/lib/utilrb/kernel/options.rb +3 -4
- data/lib/utilrb/logger/forward.rb +10 -0
- data/lib/utilrb/logger/hierarchy.rb +61 -19
- data/lib/utilrb/logger/root.rb +12 -12
- data/lib/utilrb/marshal/load_with_missing_constants.rb +18 -21
- data/lib/utilrb/marshal.rb +3 -0
- data/lib/utilrb/module/dsl_attribute.rb +37 -25
- data/lib/utilrb/object/address.rb +15 -3
- data/lib/utilrb/object/attribute.rb +2 -1
- data/lib/utilrb/pkgconfig.rb +346 -162
- data/lib/utilrb/test.rb +4 -4
- data/lib/utilrb/thread_pool.rb +29 -25
- data/lib/utilrb/timepoints.rb +7 -0
- data/lib/utilrb/version.rb +1 -1
- data/manifest.xml +1 -0
- data/utilrb.gemspec +1 -0
- metadata +21 -8
- data/.travis.yml +0 -9
data/lib/utilrb/pkgconfig.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
1
|
+
require "set"
|
|
2
|
+
require "shellwords"
|
|
3
3
|
|
|
4
4
|
module Utilrb
|
|
5
5
|
# Access to information from pkg-config(1)
|
|
@@ -32,7 +32,7 @@ module Utilrb
|
|
|
32
32
|
# pkg.static
|
|
33
33
|
#
|
|
34
34
|
# Arbitrary variables defined in the .pc file can be accessed with
|
|
35
|
-
#
|
|
35
|
+
#
|
|
36
36
|
# pkg.prefix
|
|
37
37
|
# pkg.libdir
|
|
38
38
|
#
|
|
@@ -41,15 +41,6 @@ module Utilrb
|
|
|
41
41
|
VAR_NAME_RX = /\w+/
|
|
42
42
|
FIELD_NAME_RX = /[\w\.\-]+/
|
|
43
43
|
|
|
44
|
-
class << self
|
|
45
|
-
attr_reader :loaded_packages
|
|
46
|
-
|
|
47
|
-
def clear_cache
|
|
48
|
-
loaded_packages.clear
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
@loaded_packages = Hash.new
|
|
52
|
-
|
|
53
44
|
def self.load(path, preset_variables)
|
|
54
45
|
pkg_name = File.basename(path, ".pc")
|
|
55
46
|
pkg = Class.instance_method(:new).bind(PkgConfig).call(pkg_name)
|
|
@@ -57,28 +48,44 @@ module Utilrb
|
|
|
57
48
|
pkg
|
|
58
49
|
end
|
|
59
50
|
|
|
51
|
+
def self.load_minimal(path, preset_variables)
|
|
52
|
+
pkg_name = File.basename(path, ".pc")
|
|
53
|
+
pkg = Class.instance_method(:new).bind(PkgConfig).call(pkg_name)
|
|
54
|
+
pkg.load_minimal(path, preset_variables)
|
|
55
|
+
pkg
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# @deprecated {PkgConfig} does not cache the packages anymore, so no
|
|
59
|
+
# need to call this method
|
|
60
|
+
def self.clear_cache
|
|
61
|
+
end
|
|
62
|
+
|
|
60
63
|
# Returns the pkg-config object that matches the given name, and
|
|
61
64
|
# optionally a version string
|
|
62
|
-
def self.get(name, version_spec = nil, preset_variables = Hash.new
|
|
63
|
-
|
|
64
|
-
paths = find_all_package_files(name)
|
|
65
|
-
if paths.empty?
|
|
66
|
-
raise NotFound.new(name), "cannot find the pkg-config specification for #{name}"
|
|
67
|
-
end
|
|
65
|
+
def self.get(name, version_spec = nil, preset_variables = Hash.new,
|
|
66
|
+
minimal: false, pkg_config_path: self.pkg_config_path, memo: Hash.new)
|
|
68
67
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
paths = find_all_package_files(name, pkg_config_path: pkg_config_path)
|
|
69
|
+
if paths.empty?
|
|
70
|
+
raise NotFound.new(name), "cannot find the pkg-config specification for #{name}"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
candidates = paths.map do |p|
|
|
74
|
+
PkgConfig.load_minimal(p, preset_variables)
|
|
74
75
|
end
|
|
75
76
|
|
|
76
77
|
# Now try to find a matching spec
|
|
77
|
-
if
|
|
78
|
-
|
|
78
|
+
if match = find_matching_version(candidates, version_spec)
|
|
79
|
+
memo[[name, version_spec]] = [false, match]
|
|
79
80
|
else
|
|
80
|
-
raise NotFound, "found #{candidates.size} packages for #{name},
|
|
81
|
+
raise NotFound, "found #{candidates.size} packages for #{name},"\
|
|
82
|
+
" but none match the version specification #{version_spec}"
|
|
81
83
|
end
|
|
84
|
+
|
|
85
|
+
match.load_fields(memo: memo) unless minimal
|
|
86
|
+
|
|
87
|
+
memo[[name, version_spec]] = [true, match]
|
|
88
|
+
match
|
|
82
89
|
end
|
|
83
90
|
|
|
84
91
|
# Finds the provided package and optional version and returns its
|
|
@@ -89,8 +96,8 @@ module Utilrb
|
|
|
89
96
|
# ...
|
|
90
97
|
# @return [PkgConfig] the pkg-config description
|
|
91
98
|
# @raise [NotFound] if the package is not found
|
|
92
|
-
def self.new(name, version_spec = nil, options
|
|
93
|
-
get(name, version_spec, options)
|
|
99
|
+
def self.new(name, version_spec = nil, **options)
|
|
100
|
+
get(name, version_spec, **options)
|
|
94
101
|
end
|
|
95
102
|
|
|
96
103
|
# Returns the first package in +candidates+ that match the given version
|
|
@@ -124,44 +131,51 @@ module Utilrb
|
|
|
124
131
|
end
|
|
125
132
|
|
|
126
133
|
# Exception raised when a request pkg-config file is not found
|
|
127
|
-
|
|
134
|
+
class NotFound < RuntimeError
|
|
128
135
|
# The name of the pkg-config package
|
|
129
|
-
|
|
136
|
+
attr_reader :name
|
|
130
137
|
|
|
131
|
-
|
|
132
|
-
|
|
138
|
+
def initialize(name); @name = name end
|
|
139
|
+
end
|
|
133
140
|
|
|
134
141
|
# Exception raised when invalid data is found in a pkg-config file
|
|
135
142
|
class Invalid < RuntimeError
|
|
136
143
|
# The name of the pkg-config package
|
|
137
|
-
|
|
144
|
+
attr_reader :name
|
|
138
145
|
|
|
139
|
-
|
|
146
|
+
def initialize(name); @name = name end
|
|
140
147
|
end
|
|
141
148
|
|
|
142
|
-
|
|
143
|
-
attr_reader :file
|
|
144
149
|
attr_reader :path
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
150
|
+
|
|
151
|
+
# The module name
|
|
152
|
+
attr_reader :name
|
|
148
153
|
attr_reader :description
|
|
154
|
+
|
|
149
155
|
# The module version as a string
|
|
150
156
|
attr_reader :raw_version
|
|
157
|
+
|
|
151
158
|
# The module version, as an array of integers
|
|
152
159
|
attr_reader :version
|
|
153
160
|
|
|
161
|
+
attr_reader :raw_fields
|
|
162
|
+
|
|
154
163
|
# Information extracted from the file
|
|
155
164
|
attr_reader :variables
|
|
156
165
|
attr_reader :fields
|
|
157
166
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
167
|
+
# The list of packages that are Require:'d by this package
|
|
168
|
+
#
|
|
169
|
+
# @return [Array<PkgConfig>]
|
|
170
|
+
attr_reader :requires
|
|
171
|
+
|
|
172
|
+
# Create a PkgConfig object for the package +name+
|
|
173
|
+
# Raises PkgConfig::NotFound if the module does not exist
|
|
174
|
+
def initialize(name)
|
|
175
|
+
@name = name
|
|
176
|
+
@fields = Hash.new
|
|
177
|
+
@variables = Hash.new
|
|
178
|
+
end
|
|
165
179
|
|
|
166
180
|
# Helper method that expands ${word} in +value+ using the name to value
|
|
167
181
|
# map +variables+
|
|
@@ -169,7 +183,7 @@ module Utilrb
|
|
|
169
183
|
# +current+ is a string that describes what we are expanding. It is used
|
|
170
184
|
# to detect recursion in expansion of variables, and to give meaningful
|
|
171
185
|
# errors to the user
|
|
172
|
-
def
|
|
186
|
+
def perform_substitution(value, variables, current)
|
|
173
187
|
value = value.gsub(/\$\{(\w+)\}/) do |rx|
|
|
174
188
|
expand_name = $1
|
|
175
189
|
if expand_name == current
|
|
@@ -182,45 +196,59 @@ module Utilrb
|
|
|
182
196
|
value
|
|
183
197
|
end
|
|
184
198
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
199
|
+
class DependencyLoop < RuntimeError; end
|
|
200
|
+
|
|
201
|
+
def self.parse_dependencies(string, allow_loops: false, memo: Hash.new)
|
|
202
|
+
string = string.gsub(',', ' ')
|
|
203
|
+
packages = []
|
|
204
|
+
words = string.split(' ')
|
|
205
|
+
while !words.empty?
|
|
206
|
+
w = words.shift
|
|
207
|
+
if w =~ /[<>=]/
|
|
208
|
+
version = words.shift
|
|
209
|
+
if version =~ /[\d\.]+/
|
|
210
|
+
packages[-1][1] = "#{w} #{version}"
|
|
195
211
|
else
|
|
196
|
-
packages <<
|
|
212
|
+
packages << [version, nil]
|
|
197
213
|
end
|
|
214
|
+
else
|
|
215
|
+
packages << [w, nil]
|
|
198
216
|
end
|
|
199
217
|
end
|
|
200
|
-
|
|
201
218
|
result = packages.map do |dep|
|
|
202
|
-
|
|
203
|
-
if
|
|
204
|
-
|
|
219
|
+
finished, pkg = memo[dep]
|
|
220
|
+
if pkg
|
|
221
|
+
if allow_loops || finished
|
|
222
|
+
pkg
|
|
223
|
+
else
|
|
224
|
+
raise DependencyLoop, "found a dependency loop"
|
|
225
|
+
end
|
|
205
226
|
else
|
|
206
|
-
PkgConfig.get(dep)
|
|
227
|
+
PkgConfig.get(*dep, memo: memo)
|
|
207
228
|
end
|
|
208
229
|
end
|
|
209
|
-
result
|
|
230
|
+
result.compact
|
|
210
231
|
end
|
|
211
232
|
|
|
212
233
|
SHELL_VARS = %w{Cflags Libs Libs.private}
|
|
213
234
|
|
|
214
|
-
#
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
235
|
+
# @api private
|
|
236
|
+
#
|
|
237
|
+
# Normalize a field name to be lowercase with only the first letter
|
|
238
|
+
# capitalized
|
|
239
|
+
def normalize_field_name(name)
|
|
240
|
+
name = name.downcase
|
|
241
|
+
name[0, 1] = name[0, 1].upcase
|
|
242
|
+
name
|
|
243
|
+
end
|
|
221
244
|
|
|
245
|
+
# Parse a pkg-config field and extracts the raw definition of variables
|
|
246
|
+
# and fields
|
|
247
|
+
#
|
|
248
|
+
# @return [(Hash,Hash)] the set of variables and the set of fields
|
|
249
|
+
def parse(path)
|
|
222
250
|
running_line = nil
|
|
223
|
-
|
|
251
|
+
file = File.readlines(path).map do |line|
|
|
224
252
|
line = line.gsub(/\s*#.*$/, '')
|
|
225
253
|
line = line.strip
|
|
226
254
|
next if line.empty?
|
|
@@ -239,79 +267,137 @@ module Utilrb
|
|
|
239
267
|
end
|
|
240
268
|
end.compact
|
|
241
269
|
|
|
242
|
-
|
|
270
|
+
raw_variables, raw_fields = Hash.new, Hash.new
|
|
243
271
|
file.each do |line|
|
|
244
272
|
case line
|
|
245
273
|
when /^(#{VAR_NAME_RX})\s*=(.*)/
|
|
246
274
|
raw_variables[$1] = $2.strip
|
|
247
275
|
when /^(#{FIELD_NAME_RX}):\s*(.*)/
|
|
248
|
-
|
|
276
|
+
field_name = normalize_field_name($1)
|
|
277
|
+
raw_fields[field_name] = $2.strip
|
|
249
278
|
else
|
|
250
279
|
raise NotImplementedError, "#{path}: cannot parse pkg-config line #{line.inspect}"
|
|
251
280
|
end
|
|
252
281
|
end
|
|
282
|
+
return raw_variables, raw_fields
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def expand_variables(raw_variables)
|
|
286
|
+
raw_variables = raw_variables.dup
|
|
253
287
|
|
|
288
|
+
variables = Hash.new
|
|
254
289
|
# Resolve the variables
|
|
255
290
|
while variables.size != raw_variables.size
|
|
256
291
|
raw_variables.each do |name, value|
|
|
257
|
-
value =
|
|
292
|
+
value = perform_substitution(value, raw_variables, name)
|
|
258
293
|
raw_variables[name] = value
|
|
259
294
|
if value !~ /\$\{#{VAR_NAME_RX}\}/
|
|
260
295
|
variables[name] = value
|
|
261
296
|
end
|
|
262
297
|
end
|
|
263
298
|
end
|
|
299
|
+
variables
|
|
300
|
+
end
|
|
264
301
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
end.compact
|
|
280
|
-
end
|
|
281
|
-
fields[name] = resolved
|
|
282
|
-
else
|
|
283
|
-
fields[name] = expand_variables(value, variables, name)
|
|
302
|
+
def expand_field(name, field)
|
|
303
|
+
if SHELL_VARS.include?(name)
|
|
304
|
+
value = Shellwords.shellsplit(field)
|
|
305
|
+
resolved = Array.new
|
|
306
|
+
while !value.empty?
|
|
307
|
+
value = value.flat_map do |v|
|
|
308
|
+
expanded = perform_substitution(v, variables, name)
|
|
309
|
+
if expanded == v
|
|
310
|
+
resolved << v
|
|
311
|
+
nil
|
|
312
|
+
else
|
|
313
|
+
Shellwords.shellsplit(expanded)
|
|
314
|
+
end
|
|
315
|
+
end.compact
|
|
284
316
|
end
|
|
317
|
+
resolved
|
|
318
|
+
else
|
|
319
|
+
perform_substitution(field, variables, name)
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
def builtin_variables(path)
|
|
324
|
+
{
|
|
325
|
+
"pcfiledir" => File.dirname(path),
|
|
326
|
+
"pc_sysrootdir" => sysrootdir
|
|
327
|
+
}
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def load_variables(path, preset_variables = Hash.new)
|
|
331
|
+
raw_variables, raw_fields = parse(path)
|
|
332
|
+
raw_variables = preset_variables.merge(raw_variables)
|
|
333
|
+
expand_variables(
|
|
334
|
+
raw_variables.merge(builtin_variables(path))
|
|
335
|
+
)
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
def load_minimal(path, preset_variables = Hash.new)
|
|
339
|
+
raw_variables, raw_fields = parse(path)
|
|
340
|
+
raw_variables = preset_variables.merge(raw_variables)
|
|
341
|
+
|
|
342
|
+
@variables = expand_variables(
|
|
343
|
+
raw_variables.merge(builtin_variables(path))
|
|
344
|
+
)
|
|
345
|
+
if raw_fields['Version']
|
|
346
|
+
@raw_version = expand_field('Version', raw_fields['Version'])
|
|
347
|
+
else
|
|
348
|
+
@raw_version = ''
|
|
349
|
+
end
|
|
350
|
+
@version = raw_version.split('.').map { |v| Integer(v) if v =~ /^\d+$/ }.compact
|
|
351
|
+
|
|
352
|
+
# To be used in the call to #load
|
|
353
|
+
@raw_fields = raw_fields
|
|
354
|
+
@path = path
|
|
355
|
+
end
|
|
285
356
|
|
|
357
|
+
def load_fields(memo: Hash.new)
|
|
358
|
+
fields = Hash.new
|
|
359
|
+
@raw_fields.each do |name, value|
|
|
360
|
+
fields[name] = expand_field(name, value)
|
|
286
361
|
end
|
|
362
|
+
@fields = fields
|
|
287
363
|
|
|
288
364
|
# Initialize the main flags
|
|
289
|
-
@raw_version = (fields['Version'] || '')
|
|
290
|
-
@version = raw_version.split('.').map { |v| Integer(v) if v =~ /^\d+$/ }.compact
|
|
291
365
|
@description = (fields['Description'] || '')
|
|
292
366
|
|
|
293
367
|
# Get the requires/conflicts
|
|
294
|
-
@requires = PkgConfig.parse_dependencies(
|
|
295
|
-
|
|
296
|
-
@
|
|
368
|
+
@requires = PkgConfig.parse_dependencies(
|
|
369
|
+
fields['Requires'] || '', allow_loops: false, memo: memo)
|
|
370
|
+
@requires_private = PkgConfig.parse_dependencies(
|
|
371
|
+
fields['Requires.private'] || '', allow_loops: false, memo: memo)
|
|
372
|
+
@conflicts = PkgConfig.parse_dependencies(
|
|
373
|
+
fields['Conflicts'] || '', allow_loops: true, memo: memo)
|
|
297
374
|
|
|
298
375
|
# And finally resolve the compilation flags
|
|
299
|
-
|
|
376
|
+
cflags = fields['Cflags'] || []
|
|
377
|
+
cflags.uniq!
|
|
378
|
+
cflags -= self.class.default_search_path_I
|
|
379
|
+
cflags = apply_sysrootdir(cflags, "-I")
|
|
300
380
|
@requires.each do |pkg|
|
|
301
|
-
|
|
381
|
+
cflags.concat(pkg.raw_cflags)
|
|
302
382
|
end
|
|
303
383
|
@requires_private.each do |pkg|
|
|
304
|
-
|
|
384
|
+
cflags.concat(pkg.raw_cflags)
|
|
305
385
|
end
|
|
306
|
-
@cflags
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
386
|
+
@cflags = cflags
|
|
387
|
+
|
|
388
|
+
ldflags_public = fields['Libs'] || []
|
|
389
|
+
ldflags_public.uniq!
|
|
390
|
+
ldflags_private = ldflags_public + (fields['Libs.private'] || [])
|
|
391
|
+
ldflags_private.uniq!
|
|
392
|
+
|
|
393
|
+
ldflags_public -= self.class.default_search_path_L
|
|
394
|
+
ldflags_public = apply_sysrootdir(ldflags_public, "-L")
|
|
395
|
+
ldflags_private -= self.class.default_search_path_L
|
|
396
|
+
ldflags_private = apply_sysrootdir(ldflags_private, "-L")
|
|
397
|
+
@ldflags = {
|
|
398
|
+
false => ldflags_public,
|
|
399
|
+
true => ldflags_private
|
|
400
|
+
}
|
|
315
401
|
|
|
316
402
|
@ldflags_with_requires = {
|
|
317
403
|
true => @ldflags[true].dup,
|
|
@@ -326,7 +412,15 @@ module Utilrb
|
|
|
326
412
|
end
|
|
327
413
|
end
|
|
328
414
|
|
|
329
|
-
|
|
415
|
+
# Loads the information contained in +path+
|
|
416
|
+
def load(path, preset_variables = Hash.new)
|
|
417
|
+
if !@raw_fields
|
|
418
|
+
load_minimal(path, preset_variables)
|
|
419
|
+
end
|
|
420
|
+
load_fields
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
def self.define_pkgconfig_action(action) # :nodoc:
|
|
330
424
|
class_eval <<-EOD, __FILE__, __LINE__+1
|
|
331
425
|
def pkgconfig_#{action.gsub(/-/, '_')}(static = false)
|
|
332
426
|
if static
|
|
@@ -336,8 +430,8 @@ module Utilrb
|
|
|
336
430
|
end
|
|
337
431
|
end
|
|
338
432
|
EOD
|
|
339
|
-
|
|
340
|
-
|
|
433
|
+
nil
|
|
434
|
+
end
|
|
341
435
|
|
|
342
436
|
def pkgconfig_variable(varname)
|
|
343
437
|
`pkg-config --variable=#{varname}`.strip
|
|
@@ -346,43 +440,79 @@ module Utilrb
|
|
|
346
440
|
# Returns the list of include directories listed in the Cflags: section
|
|
347
441
|
# of the pkgconfig file
|
|
348
442
|
def include_dirs
|
|
349
|
-
result =
|
|
443
|
+
result = raw_cflags_only_I.map { |v| v[2..-1] }
|
|
350
444
|
if result.any?(&:empty?)
|
|
351
445
|
raise Invalid.new(name), "empty include directory (-I without argument) found in pkg-config package #{name}"
|
|
352
446
|
end
|
|
447
|
+
|
|
353
448
|
result
|
|
354
449
|
end
|
|
355
450
|
|
|
356
451
|
# Returns the list of library directories listed in the Libs: section
|
|
357
452
|
# of the pkgconfig file
|
|
358
453
|
def library_dirs
|
|
359
|
-
result =
|
|
454
|
+
result = raw_libs_only_L.map { |v| v[2..-1] }
|
|
360
455
|
if result.any?(&:empty?)
|
|
361
456
|
raise Invalid.new(name), "empty link directory (-L without argument) found in pkg-config package #{name}"
|
|
362
457
|
end
|
|
458
|
+
|
|
363
459
|
result
|
|
364
460
|
end
|
|
365
461
|
|
|
366
|
-
|
|
462
|
+
# A "new root" that should be prepended to -L and -I flags
|
|
463
|
+
def sysrootdir
|
|
464
|
+
ENV["PKG_CONFIG_SYSROOT_DIR"] || "/"
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
# @api private
|
|
468
|
+
#
|
|
469
|
+
# Apply {#sysrootdir} to all the given paths flags (-I or -L)
|
|
470
|
+
def apply_sysrootdir(entries, flag_name)
|
|
471
|
+
sysrootdir = self.sysrootdir
|
|
472
|
+
return entries if sysrootdir == "/"
|
|
473
|
+
|
|
474
|
+
entries.map do |v|
|
|
475
|
+
if v.start_with?(flag_name)
|
|
476
|
+
"#{flag_name}#{sysrootdir}#{v[2..-1]}"
|
|
477
|
+
else
|
|
478
|
+
v
|
|
479
|
+
end
|
|
480
|
+
end
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
ACTIONS = %w{cflags cflags-only-I cflags-only-other
|
|
367
484
|
libs libs-only-L libs-only-l libs-only-other}
|
|
368
|
-
|
|
485
|
+
ACTIONS.each { |action| define_pkgconfig_action(action) }
|
|
486
|
+
|
|
487
|
+
def conflicts
|
|
488
|
+
@conflicts
|
|
489
|
+
end
|
|
369
490
|
|
|
370
491
|
def raw_cflags
|
|
371
492
|
@cflags
|
|
372
493
|
end
|
|
373
494
|
|
|
495
|
+
def raw_cflags_only_I
|
|
496
|
+
@cflags.grep(/^-I/)
|
|
497
|
+
end
|
|
498
|
+
|
|
499
|
+
def raw_cflags_only_other
|
|
500
|
+
@cflags.find_all { |s| s !~ /^-I/ }
|
|
501
|
+
end
|
|
502
|
+
|
|
374
503
|
def cflags
|
|
375
|
-
|
|
504
|
+
raw_cflags.join(" ")
|
|
376
505
|
end
|
|
377
506
|
|
|
378
507
|
def cflags_only_I
|
|
379
|
-
|
|
508
|
+
raw_cflags_only_I.join(" ")
|
|
380
509
|
end
|
|
381
510
|
|
|
382
511
|
def cflags_only_other
|
|
383
|
-
|
|
512
|
+
raw_cflags_only_other.join(" ")
|
|
384
513
|
end
|
|
385
514
|
|
|
515
|
+
|
|
386
516
|
def raw_ldflags
|
|
387
517
|
@ldflags
|
|
388
518
|
end
|
|
@@ -391,41 +521,63 @@ module Utilrb
|
|
|
391
521
|
@ldflags_with_requires
|
|
392
522
|
end
|
|
393
523
|
|
|
524
|
+
|
|
525
|
+
def raw_libs(static = false)
|
|
526
|
+
@ldflags_with_requires[static]
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
def raw_libs_only_L(static = false)
|
|
530
|
+
@ldflags_with_requires[static].grep(/^-L/)
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
def raw_libs_only_l(static = false)
|
|
534
|
+
@ldflags_with_requires[static].grep(/^-l/)
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
def raw_libs_only_other(static = false)
|
|
538
|
+
@ldflags_with_requires[static].find_all { |s| s !~ /^-[lL]/ }
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
|
|
394
542
|
def libs(static = false)
|
|
395
|
-
|
|
543
|
+
raw_libs(static).join(" ")
|
|
396
544
|
end
|
|
397
545
|
|
|
398
546
|
def libs_only_L(static = false)
|
|
399
|
-
|
|
547
|
+
raw_libs_only_L(static).join(" ")
|
|
400
548
|
end
|
|
401
549
|
|
|
402
550
|
def libs_only_l(static = false)
|
|
403
|
-
|
|
551
|
+
raw_libs_only_l(static).join(" ")
|
|
404
552
|
end
|
|
405
553
|
|
|
406
554
|
def libs_only_other(static = false)
|
|
407
|
-
|
|
555
|
+
raw_libs_only_other(static).join(" ")
|
|
408
556
|
end
|
|
409
557
|
|
|
410
|
-
|
|
411
|
-
|
|
558
|
+
def method_missing(varname, *args, &proc) # :nodoc:
|
|
559
|
+
if args.empty?
|
|
412
560
|
variables[varname.to_s]
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
end
|
|
416
|
-
end
|
|
417
|
-
|
|
418
|
-
def self.each_pkgconfig_directory(&block)
|
|
419
|
-
if path = ENV['PKG_CONFIG_PATH']
|
|
420
|
-
path.split(':').each(&block)
|
|
561
|
+
else
|
|
562
|
+
super(varname, *args, &proc)
|
|
421
563
|
end
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
def self.pkg_config_path
|
|
567
|
+
ENV['PKG_CONFIG_PATH']
|
|
568
|
+
end
|
|
569
|
+
|
|
570
|
+
def self.each_pkgconfig_directory(pkg_config_path: self.pkg_config_path, &block)
|
|
571
|
+
return enum_for(__method__) if !block_given?
|
|
572
|
+
|
|
573
|
+
pkg_config_path.split(':').each(&block) if pkg_config_path
|
|
422
574
|
default_search_path.each(&block)
|
|
423
575
|
end
|
|
424
576
|
|
|
425
577
|
# Returns true if there is a package with this name
|
|
426
|
-
def self.find_all_package_files(name)
|
|
578
|
+
def self.find_all_package_files(name, pkg_config_path: self.pkg_config_path)
|
|
427
579
|
result = []
|
|
428
|
-
each_pkgconfig_directory do |dir|
|
|
580
|
+
each_pkgconfig_directory(pkg_config_path: pkg_config_path) do |dir|
|
|
429
581
|
path = File.join(dir, "#{name}.pc")
|
|
430
582
|
if File.exist?(path)
|
|
431
583
|
result << path
|
|
@@ -434,9 +586,9 @@ module Utilrb
|
|
|
434
586
|
result
|
|
435
587
|
end
|
|
436
588
|
|
|
437
|
-
def self.available_package_names
|
|
589
|
+
def self.available_package_names(pkg_config_path: self.pkg_config_path)
|
|
438
590
|
result = []
|
|
439
|
-
each_pkgconfig_directory do |dir|
|
|
591
|
+
each_pkgconfig_directory(pkg_config_path: pkg_config_path) do |dir|
|
|
440
592
|
Dir.glob(File.join(dir, "*.pc")) do |path|
|
|
441
593
|
result << File.basename(path, ".pc")
|
|
442
594
|
end
|
|
@@ -445,15 +597,17 @@ module Utilrb
|
|
|
445
597
|
end
|
|
446
598
|
|
|
447
599
|
# Returns true if there is a package with this name
|
|
448
|
-
def self.has_package?(name)
|
|
449
|
-
!find_all_package_files(name).empty?
|
|
600
|
+
def self.has_package?(name, pkg_config_path: self.pkg_config_path)
|
|
601
|
+
!find_all_package_files(name, pkg_config_path: pkg_config_path).empty?
|
|
450
602
|
end
|
|
451
603
|
|
|
452
604
|
# Yields the package names of available packages. If +regex+ is given,
|
|
453
605
|
# lists only the names that match the regular expression.
|
|
454
|
-
def self.each_package(regex = nil)
|
|
606
|
+
def self.each_package(regex = nil, pkg_config_path: self.pkg_config_path)
|
|
607
|
+
return enum_for(__method__) if !block_given?
|
|
608
|
+
|
|
455
609
|
seen = Set.new
|
|
456
|
-
each_pkgconfig_directory do |dir|
|
|
610
|
+
each_pkgconfig_directory(pkg_config_path: pkg_config_path) do |dir|
|
|
457
611
|
Dir.glob(File.join(dir, '*.pc')) do |file|
|
|
458
612
|
pkg_name = File.basename(file, ".pc")
|
|
459
613
|
next if seen.include?(pkg_name)
|
|
@@ -466,34 +620,64 @@ module Utilrb
|
|
|
466
620
|
end
|
|
467
621
|
|
|
468
622
|
|
|
469
|
-
|
|
470
|
-
NONEXISTENT_PATH_RX = /Cannot open directory (?:#\d+ )?'.*\/((?:lib|lib64|share)\/.*)' in package search path:.*/
|
|
623
|
+
PKGCONFIG_PATH_RX = %r{.*/((?:lib|lib64|share)/.*)}.freeze
|
|
471
624
|
|
|
472
625
|
# Returns the system-wide search path that is embedded in pkg-config
|
|
473
626
|
def self.default_search_path
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
627
|
+
@default_search_path ||=
|
|
628
|
+
`LANG=C pkg-config --variable pc_path pkg-config`
|
|
629
|
+
.strip
|
|
630
|
+
.split(":")
|
|
631
|
+
.grep(PKGCONFIG_PATH_RX)
|
|
632
|
+
.to_set
|
|
480
633
|
end
|
|
634
|
+
|
|
481
635
|
@default_search_path = nil
|
|
482
636
|
|
|
637
|
+
def self.arch_dir
|
|
638
|
+
return if @arch_dir == false
|
|
639
|
+
|
|
640
|
+
unless @arch_dir
|
|
641
|
+
suffix_with_arch =
|
|
642
|
+
default_search_suffixes
|
|
643
|
+
.find { |p| %r{^lib/[^/]+/pkgconfig} =~ p }
|
|
644
|
+
|
|
645
|
+
@arch_dir =
|
|
646
|
+
if suffix_with_arch
|
|
647
|
+
suffix_with_arch.split("/")[1]
|
|
648
|
+
else
|
|
649
|
+
false
|
|
650
|
+
end
|
|
651
|
+
end
|
|
652
|
+
|
|
653
|
+
@arch_dir
|
|
654
|
+
end
|
|
655
|
+
|
|
656
|
+
def self.default_search_path_L # rubocop:disable Naming/MethodName
|
|
657
|
+
unless @default_search_path_L
|
|
658
|
+
arch_dir = self.arch_dir
|
|
659
|
+
@default_search_path_L = # rubocop:disable Naming/VariableName
|
|
660
|
+
["-L/usr/lib", "-L/lib"]
|
|
661
|
+
.flat_map { |p| [p, "#{p}/#{arch_dir}"] }
|
|
662
|
+
end
|
|
663
|
+
|
|
664
|
+
@default_search_path_L
|
|
665
|
+
end
|
|
666
|
+
|
|
667
|
+
def self.default_search_path_I # rubocop:disable Naming/MethodName
|
|
668
|
+
@default_search_path_I ||= ["-I/usr/include"] # rubocop:disable Naming/VariableName
|
|
669
|
+
end
|
|
670
|
+
|
|
483
671
|
# Returns the system-wide standard suffixes that should be appended to
|
|
484
672
|
# new prefixes to find pkg-config files
|
|
485
673
|
def self.default_search_suffixes
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
to_set
|
|
494
|
-
@default_search_suffixes = found_paths | not_found
|
|
495
|
-
end
|
|
496
|
-
return @default_search_suffixes
|
|
674
|
+
@default_search_suffixes ||=
|
|
675
|
+
`LANG=C pkg-config --variable pc_path pkg-config`
|
|
676
|
+
.strip
|
|
677
|
+
.split(":")
|
|
678
|
+
.grep(PKGCONFIG_PATH_RX)
|
|
679
|
+
.map { |l| l.gsub(PKGCONFIG_PATH_RX, '\1') }
|
|
680
|
+
.to_set
|
|
497
681
|
end
|
|
498
682
|
end
|
|
499
683
|
end
|