[BACK]Return to pkg-config CVS log [TXT][DIR] Up to [local] / src / usr.bin / pkg-config

Annotation of src/usr.bin/pkg-config/pkg-config, Revision 1.12

1.1       ckuethe     1: #!/usr/bin/perl
1.12    ! espie       2: # $OpenBSD: pkg-config,v 1.11 2006/12/02 18:28:22 espie Exp $
1.1       ckuethe     3:
                      4: #$CSK: pkgconfig.pl,v 1.39 2006/11/27 16:26:20 ckuethe Exp $
                      5: # Copyright (c) 2006 Chris Kuethe <ckuethe@openbsd.org>
                      6: #
                      7: # Permission to use, copy, modify, and distribute this software for any
                      8: # purpose with or without fee is hereby granted, provided that the above
                      9: # copyright notice and this permission notice appear in all copies.
                     10: #
                     11: # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     12: # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     13: # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     14: # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     15: # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     16: # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     17: # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     18:
                     19: use strict;
                     20: use warnings;
                     21: use Getopt::Long;
1.4       espie      22: use File::Basename;
1.11      espie      23: use OpenBSD::PkgConfig;
1.1       ckuethe    24:
                     25: my @PKGPATH = qw(/usr/local/lib/pkgconfig /usr/X11R6/lib/pkgconfig );
                     26:
1.4       espie      27: if (defined($ENV{'PKG_CONFIG_PATH'}) && $ENV{'PKG_CONFIG_PATH'}) {
                     28:        push(@PKGPATH, split /:/, $ENV{'PKG_CONFIG_PATH'});
1.1       ckuethe    29: }
                     30:
                     31: my $logfile = '';
1.4       espie      32: if (defined($ENV{'PKG_CONFIG_LOGFILE'}) && $ENV{'PKG_CONFIG_LOGFILE'}) {
1.1       ckuethe    33:        $logfile = $ENV{'PKG_CONFIG_LOGFILE'};
                     34: }
                     35:
1.10      espie      36: my $version = 0.19; # pretend to be this version of pkgconfig
                     37:
                     38: my %configs = ();
1.11      espie      39: my $cfg_list = [];
1.10      espie      40: my %mode = ();
1.11      espie      41: my $variables = {};
1.10      espie      42: my $D = 0; # debug flag
1.1       ckuethe    43:
1.7       ckuethe    44: # defaults
1.11      espie      45: $mode{printerr} = 1;
1.7       ckuethe    46:
1.4       espie      47: if ($logfile) {
                     48:        open my $L, ">>" . $logfile;
                     49:        print $L '[' . join('] [', $0, @ARGV) . "]\n";
                     50:        close $L;
1.1       ckuethe    51: }
                     52:
                     53: # combo arg-parsing and dependency resolution loop. Hopefully when the loop
                     54: # terminates, we have a full list of packages upon which we depend, and the
                     55: # right set of compiler and linker flags to use them.
                     56: #
                     57: # as each .pc file is loaded, it is stored in %configs, indexed by package
                     58: # name. this makes it possible to then pull out flags or do substitutions
                     59: # without having to go back and reload the files from disk
                     60:
                     61: Getopt::Long::Configure('no_ignore_case');
                     62: GetOptions(    'debug' => \$D,
                     63:                'help' => \&help, #does not return
                     64:                'usage' => \&help, #does not return
                     65:                'list-all' => \&do_list, #does not return
                     66:                'version' => sub { print "$version\n" ; exit(0);} ,
1.11      espie      67:                'errors-to-stdout' => sub { $mode{estdout} = 1},
                     68:                'print-errors' => sub { $mode{printerr} = 1},
                     69:                'silence-errors' => sub { $mode{printerr} = 0},
                     70:                'atleast-pkgconfig-version=s' => \$mode{minvers},
                     71:
                     72:                'cflags' => sub { $mode{cflags} = 3},
                     73:                'cflags-only-I' => sub { $mode{cflags} |= 1},
                     74:                'cflags-only-other' => sub { $mode{cflags} |= 2},
                     75:                'libs' => sub { $mode{libs} = 7},
                     76:                'libs-only-l' => sub { $mode{libs} |= 1},
                     77:                'libs-only-L' => sub { $mode{libs} |= 2},
                     78:                'libs-only-other' => sub { $mode{libs} |= 4},
                     79:                'exists' => sub { $mode{exists} = 1} ,
                     80:                'static' => sub { $mode{static} = 1},
                     81:                'uninstalled' => sub { $mode{uninstalled} = 1},
1.1       ckuethe    82:                'atleast-version=s' => \$mode{'atleast-version'},
1.11      espie      83:                'modversion:s' => \$mode{modversion},
                     84:                'variable=s' => \$mode{variable},
                     85:                'define-variable=s' => $variables,
1.1       ckuethe    86:        );
                     87:
1.4       espie      88: print STDERR "\n[" . join('] [', $0, @ARGV) . "]\n" if $D;
1.11      espie      89: self_version($mode{minvers}) if $mode{minvers}; #does not return
                     90: if (defined $mode{modversion}) {
                     91:        if ($mode{modversion}) {
                     92:                do_modversion($mode{modversion}) ; #does not return
1.6       ckuethe    93:        } else {
                     94:                print $version . "\n";
                     95:                exit 0;
                     96:        }
                     97: }
1.1       ckuethe    98:
1.10      espie      99: {
                    100: my $p = join(' ', @ARGV);
1.1       ckuethe   101: $p =~ s/\s+/ /g;
                    102: $p =~ s/^\s//g;
1.4       espie     103: @ARGV = split /\s+/, $p;
1.10      espie     104: }
1.1       ckuethe   105:
1.11      espie     106: if (defined $mode{exists}) {
1.4       espie     107:        while (@ARGV) {
1.1       ckuethe   108:                if ((@ARGV >= 2)  && ($ARGV[1] =~ /[<=>]+/) &&
1.4       espie     109:                    ($ARGV[2] =~ /[0-9\.]+/)) {
                    110:                        exit 1 unless versionmatch(@ARGV);
                    111:                        shift @ARGV; shift @ARGV; shift @ARGV;
1.1       ckuethe   112:                } else {
1.4       espie     113:                        exit 1 unless pathresolve($ARGV[0]);
                    114:                        shift @ARGV;
1.1       ckuethe   115:                }
                    116:        }
1.4       espie     117:        exit 0;
1.1       ckuethe   118: }
                    119:
1.11      espie     120: do_variable($ARGV[0], $mode{variable}) if $mode{variable};
1.1       ckuethe   121:
                    122: while (@ARGV){
1.10      espie     123:        my $p = $ARGV[0];
1.1       ckuethe   124:        if ((@ARGV >= 2)  && ($ARGV[1] =~ /[<=>]+/) &&
1.4       espie     125:            ($ARGV[2] =~ /[0-9\.]+/)) {
                    126:                shift @ARGV;
                    127:                shift @ARGV;
1.1       ckuethe   128:        }
1.4       espie     129:        shift @ARGV;
1.1       ckuethe   130:        $p =~ s/,//g;
1.11      espie     131:        handle_config($p);
                    132: }
1.1       ckuethe   133:
1.11      espie     134: if ($mode{cflags} || $mode{libs}) {
                    135:     my @l = ();
                    136:     push @l, do_cflags() if $mode{cflags};
                    137:     push @l, do_libs() if $mode{libs};
                    138:     print join(' ', @l), "\n";
1.1       ckuethe   139: }
                    140:
1.4       espie     141: exit 0;
1.1       ckuethe   142:
                    143: ###########################################################################
                    144:
1.11      espie     145: sub handle_config
                    146: {
                    147:        my $p = shift;
                    148:
                    149:        return if $configs{$p};
                    150:
                    151:        print STDERR "processing $p\n" if $D;
                    152:        my $cfg = find_config($p);
                    153:
                    154:        if (!defined $cfg) {
                    155:                warn "can't find $p\n" if $mode{printerr};
                    156:                exit 1;
                    157:        }
                    158:        return undef if defined $mode{exists};
                    159:
                    160:        push(@$cfg_list, $p);
                    161:        $configs{$p} = $cfg;
                    162:
                    163:        my $deps = $cfg->get_property('Requires', $variables);
                    164:        if (defined $deps) {
                    165:                # XXX don't handle version yet
                    166:                map { s/\s*[<=>]+\s*[\d\.]+//; handle_config($_) } @$deps;
                    167:                print STDERR "package $p requires ",
                    168:                    join(',', @$deps), "\n" if $D;
                    169:        }
                    170:
                    171:        $deps = $cfg->get_property('Requires.private', $variables);
                    172:        if (defined $deps) {
                    173:                # XXX don't handle version yet
                    174:                map { s/\s*[<=>]+\s*[\d\.]+//; handle_config($_) } @$deps;
                    175:                print STDERR "package $p requires (private)",
                    176:                        join(',', @$deps), "\n" if $D;
                    177:        }
                    178: }
                    179:
1.1       ckuethe   180: # look for the .pc file in each of the PKGPATH elements. Return the path or
                    181: # undef if it's not there
1.4       espie     182: sub pathresolve
                    183: {
                    184:        my ($p) = @_;
                    185:
                    186:        foreach my $d (@PKGPATH) {
1.10      espie     187:                my $f = "$d/$p.pc";
1.4       espie     188:                print STDERR "pathresolve($p) looking in $f\n" if $D;
1.10      espie     189:                return $f if -f $f;
1.1       ckuethe   190:        }
1.10      espie     191:        return undef;
1.1       ckuethe   192: }
                    193:
1.11      espie     194: sub get_config
                    195: {
                    196:        my ($f) = @_;
                    197:
                    198:        my $cfg;
                    199:        eval {
                    200:            $cfg = OpenBSD::PkgConfig->read_file($f);
                    201:        };
                    202:        if (!$@) {
                    203:                return $cfg;
                    204:        } else {
1.12    ! espie     205:                print STDERR $@, "\n" if $D;
1.11      espie     206:        }
                    207:        return undef;
                    208: }
                    209:
                    210: sub find_config
                    211: {
                    212:        my ($p) = @_;
                    213:        my $f = pathresolve($p);
                    214:        if (defined $f) {
                    215:                return get_config($f);
                    216:        }
                    217:        return undef;
                    218: }
1.1       ckuethe   219:
1.11      espie     220: sub stringize
1.4       espie     221: {
1.11      espie     222:        my $list = shift;
1.4       espie     223:
1.11      espie     224:        if (defined $list) {
                    225:                return join(',', @$list)
                    226:        } else {
                    227:                return '';
1.1       ckuethe   228:        }
                    229: }
                    230:
                    231: #if the variable option is set, pull out the named variable
1.4       espie     232: sub do_variable
                    233: {
1.11      espie     234:        my ($p, $v) = @_;
1.1       ckuethe   235:
1.11      espie     236:        if (my $cfg = find_config($p)) {
                    237:                my $value = $cfg->get_variable($v, $variables);
                    238:                if (defined $value) {
                    239:                        print $value, "\n";
                    240:                        exit 1;
                    241:                }
                    242:        }
1.4       espie     243:        exit 0;
1.1       ckuethe   244: }
                    245:
                    246: #if the modversion option is set, pull out the compiler flags
1.4       espie     247: sub do_modversion
                    248: {
1.11      espie     249:        my ($p) = @_;
1.1       ckuethe   250:
1.11      espie     251:        if (my $cfg = find_config($p)) {
                    252:                my $value = $cfg->get_property('Version', $variables);
                    253:                if (defined $value) {
                    254:                        print stringize($value), "\n";
                    255:                        exit 1;
                    256:                }
                    257:        }
1.4       espie     258:        exit 0;
1.1       ckuethe   259: }
                    260:
                    261: #if the cflags option is set, pull out the compiler flags
1.4       espie     262: sub do_cflags
                    263: {
1.11      espie     264:        my $cflags = [];
1.1       ckuethe   265:
1.11      espie     266:        foreach my $pkg (@$cfg_list) {
                    267:                my $l = $configs{$pkg}->get_property('Cflags', $variables);
                    268:                push(@$cflags, @$l) if defined $l;
                    269:        }
                    270:        return OpenBSD::PkgConfig->compress($cflags,
                    271:                sub {
                    272:                        local $_ = shift;
                    273:                        if (($mode{cflags} & 1) && /^-I/ ||
                    274:                            ($mode{cflags} & 2) && !/^-I/) {
                    275:                            return 1;
                    276:                        } else {
                    277:                            return 0;
1.4       espie     278:                        }
1.11      espie     279:                });
1.1       ckuethe   280: }
                    281:
                    282: #if the lib option is set, pull out the linker flags
1.4       espie     283: sub do_libs
                    284: {
1.11      espie     285:        my $libs = [];
1.1       ckuethe   286:
1.11      espie     287:        foreach my $pkg (@$cfg_list) {
                    288:                my $l = $configs{$pkg}->get_property('Libs', $variables);
                    289:                push(@$libs, @$l) if defined $l;
                    290:        }
                    291:        return OpenBSD::PkgConfig->compress($libs,
                    292:                sub {
                    293:                        local $_ = shift;
                    294:                        if (($mode{libs} & 1) && /^-l/ ||
                    295:                            ($mode{libs} & 2) && /^-L/ ||
                    296:                            ($mode{libs} & 4) && !/^-[lL]/) {
                    297:                            return 1;
                    298:                        } else {
                    299:                            return 0;
1.4       espie     300:                        }
1.11      espie     301:                });
1.1       ckuethe   302: }
                    303:
                    304: #list all packages
1.4       espie     305: sub do_list
                    306: {
1.1       ckuethe   307:        my ($p, $x, $y, @files, $fname, $name);
1.4       espie     308:        foreach my $p (@PKGPATH) {
                    309:                push(@files, <$p/*.pc>);
                    310:        }
1.1       ckuethe   311:
                    312:        # Scan the lengths of the package names so I can make a format
                    313:        # string to line the list up just like the real pkgconfig does.
                    314:        $x = 0;
1.4       espie     315:        foreach my $f (@files) {
                    316:                $fname = basename($f, '.pc');
                    317:                $y = length $fname;
1.1       ckuethe   318:                $x = (($y > $x) ? $y : $x);
                    319:        }
                    320:        $x *= -1;
                    321:
1.4       espie     322:        foreach my $f (@files) {
1.11      espie     323:                my $cfg = get_config($f);
1.4       espie     324:                $fname = basename($f, '.pc');
1.11      espie     325:                printf("%${x}s %s - %s\n", $fname,
                    326:                    stringize($cfg->get_property('Name', $variables)),
                    327:                    stringize($cfg->get_property('Description', $variables)));
1.1       ckuethe   328:        }
1.4       espie     329:        exit 0;
1.1       ckuethe   330: }
                    331:
1.4       espie     332: sub help
                    333: {
1.1       ckuethe   334:        print <<EOF
                    335: Usage: $0 [options]
                    336: --debug        - turn on debugging output
                    337: --help - this message
                    338: --usage - this message
                    339: --list-all - show all packages that $0 can find
1.8       ckuethe   340: --version - print version of pkgconfig
                    341: --errors-to-stdout - direct error messages to stdout rather than stderr
                    342: --print-errors - print error messages in case of error
                    343: --silence-errors - don't print error messages in case of error
1.1       ckuethe   344: --atleast-pkgconfig-version [version] - require a certain version of pkgconfig
                    345: --cflags package [versionspec] [package [versionspec]]
                    346: --cflags-only-I - only output -Iincludepath flags
                    347: --cflags-only-other - only output flags that are not -I
1.11      espie     348: --define-variable=NAME=VALUE - define variables
1.1       ckuethe   349: --libs package [versionspec] [package [versionspec]]
                    350: --libs-only-l - only output -llib flags
                    351: --libs-only-L - only output -Llibpath flags
                    352: --libs-only-other - only output flags that are not -l or -L
                    353: --exists package [versionspec] [package [versionspec]]
                    354: --uninstalled - allow for uninstalled versions to be used
1.8       ckuethe   355: --static - adjust output for static linking
                    356: --atleast-version [version] - require a certain version of a package
                    357: --modversion [package] - query the version of a package
                    358: --variable var package - return the definition of <var> in <package>
1.1       ckuethe   359: EOF
                    360: ;
1.4       espie     361:        exit 1;
1.1       ckuethe   362: }
                    363:
                    364: # do we meet/beat the version the caller requested?
1.4       espie     365: sub self_version
                    366: {
                    367:        my ($v) = @_;
                    368:        my (@a, @b);
                    369:
                    370:        @a = split /\./, $v;
                    371:        @b = split /\./, $version;
1.1       ckuethe   372:
1.4       espie     373:        if (($b[0] >= $a[0]) && ($b[1] >= $a[1])) {
                    374:                exit 0;
1.1       ckuethe   375:        } else {
1.4       espie     376:                exit 1;
1.1       ckuethe   377:        }
                    378: }
                    379:
                    380: # got a package meeting the requested specific version?
1.4       espie     381: sub versionmatch
                    382: {
1.11      espie     383:        my ($pname, $op, $ver) = @_;
1.1       ckuethe   384:
1.4       espie     385:        print STDERR "pname = '$pname'\n" if  $D;
1.11      espie     386:        my $cfg = find_config($pname);
1.1       ckuethe   387:        # can't possibly match if we can't find the file
1.11      espie     388:        return 0 if !defined $cfg;
                    389:
                    390:        $configs{$pname} = $cfg;
                    391:
                    392:        my $v = stringize($cfg->get_property('Version', $variables));
                    393:
1.1       ckuethe   394:        # can't possibly match if we can't find the version string
1.11      espie     395:        return 0 if $v eq '';
1.1       ckuethe   396:
1.11      espie     397:        print "comparing $ver (wanted) to $v (installed)\n" if $D;
                    398:        my @inst = split /\./, $v;
                    399:        my @want = split /\./, $ver;
1.1       ckuethe   400:
1.4       espie     401:        while (@inst && @want) { #so long as both lists have something
1.1       ckuethe   402:                # bail if the requested version element beats existing
1.4       espie     403:                return 1 if $inst[0] > $want[0];
                    404:                return 0 if $inst[0] < $want[0];
                    405:                shift @inst; shift @want;
1.1       ckuethe   406:        }
                    407:        # the version at least equals the requested. if the requested
                    408:        # version has some micropatchlevel beyond the existing version,
                    409:        # return failure
1.4       espie     410:        return 0 if @want;
1.1       ckuethe   411:        # and after all that, the version is good enough
                    412:        return 1;
                    413: }