[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.11

1.1       ckuethe     1: #!/usr/bin/perl
1.11    ! espie       2: # $OpenBSD: pkg-config,v 1.10 2006/12/01 19:32:31 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 {
        !           205:                print STDERR $@, "\n" if $@;
        !           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: }