File Coverage

blib/lib/PkgConfig.pm
Criterion Covered Total %
statement 289 393 73.5
branch 50 102 49.0
condition 14 26 53.8
subroutine 50 57 87.7
pod 4 18 22.2
total 407 596 68.2


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             # lightweight no-dependency version of pkg-config. This will work on any machine
4             # with Perl installed.
5              
6             # Copyright (C) 2012 M. Nunberg.
7             # You may use and distribute this software under the same terms and conditions
8             # as Perl itself.
9              
10             package
11             PkgConfig::Vars;
12             # this is a namespace for .pc files to hold their variables without
13             # relying on lexical scope.
14              
15             package
16             PkgConfig::UDefs;
17             # This namespace provides user-defined variables which are to override any
18             # declarations within the .pc file itself.
19              
20             package PkgConfig;
21              
22             #First two digits are Perl version, second two are pkg-config version
23             our $VERSION = '0.23026';
24              
25             $VERSION =~ /([0-9]{2})$/;
26             my $compat_version = $1;
27              
28 10     10   353801 use strict;
  10         98  
  10         301  
29 10     10   44 use warnings;
  10         14  
  10         290  
30 10     10   247 use 5.006;
  10         29  
31 10     10   145 use Config;
  10         20  
  10         488  
32 10     10   69 use File::Spec;
  10         14  
  10         324  
33 10     10   44 use File::Glob 'bsd_glob';
  10         17  
  10         1093  
34 10     10   4779 use Class::Struct; #in core since 5.004
  10         16193  
  10         53  
35 10     10   6682 use Data::Dumper;
  10         57578  
  10         603  
36 10     10   66 use File::Basename qw( dirname );
  10         19  
  10         739  
37 10     10   4317 use Text::ParseWords qw( shellwords );
  10         11244  
  10         1850  
38              
39             our $UseDebugging;
40              
41             ################################################################################
42             ### Check for Log::Fu ###
43             ################################################################################
44             BEGIN {
45 10     10   700 my $ret = eval q{
  10     10   1878  
  0         0  
  0         0  
46             use Log::Fu 0.25 { level => "warn" };
47             1;
48             };
49            
50 10 50       62 if(!$ret) {
51             my $log_base = sub {
52 0     0   0 my (@args) = @_;
53 0         0 print STDERR "[DEBUG] ", join(' ', @args);
54 0         0 print STDERR "\n";
55 10         45 };
56 10 50   236   49 *log_debug = *log_debugf = sub { return unless $UseDebugging; goto &$log_base };
  236         381  
  0         0  
57 10         15995 *log_err = *log_errf = *log_warn = *log_warnf = *log_info = *log_infof =
58             $log_base;
59            
60             }
61             }
62              
63             our $VarClassSerial = 0;
64              
65             ################################################################################
66             ### Sane Defaults ###
67             ################################################################################
68             our @DEFAULT_SEARCH_PATH = qw(
69             /usr/local/lib/pkgconfig /usr/local/share/pkgconfig
70             /usr/lib/pkgconfig /usr/share/pkgconfig
71              
72             );
73              
74             our @DEFAULT_EXCLUDE_CFLAGS = qw(-I/usr/include -I/usr/local/include);
75             # don't include default link/search paths!
76             our @DEFAULT_EXCLUDE_LFLAGS = map { ( "-L$_", "-R$_" ) } qw( /lib /lib32 /lib64 /usr/lib /usr/lib32 /usr/lib/64 /usr/local/lib /usr/local/lib32 /usr/local/lib64 );
77              
78             if($ENV{PKG_CONFIG_NO_OS_CUSTOMIZATION}) {
79              
80             # use the defaults regardless of detected platform
81              
82             } elsif($ENV{PKG_CONFIG_LIBDIR}) {
83              
84             @DEFAULT_SEARCH_PATH = split $Config{path_sep}, $ENV{PKG_CONFIG_LIBDIR};
85              
86             } elsif($^O eq 'msys') {
87              
88             # MSYS2 seems to actually set PKG_CONFIG_PATH in its /etc/profile
89             # god bless it. But. The defaults if you unset the environment
90             # variable are different
91             @DEFAULT_SEARCH_PATH = qw(
92             /usr/lib/pkgconfig
93             /usr/share/pkgconfig
94             );
95              
96             } elsif($^O eq 'solaris' && $Config{ptrsize} == 8) {
97              
98             @DEFAULT_SEARCH_PATH = qw(
99             /usr/local/lib/64/pkgconfig /usr/local/share/pkgconfig
100             /usr/lib/64/pkgconfig /usr/share/pkgconfig
101             );
102              
103             } elsif($^O eq 'linux' and -f '/etc/gentoo-release') {
104             # OK, we're running on Gentoo
105              
106             # Fetch ptrsize value
107             my $ptrsize = $Config{ptrsize};
108              
109             # Are we running on 64 bit system?
110             if ($ptrsize eq 8) {
111             # We do
112             @DEFAULT_SEARCH_PATH = qw!
113             /usr/lib64/pkgconfig/ /usr/share/pkgconfig/
114             !;
115             } else {
116             # We're running on a 32 bit system (hopefully)
117             @DEFAULT_SEARCH_PATH = qw!
118             /usr/lib/pkgconfig/ /usr/share/pkgconfig/
119             !;
120             }
121              
122             } elsif($^O =~ /^(gnukfreebsd|linux)$/ && -r "/etc/debian_version") {
123              
124             my $arch;
125             if(-x "/usr/bin/dpkg-architecture") {
126             # works if dpkg-dev is installed
127             # rt96694
128             ($arch) = map { chomp; (split /=/)[1] }
129             grep /^DEB_HOST_MULTIARCH=/,
130             `/usr/bin/dpkg-architecture`;
131             } elsif(-x "/usr/bin/gcc") {
132             # works if gcc is installed
133             $arch = `/usr/bin/gcc -dumpmachine`;
134             chomp $arch;
135             } else {
136             my $deb_arch = `dpkg --print-architecture`;
137             if($deb_arch =~ /^amd64/) {
138             if($^O eq 'linux') {
139             $arch = 'x86_64-linux-gnu';
140             } elsif($^O eq 'gnukfreebsd') {
141             $arch = 'x86_64-kfreebsd-gnu';
142             }
143             } elsif($deb_arch =~ /^i386/) {
144             if($^O eq 'linux') {
145             $arch = 'i386-linux-gnu';
146             } elsif($^O eq 'gnukfreebsd') {
147             $arch = 'i386-kfreebsd-gnu';
148             }
149             }
150             }
151              
152             if($arch) {
153             if(scalar grep /--print-foreign-architectures/, `dpkg --help`)
154             {
155             # multi arch support / Debian 7+
156             @DEFAULT_SEARCH_PATH = (
157             "/usr/local/lib/$arch/pkgconfig",
158             "/usr/local/lib/pkgconfig",
159             "/usr/local/share/pkgconfig",
160             "/usr/lib/$arch/pkgconfig",
161             "/usr/lib/pkgconfig",
162             "/usr/share/pkgconfig",
163             );
164              
165             push @DEFAULT_EXCLUDE_LFLAGS, map { ("-L$_", "-R$_") }
166             "/usr/local/lib/$arch",
167             "/usr/lib/$arch";
168              
169             } else {
170            
171             @DEFAULT_SEARCH_PATH = (
172             "/usr/local/lib/pkgconfig",
173             "/usr/local/lib/pkgconfig/$arch",
174             "/usr/local/share/pkgconfig",
175             "/usr/lib/pkgconfig",
176             "/usr/lib/pkgconfig/$arch",
177             "/usr/share/pkgconfig",
178             );
179             }
180            
181             } else {
182              
183             @DEFAULT_SEARCH_PATH = (
184             "/usr/local/lib/pkgconfig",
185             "/usr/local/share/pkgconfig",
186             "/usr/lib/pkgconfig",
187             "/usr/share/pkgconfig",
188             );
189              
190             }
191            
192             } elsif($^O eq 'linux' && -r "/etc/redhat-release") {
193              
194             if(-d "/usr/lib64/pkgconfig") {
195             @DEFAULT_SEARCH_PATH = qw(
196             /usr/lib64/pkgconfig
197             /usr/share/pkgconfig
198             );
199             } else {
200             @DEFAULT_SEARCH_PATH = qw(
201             /usr/lib/pkgconfig
202             /usr/share/pkgconfig
203             );
204             }
205              
206             } elsif($^O eq 'linux' && -r "/etc/slackware-version") {
207              
208             # Fetch ptrsize value
209             my $ptrsize = $Config{ptrsize};
210              
211             # Are we running on 64 bit system?
212             if ($ptrsize == 8) {
213             # We do
214             @DEFAULT_SEARCH_PATH = qw!
215             /usr/lib64/pkgconfig/ /usr/share/pkgconfig/
216             !;
217             } else {
218             # We're running on a 32 bit system (hopefully)
219             @DEFAULT_SEARCH_PATH = qw!
220             /usr/lib/pkgconfig/ /usr/share/pkgconfig/
221             !;
222             }
223            
224              
225             } elsif($^O eq 'freebsd') {
226              
227             # TODO: FreeBSD 10's version of pkg-config does not
228             # support PKG_CONFIG_DEBUG_SPEW so I can't verify
229             # the path there, but this is what it is for
230             # FreeBSD 9
231             @DEFAULT_SEARCH_PATH = qw(
232             /usr/local/libdata/pkgconfig
233             /usr/local/lib/pkgconfig
234             );
235              
236             } elsif($^O eq 'netbsd') {
237              
238             @DEFAULT_SEARCH_PATH = qw(
239             /usr/pkg/lib/pkgconfig
240             /usr/pkg/share/pkgconfig
241             /usr/X11R7/lib/pkgconfig
242             /usr/lib/pkgconfig
243             );
244             } elsif($^O eq 'openbsd') {
245              
246             @DEFAULT_SEARCH_PATH = qw(
247             /usr/lib/pkgconfig
248             /usr/local/lib/pkgconfig
249             /usr/local/share/pkgconfig
250             /usr/X11R6/lib/pkgconfig
251             /usr/X11R6/share/pkgconfig
252             );
253              
254             } elsif($^O eq 'MSWin32') {
255              
256             # Caveats:
257             # 1. This pulls in Config,
258             # which we don't load on non MSWin32
259             # but it is in the core.
260             # 2. Slight semantic difference in that we are treating
261             # Strawberry as the "system" rather than Windows, but
262             # since pkg-config is rarely used in MSWin32, it is
263             # better to have something that is useful rather than
264             # worry about if it is exactly the same as other
265             # platforms.
266             # 3. It is a little brittle in that Strawberry might
267             # one day change its layouts. If it has and you are
268             # reading this, please send a pull request or simply
269             # let me know -plicease
270             require Config;
271             if($Config::Config{myuname} =~ /strawberry-perl/)
272             {
273             # handle PAR::Packer executables which have $^X eq "perl.exe"
274             if ($ENV{PAR_0})
275             {
276             my $path = $ENV{PAR_TEMP};
277             $path =~ s{\\}{/}g;
278             @DEFAULT_SEARCH_PATH = ($path);
279             }
280             else {
281             my($vol, $dir, $file) = File::Spec->splitpath($^X);
282             my @dirs = File::Spec->splitdir($dir);
283             splice @dirs, -3;
284             my $path = (File::Spec->catdir($vol, @dirs, qw( c lib pkgconfig )));
285             $path =~ s{\\}{/}g;
286             @DEFAULT_SEARCH_PATH = $path;
287             }
288             }
289            
290             my @reg_paths;
291            
292             eval q{
293             package
294             PkgConfig::WinReg;
295            
296             use Win32API::Registry 0.21 qw( :ALL );
297            
298             foreach my $top (HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER) {
299             my $key;
300             RegOpenKeyEx( $top, "Software\\\\pkgconfig\\\\PKG_CONFIG_PATH", 0, KEY_READ, $key) || next;
301             my $nlen = 1024;
302             my $pos = 0;
303             my $name = '';
304            
305             while(RegEnumValue($key, $pos++, $name, $nlen, [], [], [], [])) {
306             my $type;
307             my $data;
308             RegQueryValueEx($key, $name, [], $type, $data, []);
309             push @reg_paths, $data;
310             }
311            
312             RegCloseKey( $key );
313             }
314             };
315            
316             unless($@) {
317             unshift @DEFAULT_SEARCH_PATH, @reg_paths;
318             }
319              
320             if($Config::Config{cc} =~ /cl(\.exe)?$/i)
321             {
322             @DEFAULT_EXCLUDE_LFLAGS = ();
323             @DEFAULT_EXCLUDE_CFLAGS = ();
324             }
325             else
326             {
327             @DEFAULT_EXCLUDE_LFLAGS = (
328             "-L/mingw/lib",
329             "-R/mingw/lib",
330             "-L/mingw/lib/pkgconfig/../../lib",
331             "-R/mingw/lib/pkgconfig/../../lib",
332             );
333             @DEFAULT_EXCLUDE_CFLAGS = (
334             "-I/mingw/include",
335             "-I/mingw/lib/pkgconfig/../../include",
336             );
337             }
338            
339             # See caveats above for Strawberry and PAR::Packer
340             require Config;
341             if(not $ENV{PAR_0} and $Config::Config{myuname} =~ /strawberry-perl/)
342             {
343             my($vol, $dir, $file) = File::Spec->splitpath($^X);
344             my @dirs = File::Spec->splitdir($dir);
345             splice @dirs, -3;
346             my $path = (File::Spec->catdir($vol, @dirs, qw( c )));
347             $path =~ s{\\}{/}g;
348             push @DEFAULT_EXCLUDE_LFLAGS, (
349             "-L$path/lib",
350             "-L$path/lib/pkgconfig/../../lib",
351             "-R$path/lib",
352             "-R$path/lib/pkgconfig/../../lib",
353             );
354             push @DEFAULT_EXCLUDE_CFLAGS, (
355             "-I$path/include",
356             "-I$path/lib/pkgconfig/../../include",
357             );
358             }
359             } elsif($^O eq 'darwin') {
360              
361             if(-x '/usr/local/Homebrew/bin/brew') {
362             # Mac OS X with homebrew installed
363             push @DEFAULT_SEARCH_PATH,
364             bsd_glob '/usr/local/opt/*/lib/pkgconfig'
365             ;
366             }
367              
368             }
369              
370             my @ENV_SEARCH_PATH = split($Config{path_sep}, $ENV{PKG_CONFIG_PATH} || "");
371              
372             unshift @DEFAULT_SEARCH_PATH, @ENV_SEARCH_PATH;
373              
374             if($^O eq 'MSWin32') {
375             @DEFAULT_SEARCH_PATH = map { s{\\}{/}g; $_ } map { /\s/ ? Win32::GetShortPathName($_) : $_ } @DEFAULT_SEARCH_PATH;
376             }
377              
378             if($ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS}) {
379             @DEFAULT_EXCLUDE_CFLAGS = ();
380             }
381              
382             if($ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS}) {
383             @DEFAULT_EXCLUDE_LFLAGS = ();
384             }
385              
386             my $LD_OUTPUT_RE = qr/
387             SEARCH_DIR\("
388             ([^"]+)
389             "\)
390             /x;
391              
392             sub GuessPaths {
393 0     0 0 0 my $pkg = shift;
394 0         0 local $ENV{LD_LIBRARY_PATH} = "";
395 0         0 local $ENV{C_INCLUDE_PATH} = "";
396 0         0 local $ENV{LD_RUN_PATH} = "";
397            
398 0   0     0 my $ld = $ENV{LD} || 'ld';
399 0         0 my $ld_output = qx(ld -verbose);
400 0         0 my @defl_search_dirs = ($ld_output =~ m/$LD_OUTPUT_RE/g);
401            
402 0         0 @DEFAULT_EXCLUDE_LFLAGS = ();
403 0         0 foreach my $path (@defl_search_dirs) {
404 0         0 push @DEFAULT_EXCLUDE_LFLAGS, (map { "$_".$path }
  0         0  
405             (qw(-R -L -rpath= -rpath-link= -rpath -rpath-link)));
406             }
407 0         0 log_debug("Determined exclude LDFLAGS", @DEFAULT_EXCLUDE_LFLAGS);
408            
409             #now get the include paths:
410 0         0 my @cpp_output = qx(cpp --verbose 2>&1 < /dev/null);
411 0         0 @cpp_output = map { chomp $_; $_ } @cpp_output;
  0         0  
  0         0  
412             #log_info(join("!", @cpp_output));
413 0         0 while (my $cpp_line = shift @cpp_output) {
414 0         0 chomp($cpp_line);
415 0 0       0 if($cpp_line =~ /\s*#include\s*<.+search starts here/) {
416 0         0 last;
417             }
418             }
419             #log_info(@cpp_output);
420 0         0 my @include_paths;
421 0         0 while (my $path = shift @cpp_output) {
422 0 0       0 if($path =~ /\s*End of search list/) {
423 0         0 last;
424             }
425 0         0 push @include_paths, $path;
426             }
427 0         0 @DEFAULT_EXCLUDE_CFLAGS = map { "-I$_" } @include_paths;
  0         0  
428 0         0 log_debug("Determine exclude CFLAGS", @DEFAULT_EXCLUDE_CFLAGS);
429             }
430              
431              
432             ################################################################################
433             ### Define our fields ###
434             ################################################################################
435             struct(
436             __PACKAGE__,
437             [
438             # .pc search paths, defaults to PKG_CONFIG_PATH in environment
439             'search_path' => '@',
440              
441             # whether to also spit out static dependencies
442             'static' => '$',
443            
444             # whether we replace references to -L and friends with -Wl,-rpath, etc.
445             'rpath' => '$',
446            
447             # build rpath-search,
448            
449             # no recursion. set if we just want a version, or to see if the
450             # package exists.
451             'no_recurse' => '$',
452              
453             #list of cflags and ldflags to exclude
454             'exclude_ldflags' => '@',
455             'exclude_cflags' => '@',
456              
457             # what level of recursion we're at
458             'recursion' => '$',
459              
460             # hash of libraries, keyed by recursion levels. Lower recursion numbers
461             # will be listed first
462             'libs_deplist' => '*%',
463              
464             # cumulative cflags and ldflags
465             'ldflags' => '*@',
466             'cflags' => '*@',
467              
468             # whether we print the c/ldflags
469             'print_cflags' => '$',
470             'print_ldflags' => '$',
471              
472             # information about our top-level package
473             'pkg' => '$',
474             'pkg_exists' => '$',
475             'pkg_version' => '$',
476             'pkg_url', => '$',
477             'pkg_description' => '$',
478             'errmsg' => '$',
479            
480             # classes used for storing persistent data
481             'varclass' => '$',
482             'udefclass' => '$',
483             'filevars' => '*%',
484             'uservars' => '*%',
485            
486             # options for printing variables
487             'print_variables' => '$',
488             'print_variable' => '$',
489             'print_values' => '$',
490             'defined_variables' => '*%',
491            
492             # for creating PkgConfig objects with identical
493             # settings
494             'original' => '$',
495             ]
496             );
497              
498             ################################################################################
499             ################################################################################
500             ### Variable Storage ###
501             ################################################################################
502             ################################################################################
503              
504             sub _get_pc_varname {
505 197     197   269 my ($self,$vname_base) = @_;
506 197         2349 $self->varclass . "::" . $vname_base;
507             }
508              
509             sub _get_pc_udefname {
510 0     0   0 my ($self,$vname_base) = @_;
511 0         0 $self->udefclass . "::" . $vname_base;
512             }
513              
514             sub _pc_var {
515 79     79   125 my ($self,$vname) = @_;
516 79         140 $vname =~ s,\.,DOT,g;
517 10     10   71 no strict 'refs';
  10         70  
  10         522  
518 79         131 $vname = $self->_get_pc_varname($vname);
519 10     10   57 no warnings qw(once);
  10         20  
  10         1558  
520 79         479 my $glob = *{$vname};
  79         256  
521 79 50       628 $glob ? $$glob : ();
522             }
523              
524             sub _quote_cvt($) {
525 118     118   290 join ' ', map { s/(\s|"|')/\\$1/g; $_ } shellwords(shift)
  176         7338  
  176         911  
526             }
527              
528             sub assign_var {
529 118     118 0 198 my ($self,$field,$value) = @_;
530 10     10   65 no strict 'refs';
  10         16  
  10         872  
531            
532             # if the user has provided a definition, use that.
533 118 50       116 if(exists ${$self->udefclass."::"}{$field}) {
  118         1395  
534 0         0 log_debug("Prefix already defined by user");
535 0         0 return;
536             }
537 118         940 my $evalstr = sprintf('$%s = PkgConfig::_quote_cvt(%s)',
538             $self->_get_pc_varname($field), $value);
539            
540 118         980 log_debug("EVAL", $evalstr);
541 118         121 do {
542 10     10   70 no warnings 'uninitialized';
  10         34  
  10         864  
543 118         5235 eval $evalstr;
544             };
545 118 50       548 if($@) {
546 0         0 log_err($@);
547             }
548             }
549              
550             sub prepare_vars {
551 11     11 0 19 my $self = shift;
552 11         213 my $varclass = $self->varclass;
553 10     10   60 no strict 'refs';
  10         15  
  10         2895  
554            
555 11         91 %{$varclass . "::"} = ();
  11         70  
556            
557 11         24 while (my ($name,$glob) = each %{$self->udefclass."::"}) {
  11         147  
558 0         0 my $ref = *$glob{SCALAR};
559 0 0       0 next unless defined $ref;
560 0         0 ${"$varclass\::$name"} = $$ref;
  0         0  
561             }
562             }
563              
564             ################################################################################
565             ################################################################################
566             ### Initializer ###
567             ################################################################################
568             ################################################################################
569             sub find {
570 13     13 1 20129 my ($cls,$library,%options) = @_;
571 13         79 my @uspecs = (
572             ['search_path', \@DEFAULT_SEARCH_PATH],
573             ['exclude_ldflags', \@DEFAULT_EXCLUDE_LFLAGS],
574             ['exclude_cflags', \@DEFAULT_EXCLUDE_CFLAGS]
575             );
576            
577 13         34 my %original = %options;
578            
579 13         25 foreach (@uspecs) {
580 39         70 my ($basekey,$default) = @$_;
581 39   100     41 my $list = [ @{$options{$basekey} ||= [] } ];
  39         173  
582 39 50       97 if($options{$basekey . "_override"}) {
583 0         0 @$list = @{ delete $options{$basekey."_override"} };
  0         0  
584             } else {
585 39         148 push @$list, @$default;
586             }
587              
588 39         73 $options{$basekey} = $list;
589             #print "$basekey: " . Dumper($list);
590             }
591            
592 13         19 $VarClassSerial++;
593 13         57 $options{varclass} = sprintf("PkgConfig::Vars::SERIAL_%d", $VarClassSerial);
594 13         49 $options{udefclass} = sprintf("PkgConfig::UDefs::SERIAL_%d", $VarClassSerial);
595 13         31 $options{original} = \%original;
596            
597            
598 13   50     74 my $udefs = delete $options{VARS} || {};
599            
600 13         53 while (my ($k,$v) = each %$udefs) {
601 10     10   63 no strict 'refs';
  10         17  
  10         8217  
602 0         0 my $vname = join('::', $options{udefclass}, $k);
603 0         0 ${$vname} = $v;
  0         0  
604             }
605            
606 13         279 my $o = $cls->new(%options);
607            
608 13         2569 my @libraries;
609 13 50       55 if(ref $library eq 'ARRAY') {
610 0         0 @libraries = @$library;
611             } else {
612 13         33 @libraries = ($library);
613             }
614            
615 13 100       36 if($options{file_path}) {
616            
617 2 100       36 if(-r $options{file_path}) {
618 1         24 $o->recursion(1);
619 1         15 $o->parse_pcfile($options{file_path});
620 1         14 $o->recursion(0);
621             } else {
622 1         26 $o->errmsg("No such file $options{file_path}\n");
623             }
624            
625             } else {
626            
627 11         19 foreach my $lib (@libraries) {
628 11         189 $o->recursion(0);
629 11         77 my($op,$ver);
630 11 50       55 ($lib,$op,$ver) = ($1,$2,PkgConfig::Version->new($3))
631             if $lib =~ /^(.*)\s+(!=|=|>=|<=|>|<)\s+(.*)$/;
632 11         51 $o->find_pcfile($lib);
633            
634 11 50 66     218 if(!$o->errmsg && defined $op) {
635 0 0       0 $op = '==' if $op eq '=';
636 0 0       0 unless(eval qq{ PkgConfig::Version->new(\$o->pkg_version) $op \$ver })
637             {
638 0 0       0 $o->errmsg("Requested '$lib $op $ver' but version of $lib is " .
639             ($o->pkg_version ? $o->pkg_version : '') . "\n");
640             }
641             }
642             }
643             }
644            
645 13         180 $o;
646             }
647              
648             ################################################################################
649             ################################################################################
650             ### Modify our flags stack ###
651             ################################################################################
652             ################################################################################
653             sub append_ldflags {
654 12     12 0 26 my ($self,@flags) = @_;
655 12         21 my @ld_flags = _split_flags(@flags);
656            
657 12         31 foreach my $ldflag (@ld_flags) {
658 26 50       60 next unless $ldflag =~ /^-Wl/;
659              
660 0         0 my (@wlflags) = split(/,/, $ldflag);
661 0         0 shift @wlflags; #first is -Wl,
662 0         0 filter_omit(\@wlflags, $self->exclude_ldflags);
663            
664 0 0       0 if(!@wlflags) {
665 0         0 $ldflag = "";
666 0         0 next;
667             }
668            
669 0         0 $ldflag = join(",", '-Wl', @wlflags);
670             }
671            
672 12         29 @ld_flags = grep $_, @ld_flags;
673 12 100       25 return unless @ld_flags;
674            
675 11   100     16 push @{($self->libs_deplist->{$self->recursion} ||=[])},
  11         156  
676             @ld_flags;
677             }
678              
679             # notify us about extra compiler flags
680             sub append_cflags {
681 12     12 0 27 my ($self,@flags) = @_;
682 12         13 push @{$self->cflags}, _split_flags(@flags);
  12         156  
683             }
684              
685              
686             ################################################################################
687             ################################################################################
688             ### All sorts of parsing is here ###
689             ################################################################################
690             ################################################################################
691             sub get_requires {
692 22     22 0 37 my ($self,$requires) = @_;
693 22 100       48 return () unless $requires;
694              
695 2         7 my @reqlist = split(/[\s,]+/, $requires);
696 2         3 my @ret;
697 2         5 while (defined (my $req = shift @reqlist) ) {
698 2         4 my $reqlet = [ $req ];
699 2         4 push @ret, $reqlet;
700 2 50       4 last unless @reqlist;
701             #check if we need some version scanning:
702              
703 0         0 my $cmp_op;
704             my $want;
705              
706             GT_PARSE_REQ:
707             {
708             #all in one word:
709 0         0 ($cmp_op) = ($req =~ /([<>=]+)/);
  0         0  
710 0 0       0 if($cmp_op) {
    0          
711 0 0       0 if($req =~ /[<>=]+$/) {
712 0         0 log_debug("comparison operator spaced ($cmp_op)");
713 0         0 ($want) = ($req =~ /([^<>=]+$)/);
714 0   0     0 $want ||= shift @reqlist;
715             } else {
716 0         0 $want = shift @reqlist;
717             }
718 0         0 push @$reqlet, ($cmp_op, $want);
719             } elsif ($reqlist[0] =~ /[<>=]+/) {
720 0         0 $req = shift @reqlist;
721 0         0 goto GT_PARSE_REQ;
722             }
723             }
724             }
725             #log_debug(@ret);
726 2         4 @ret;
727             }
728              
729              
730             sub parse_line {
731 129     129 0 209 my ($self,$line,$evals) = @_;
732 10     10   69 no strict 'vars';
  10         19  
  10         19016  
733              
734 129         184 $line =~ s/#[^#]+$//g; # strip comments
735 129 100       198 return unless $line;
736            
737 118         332 my ($tok) = ($line =~ /([=:])/);
738            
739 118         333 my ($field,$value) = split(/[=:]/, $line, 2);
740 118 50       202 return unless defined $value;
741            
742 118 100       308 if($tok eq '=') {
743 56         911 $self->defined_variables->{$field} = $value;
744             }
745            
746             #strip trailing/leading whitespace:
747 118         790 $field =~ s/(^\s+)|(\s+)$//msg;
748            
749             #remove trailing/leading whitespace from value
750 118         597 $value =~ s/(^\s+)|(\s+$)//msg;
751              
752 118         249 log_debugf("Field %s, Value %s", $field, $value);
753            
754 118         177 $field = lc($field);
755            
756             #perl variables can't have '.' in them:
757 118         183 $field =~ s/\./DOT/g;
758            
759             #remove quotes from field names
760 118         151 $field =~ s/['"]//g;
761            
762              
763             # pkg-config escapes a '$' with a '$$'. This won't go in perl:
764 118         166 $value =~ s/[^\\]\$\$/\\\$/g;
765 118         149 $value =~ s/([@%&])/\$1/g;
766            
767            
768             # append our pseudo-package for persistence.
769 118         1602 my $varclass = $self->varclass;
770 118         831 $value =~ s/(\$\{[^}]+\})/lc($1)/ge;
  49         153  
771            
772 118         250 $value =~ s/\$\{/\$\{$varclass\::/g;
773            
774             # preserve quoted space
775 118 100       244 $value = join ' ', map { s/(["'])/\\$1/g; "'$_'" } shellwords $value
  10         436  
  10         27  
776             if $value =~ /[\\"']/;
777            
778             #quote the value string, unless quoted already
779 118         216 $value = "\"$value\"";
780            
781             #get existent variables from our hash:
782            
783            
784             #$value =~ s/'/"/g; #allow for interpolation
785 118         212 $self->assign_var($field, $value);
786            
787             }
788              
789             sub parse_pcfile {
790 11     11 0 24 my ($self,$pcfile,$wantversion) = @_;
791             #log_warn("Requesting $pcfile");
792 11 50       419 open my $fh, "<", $pcfile or die "$pcfile: $!";
793            
794 11         47 $self->prepare_vars();
795            
796 11         378 my @lines = (<$fh>);
797 11         98 close($fh);
798            
799 11         47 my $text = join("", @lines);
800 11         33 $text =~ s,\\[\r\n],,g;
801 11         86 @lines = split(/[\r\n]/, $text);
802            
803 11         19 my @eval_strings;
804            
805             #Fold lines:
806            
807 11         526 my $pcfiledir = dirname $pcfile;
808 11         29 $pcfiledir =~ s{\\}{/}g;
809              
810 11         36 foreach my $line ("pcfiledir=$pcfiledir", @lines) {
811 129         267 $self->parse_line($line, \@eval_strings);
812             }
813            
814             #now that we have eval strings, evaluate them all within the same
815             #lexical scope:
816            
817              
818 11         29 $self->append_cflags( $self->_pc_var('cflags') );
819 11 50       158 if($self->static) {
820 0         0 $self->append_cflags( $self->_pc_var('cflags.private') );
821             }
822 11         83 $self->append_ldflags( $self->_pc_var('libs') );
823 11 50       298 if($self->static) {
824 0         0 $self->append_ldflags( $self->_pc_var('libs.private') );
825             }
826              
827 11         69 my @deps;
828 11         24 my @deps_dynamic = $self->get_requires( $self->_pc_var('requires'));
829 11         22 my @deps_static = $self->get_requires( $self->_pc_var('requires.private') );
830 11         16 @deps = @deps_dynamic;
831              
832              
833 11 50       138 if($self->static) {
834 0         0 push @deps, @deps_static;
835             }
836              
837 11 50 33     178 if($self->recursion == 1 && (!$self->pkg_exists())) {
838 11         294 $self->pkg_version( $self->_pc_var('version') );
839 11         73 $self->pkg_url( $self->_pc_var('url') );
840 11         88 $self->pkg_description( $self->_pc_var('description') );
841 11         171 $self->pkg_exists(1);
842             }
843              
844 11 50       172 unless ($self->no_recurse) {
845 11         98 foreach (@deps) {
846 2         6 my ($dep,$cmp_op,$version) = @$_;
847 2 50       4 $dep = "$dep $cmp_op $version" if defined $cmp_op;
848 2         3 my $other = PkgConfig->find($dep, %{ $self->original });
  2         24  
849 2 100       28 if($other->errmsg) {
850 1         18 $self->errmsg($other->errmsg);
851 1         14 last;
852             }
853 1         9 $self->append_cflags( $other->get_cflags );
854 1         3 $self->append_ldflags( $other->get_ldflags );
855             }
856             }
857             }
858              
859              
860             ################################################################################
861             ################################################################################
862             ### Locate and process a .pc file ###
863             ################################################################################
864             ################################################################################
865             sub find_pcfile {
866 11     11 0 25 my ($self,$libname,$version) = @_;
867              
868 11         161 $self->recursion($self->recursion + 1);
869              
870 11         109 my $pcfile = "$libname.pc";
871 11         15 my $found = 0;
872             my @found_paths = (grep {
873 77         1462 -e File::Spec->catfile($_, $pcfile)
874 11         15 } @{$self->search_path});
  11         129  
875              
876 11 100       41 if(!@found_paths) {
877 1         3 my @search_paths = @{$self->search_path};
  1         19  
878 1 50       19 $self->errmsg(
879             join("\n",
880             "Can't find $pcfile in any of @search_paths",
881             "use the PKG_CONFIG_PATH environment variable, or",
882             "specify extra search paths via 'search_paths'",
883             ""
884             )
885             ) unless $self->errmsg();
886 1         30 return;
887             }
888              
889 10         67 $pcfile = File::Spec->catfile($found_paths[0], $pcfile);
890              
891 10         39 $self->parse_pcfile($pcfile);
892              
893 10         150 $self->recursion($self->recursion - 1);
894             }
895              
896             ################################################################################
897             ################################################################################
898             ### Public Getters ###
899             ################################################################################
900             ################################################################################
901              
902             sub _return_context (@) {
903 18 100   18   98 wantarray ? (@_) : join(' ', map { s/(\s|['"])/\\$1/g; $_ } @_)
  12         55  
  12         37  
904             }
905              
906             sub get_cflags {
907 15     15 1 4845 my $self = shift;
908 15         17 my @cflags = @{$self->cflags};
  15         269  
909              
910 15         264 filter_omit(\@cflags, $self->exclude_cflags);
911 15         70 filter_dups(\@cflags);
912 15         27 _return_context @cflags;
913             }
914              
915             sub get_ldflags {
916 3     3 1 7 my $self = shift;
917 3         5 my @ordered_libs;
918 3         4 my @lib_levels = sort keys %{$self->libs_deplist};
  3         52  
919 3         38 my @ret;
920              
921 3         6 @ordered_libs = @{$self->libs_deplist}{@lib_levels};
  3         36  
922 3         40 foreach my $liblist (@ordered_libs) {
923 3         11 my $lcopy = [ @$liblist ];
924 3         9 filter_dups($lcopy);
925 3         46 filter_omit($lcopy, $self->exclude_ldflags);
926 3         9 push @ret, @$lcopy;
927             }
928              
929 3         7 @ret = reverse @ret;
930 3         24 filter_dups(\@ret);
931 3         5 @ret = reverse(@ret);
932 3         8 _return_context @ret;
933             }
934              
935             sub get_var {
936 2     2 1 1269 my($self, $name) = @_;
937 2         8 $self->_pc_var($name);
938             }
939              
940             sub get_list {
941 0     0 0 0 my $self = shift;
942 0         0 my @search_paths = @{$self->search_path};
  0         0  
943 0         0 my @rv = ();
944 0         0 $self->recursion(0);
945 0         0 for my $d (@search_paths) {
946 0 0       0 next unless -d $d;
947 0         0 for my $pc (bsd_glob("$d/*.pc")) {
948 0 0       0 if ($pc =~ m|/([^\\\/]+)\.pc$|) {
949 0         0 $self->parse_pcfile($pc);
950 0         0 push @rv, [$1, $self->_pc_var('name') . ' - ' . $self->_pc_var('description')];
951             }
952             }
953             }
954 0         0 @rv;
955             }
956              
957              
958             ################################################################################
959             ################################################################################
960             ### Utility functions ###
961             ################################################################################
962             ################################################################################
963              
964             #split a list of tokens by spaces
965             sub _split_flags {
966 24     24   114 my @flags = @_;
967 24 50       64 if(!@flags) {
968 0         0 return @flags;
969             }
970 24 100       49 if(@flags == 1) {
971 23         34 my $str = shift @flags;
972 23 100       41 return () if !$str;
973             #@flags = map { s/\\(\s)/$1/g; $_ } split(/(?
974 21         39 @flags = shellwords $str;
975             }
976 22         1288 @flags = grep $_, @flags;
977 22         48 @flags;
978             }
979              
980              
981              
982             sub filter_dups {
983 21     21 0 32 my $array = shift;
984 21         24 my @ret;
985             my %seen_hash;
986             #@$array = reverse @$array;
987 21         33 foreach my $elem (@$array) {
988 59 50       96 if(exists $seen_hash{$elem}) {
989 0         0 next;
990             }
991 59         82 $seen_hash{$elem} = 1;
992 59         78 push @ret, $elem;
993             }
994             #print Dumper(\%seen_hash);
995 21         54 @$array = @ret;
996             }
997              
998             sub filter_omit {
999 18     18 0 112 my ($have,$exclude) = @_;
1000 18         20 my @ret;
1001             #print Dumper($have);
1002 18         38 foreach my $elem (@$have) {
1003             #log_warn("Checking '$elem'");
1004 44 50       56 if(grep { $_ eq $elem } @$exclude) {
  388         518  
1005             #log_warn("Found illegal flag '$elem'");
1006 0         0 next;
1007             }
1008 44         70 push @ret, $elem;
1009             }
1010 18         47 @$have = @ret;
1011             }
1012              
1013             sub version_2_array {
1014 0     0 0 0 my $string = shift;
1015 0         0 my @chunks = split(/\./, $string);
1016 0         0 my @ret;
1017             my $chunk;
1018 0   0     0 while( ($chunk = pop @chunks)
1019             && $chunk =~ /^\d+$/) {
1020 0         0 push @ret, $chunk;
1021             }
1022 0         0 @ret;
1023             }
1024              
1025              
1026             sub version_check {
1027 0     0 0 0 my ($want,$have) = @_;
1028 0         0 my @a_want = version_2_array($want);
1029 0         0 my @a_have = version_2_array($have);
1030              
1031 0 0       0 my $max_elem = scalar @a_want > scalar @a_have
1032             ? scalar @a_have
1033             : scalar @a_want;
1034              
1035 0         0 for(my $i = 0; $i < $max_elem; $i++) {
1036 0 0       0 if($a_want[$i] > $a_have[$i]) {
1037 0         0 return 0;
1038             }
1039             }
1040 0         0 1;
1041             }
1042              
1043              
1044             if(caller) {
1045             return 1;
1046             }
1047              
1048             package
1049             PkgConfig::Version;
1050              
1051             use overload
1052 8     8   19 '<=>' => sub { $_[0]->cmp($_[1]) },
1053 0     0   0 '""' => sub { $_[0]->as_string },
1054 10     10   6315 fallback => 1;
  10         5003  
  10         95  
1055              
1056             sub new {
1057 6     6   95 my($class, $value) = @_;
1058 6 50       32 bless [split /\./, defined $value ? $value : ''], $class;
1059             }
1060              
1061             sub clone {
1062 3     3   10 __PACKAGE__->new(shift->as_string);
1063             }
1064              
1065             sub as_string {
1066 3     3   6 my($self) = @_;
1067 3         4 join '.', @{ $self };
  3         29  
1068             }
1069              
1070             sub cmp {
1071 32     32   44 my($self, $other) = @_;
1072 10     10   1982 no warnings 'uninitialized';
  10         22  
  10         1099  
1073 32 100 100     155 defined($self->[0]) || defined($other->[0]) ? ($self->[0] <=> $other->[0]) || &cmp([@{$self}[1..$#$self]], [@{$other}[1..$#$other]]) : 0;
      100        
1074             }
1075              
1076             ################################################################################
1077             ################################################################################
1078             ################################################################################
1079             ################################################################################
1080             ### Script-Only stuff ###
1081             ################################################################################
1082             ################################################################################
1083             ################################################################################
1084             ################################################################################
1085             package PkgConfig::Script;
1086 10     10   61 use strict;
  10         15  
  10         393  
1087 10     10   51 use warnings;
  10         18  
  10         336  
1088 10     10   7771 use Getopt::Long qw(:config no_ignore_case);
  10         88910  
  10         39  
1089 10     10   6743 use Pod::Usage;
  10         419313  
  10         12624  
1090              
1091             my $quiet_errors = 1;
1092             my @ARGV_PRESERVE = @ARGV;
1093              
1094             my @POD_USAGE_SECTIONS = (
1095             "NAME",
1096             'DESCRIPTION/SCRIPT OPTIONS/USAGE',
1097             "DESCRIPTION/SCRIPT OPTIONS/ARGUMENTS|ENVIRONMENT",
1098             "AUTHOR & COPYRIGHT"
1099             );
1100              
1101             my @POD_USAGE_OPTIONS = (
1102             -verbose => 99,
1103             -sections => \@POD_USAGE_SECTIONS
1104             );
1105              
1106             GetOptions(
1107             'libs' => \my $PrintLibs,
1108             'libs-only-L' => \my $PrintLibsOnlyL,
1109             'libs-only-l' => \my $PrintLibsOnlyl,
1110             'libs-only-other' => \my $PrintLibsOnlyOther,
1111             'list-all' => \my $ListAll,
1112             'static' => \my $UseStatic,
1113             'cflags' => \my $PrintCflags,
1114             'cflags-only-I' => \my $PrintCflagsOnlyI,
1115             'cflags-only-other' => \my $PrintCflagsOnlyOther,
1116             'exists' => \my $PrintExists,
1117             'atleast-version=s' => \my $AtLeastVersion,
1118             'atleast-pkgconfig-version=s' => \my $AtLeastPkgConfigVersion,
1119             'exact-version=s' => \my $ExactVersion,
1120             'max-version=s' => \my $MaxVersion,
1121              
1122             'silence-errors' => \my $SilenceErrors,
1123             'print-errors' => \my $PrintErrors,
1124             'errors-to-stdout' => \my $ErrToStdOut,
1125             'short-errors' => \my $ShortErrors,
1126            
1127             'define-variable=s', => \my %UserVariables,
1128            
1129             'print-variables' => \my $PrintVariables,
1130             'print-values' => \my $PrintValues,
1131             'variable=s', => \my $OutputVariableValue,
1132            
1133             'modversion' => \my $PrintVersion,
1134             'version', => \my $PrintAPIversion,
1135             'real-version' => \my $PrintRealVersion,
1136            
1137             'debug' => \my $Debug,
1138             'with-path=s', => \my @ExtraPaths,
1139             'env-only', => \my $EnvOnly,
1140             'guess-paths', => \my $GuessPaths,
1141            
1142             'h|help|?' => \my $WantHelp
1143             ) or pod2usage(@POD_USAGE_OPTIONS);
1144              
1145             if($^O eq 'msys' && !$ENV{PKG_CONFIG_NO_OS_CUSTOMIZATION}) {
1146             $UseStatic = 1;
1147             }
1148              
1149             if($WantHelp) {
1150             pod2usage(@POD_USAGE_OPTIONS, -exitval => 0);
1151             }
1152              
1153             if($Debug) {
1154             eval {
1155             Log::Fu::set_log_level('PkgConfig', 'DEBUG');
1156             };
1157             $PkgConfig::UseDebugging = 1;
1158             }
1159              
1160             if($GuessPaths) {
1161             PkgConfig->GuessPaths();
1162             }
1163              
1164             if($PrintAPIversion) {
1165             print '0.', $compat_version, "\n";
1166             exit(0);
1167             }
1168              
1169             if($AtLeastPkgConfigVersion) {
1170             my($major,$minor,$patch) = split /\./, $AtLeastPkgConfigVersion;
1171             exit 1 if $major > 0;
1172             exit 1 if $minor > $compat_version;
1173             exit 1 if $minor == $compat_version && $patch > 0;
1174             exit 0;
1175             }
1176              
1177             if($PrintRealVersion) {
1178              
1179             printf STDOUT ("ppkg-config - cruftless pkg-config\n" .
1180             "Version: %s\n", $PkgConfig::VERSION);
1181             exit(0);
1182             }
1183              
1184             if($PrintErrors) {
1185             $quiet_errors = 0;
1186             }
1187              
1188             if($SilenceErrors) {
1189             $quiet_errors = 1;
1190             }
1191              
1192             # This option takes precedence over all other options
1193             # be it:
1194             # --silence-errors
1195             # or
1196             # --print-errors
1197             if ($ErrToStdOut) {
1198             $quiet_errors = 2;
1199             }
1200              
1201             my $WantFlags = ($PrintCflags || $PrintLibs || $PrintLibsOnlyL || $PrintCflagsOnlyI || $PrintCflagsOnlyOther || $PrintLibsOnlyOther || $PrintLibsOnlyl || $PrintVersion);
1202              
1203             if($WantFlags) {
1204             $quiet_errors = 0 unless $SilenceErrors;
1205             }
1206              
1207             my %pc_options;
1208             if($PrintExists || $AtLeastVersion || $ExactVersion || $MaxVersion || $PrintVersion) {
1209             $pc_options{no_recurse} = 1;
1210             }
1211              
1212              
1213             $pc_options{static} = $UseStatic;
1214             $pc_options{search_path} = \@ExtraPaths;
1215              
1216             if($EnvOnly) {
1217             delete $pc_options{search_path};
1218             $pc_options{search_path_override} = [ @ExtraPaths, @ENV_SEARCH_PATH];
1219             }
1220              
1221             $pc_options{print_variables} = $PrintVariables;
1222             $pc_options{print_values} = $PrintValues;
1223             $pc_options{VARS} = \%UserVariables;
1224              
1225             if($ListAll) {
1226             my $o = PkgConfig->find([], %pc_options);
1227             my @list = $o->get_list();
1228            
1229             # can't use List::Util::max as it wasn't core until Perl 5.8
1230             my $max_length = 0;
1231             foreach my $length (map { length $_->[0] } @list) {
1232             $max_length = $length if $length > $max_length;
1233             }
1234              
1235             printf "%-${max_length}s %s\n", $_->[0], $_->[1] for @list;
1236             exit(0);
1237             }
1238              
1239             my @FINDLIBS = @ARGV or die "Must specify at least one library";
1240              
1241             if($AtLeastVersion) {
1242             @FINDLIBS = map { "$_ >= $AtLeastVersion" } @FINDLIBS;
1243             } elsif($MaxVersion) {
1244             @FINDLIBS = map { "$_ <= $MaxVersion" } @FINDLIBS;
1245             } elsif($ExactVersion) {
1246             @FINDLIBS = map { "$_ = $ExactVersion" } @FINDLIBS;
1247             }
1248              
1249             my $o = PkgConfig->find(\@FINDLIBS, %pc_options);
1250              
1251             if($o->errmsg) {
1252             # --errors-to-stdout
1253             if ($quiet_errors eq 2) {
1254             print STDOUT $o->errmsg;
1255             # --print-errors
1256             } elsif ($quiet_errors eq 1) {
1257             print STDERR $o->errmsg;
1258             }
1259             # --silence-errors
1260             exit(1);
1261             }
1262              
1263             if($o->print_variables) {
1264             while (my ($k,$v) = each %{$o->defined_variables}) {
1265             print $k;
1266             if($o->print_values) {
1267             print "=$v";
1268             } else {
1269             print "\n";
1270             }
1271             }
1272             }
1273              
1274             if($OutputVariableValue) {
1275             my $val = ($o->_pc_var($OutputVariableValue) or "");
1276             print $val . "\n";
1277             }
1278              
1279             if(!$WantFlags) {
1280             exit(0);
1281             }
1282              
1283             if($PrintVersion) {
1284             print $o->pkg_version . "\n";
1285             exit(0);
1286             }
1287              
1288             my @print_flags;
1289              
1290             if($PrintCflags) {
1291             @print_flags = $o->get_cflags;
1292             }
1293              
1294             if($PrintCflagsOnlyI) {
1295             @print_flags = grep /^-I/, $o->get_cflags;
1296             }
1297              
1298             if($PrintCflagsOnlyOther) {
1299             @print_flags = grep /^-[^I]/, $o->get_cflags;
1300             }
1301              
1302             if($PrintLibs) {
1303             @print_flags = $o->get_ldflags;
1304             }
1305              
1306             if ($PrintLibsOnlyOther) {
1307             @print_flags = grep /^-[^LRl]/, $o->get_ldflags;
1308             }
1309              
1310             # handle --libs-only-L and --libs-only-l but watch the case when
1311             # we got 'ppkg-config --libs-only-L --libs-only-l foo' which must behave just like
1312             # 'ppkg-config --libs-only-l foo'
1313              
1314             if($PrintLibsOnlyl or ($PrintLibsOnlyl and $PrintLibsOnlyL)) {
1315             @print_flags = grep /^-l/, $o->get_ldflags;
1316             } elsif ($PrintLibsOnlyL) {
1317             @print_flags = grep /^-[LR]/, $o->get_ldflags;
1318             }
1319              
1320             print scalar PkgConfig::_return_context(@print_flags);
1321             print "\n";
1322             exit(0);
1323              
1324             __END__