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

Annotation of src/usr.bin/libtool/libtool, Revision 1.8

1.1       espie       1: #!/usr/bin/perl
1.8     ! espie       2: # $OpenBSD: libtool,v 1.7 2012/06/28 18:24:42 espie Exp $
1.1       espie       3:
                      4: # Copyright (c) 2007-2010 Steven Mestdagh <steven@openbsd.org>
                      5: #
                      6: # Permission to use, copy, modify, and distribute this software for any
                      7: # purpose with or without fee is hereby granted, provided that the above
                      8: # copyright notice and this permission notice appear in all copies.
                      9: #
                     10: # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11: # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12: # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13: # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14: # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     15: # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     16: # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:
                     18: use strict;
                     19: use warnings;
                     20: use feature qw(say switch state);
                     21: use Cwd qw(getcwd abs_path);
                     22: use File::Basename;
                     23: use File::Glob ':glob';
                     24: use File::Path;
                     25: use Getopt::Long;
1.3       espie      26:
1.1       espie      27: use LT::Trace;
                     28: use LT::Exec;
                     29: use LT::Util;
                     30:
                     31:
                     32: package main;
1.3       espie      33: $SIG{__DIE__} = sub {
                     34:        require Carp;
                     35:
                     36:        my $_ = pop @_;
                     37:        s/(.*)( at .*? line .*?\n$)/$1/s;
                     38:        push @_, $_;
                     39:        die &Carp::longmess;
                     40: };
                     41:
1.1       espie      42:
                     43: use subs qw(
                     44:        create_symlinks
                     45:        guess_implicit_mode
                     46:        help
                     47:        notyet
                     48:        );
                     49:
                     50:
                     51:
                     52: use Config;
                     53: my @no_shared_archs = qw(m88k vax);
                     54: my $machine_arch = $Config{'ARCH'};
                     55: (my $gnu_arch = $machine_arch) =~ s/amd64/x86_64/;
                     56: my @valid_modes = qw(clean compile execute finish install link uninstall);
                     57: my $cwd = getcwd();
                     58: my $instlibdir = '/usr/local/lib';
                     59: $instlibdir = $ENV{'LIBDIR'} if defined $ENV{'LIBDIR'};
                     60:
                     61: my $mode;
                     62: our $D = 0;            # debug flag
                     63: my $verbose = 1;
                     64:
                     65: my %opts;              # options passed to libtool
                     66: my @tags;              # list of --tag options passed to libtool
                     67:
                     68: # just to be clear:
                     69: # when building a library:
                     70: #      * -R libdir records libdir in dependency_libs
                     71: #      * -rpath is the path where the (shared) library will be installed
                     72: # when building a program:
                     73: #      * both -R libdir and -rpath libdir add libdir to the run-time path
                     74: # -Wl,-rpath,libdir will bypass libtool.
                     75:
                     76: # build static/shared objects?
                     77: my $noshared = 0;
                     78: if (grep { $_ eq $machine_arch } @no_shared_archs) {
                     79:        $noshared = 1;
                     80: }
                     81:
                     82: my $gp = new Getopt::Long::Parser;
                     83: # require_order so we stop parsing at the first non-option or argument,
                     84: # instead of parsing the whole ARGV.
                     85: $gp->configure(        'no_ignore_case',
                     86:                'pass_through',
                     87:                'no_auto_abbrev',
                     88:                'require_order'
                     89:        );
                     90: $gp->getoptions('config' => \&config,
                     91:                'debug' => \$D,
                     92:                'dry-run|n' => sub { LT::Exec->dry_run },
                     93:                'features' => \&notyet,
                     94:                'finish' => sub { $mode = 'finish'; },
                     95:                'help' => \&help, # does not return
                     96:                'mode=s{1}' => \$mode,
                     97:                'quiet' => sub { $verbose = 0; },
                     98:                'silent' => sub { $verbose = 0; },
                     99:                'tag=s{1}' => \@tags,
                    100:                'version' => sub { say "libtool (not (GNU libtool)) $version" ; exit(0); },
                    101:        );
                    102:
                    103: if ($verbose || $D) {
                    104:        LT::Exec->verbose_run;
                    105: }
                    106: # what are we going to run (cc, c++, ...)
                    107: my $ltprog = [];
                    108: # deal with multi-arg ltprog
                    109: LT::Trace::debug {"ARGV = @ARGV\n"};
                    110: while (@ARGV) {
                    111:        # just read arguments until the next option...
                    112:        if ($ARGV[0] =~ m/^\-/) { last; }
                    113:        # XXX improve checks
                    114:        if ($ARGV[0] =~ m/^\S+\.la/) { last; }
                    115:        my $arg = shift @ARGV;
                    116:        push @$ltprog, $arg;
                    117:        LT::Trace::debug {"arg = \"$arg\"\n"};
                    118:        # if the current argument is an install program, stop immediately
                    119:        if ($arg =~ /cp$/) { last; }
                    120:        if ($arg =~ /install([-.]sh)?$/) { last; }
                    121: }
                    122: LT::Trace::debug {"ltprog = \"@$ltprog\"\n"};
1.6       jasper    123: if (@$ltprog == 0) { die "No libtool command given.\n" .
                    124:                         "Use `libtool --help' for more information.\n" };
1.1       espie     125: # make ltprog a list of elements without whitespace (prevent exec errors)
                    126: my @tmp_ltprog = @$ltprog;
                    127: @$ltprog = ();
                    128: for my $el (@tmp_ltprog) {
                    129:        my @parts = split /\s+/, $el;
                    130:        push @$ltprog, @parts;
                    131: }
                    132:
                    133: # check mode and guess it if needed
                    134: if (!($mode && grep { $_ eq $mode } @valid_modes)) {
                    135:        $mode = guess_implicit_mode($ltprog);
                    136:        if ($mode) {
                    137:                LT::Trace::debug {"implicit mode: $mode\n"};
                    138:        } else {
                    139:                die "MODE must be one of:\n@valid_modes\n";
                    140:        }
                    141: }
                    142:
                    143: # from here, options may be intermixed with arguments
                    144: $gp->configure('permute');
                    145:
                    146: if ($mode eq 'compile') {
1.3       espie     147:        require LT::Mode::Compile;
                    148:        LT::Mode::Compile->run($ltprog, $gp, \@tags, $noshared);
                    149: } elsif ($mode eq 'install') {
                    150:        require LT::Mode::Install;
                    151:        LT::Mode::Install->run($ltprog);
1.1       espie     152:
                    153: } elsif ($mode eq 'link') {
1.3       espie     154:        require LT::Mode::Link;
                    155:        LT::Mode::Link->run($ltprog, $gp, \@tags, $noshared);
1.1       espie     156: } elsif ($mode eq 'finish' || $mode eq 'clean' || $mode eq 'uninstall') {
                    157:        # don't do anything
                    158:        exit 0;
                    159: } elsif ($mode eq 'execute') {
                    160:        # XXX check whether this is right
                    161:        LT::Exec->silent_run;
1.3       espie     162:        LT::Exec->execute(@$ltprog, @ARGV);
1.1       espie     163: } else {
                    164:        die "MODE=$mode not implemented yet.\n";
                    165: }
                    166:
                    167: if (LT::Exec->performed == 0) {
                    168:        die "No commands to execute.\n"
                    169: }
                    170:
                    171: ###########################################################################
                    172:
                    173: sub help
                    174: {
                    175:        print <<EOF
                    176: Usage: $0 [options]
                    177: --config - print configuration
                    178: --debug - turn on debugging output
                    179: --dry-run - don't do anything, only show what would be done
                    180: --help - this message
                    181: --mode=MODE - use operation mode MODE
                    182: --quiet - do not print informational messages
                    183: --silent - same as `--quiet'
1.5       jasper    184: --tag=TAG - specify a configuration variable TAG
1.1       espie     185: --version - print version of libtool
                    186: EOF
                    187: ;
                    188:        exit 1;
                    189: }
                    190:
                    191: sub notyet
                    192: {
                    193:        die "Option not implemented yet.\n";
                    194: }
                    195:
                    196: # XXX incomplete
                    197: sub config
                    198: {
                    199:        print "objdir=$ltdir\n";
                    200:        print "arch=$machine_arch\n";
                    201:        print "...\n";
                    202:        exit 0;
                    203: }
                    204:
                    205: sub create_symlinks
                    206: {
1.7       espie     207:        my ($dir, $libs) = @_;
1.1       espie     208:        if (! -d $dir) {
1.7       espie     209:                mkdir($dir) or die "Cannot mkdir($dir) : $!\n";
1.1       espie     210:        }
1.7       espie     211:
1.1       espie     212:        foreach my $l (values %$libs) {
                    213:                my $f = $l->{fullpath};
1.7       espie     214:                next if !defined $f;
                    215:                next if $f =~ m/\.a$/;
1.1       espie     216:                my $libnames = [];
                    217:                if (defined $l->{lafile}) {
                    218:                        require LT::LaFile;
                    219:                        my $lainfo = LT::LaFile->parse($l->{lafile});
                    220:                        my $librarynames = $lainfo->stringize('library_names');
                    221:                        @$libnames = split /\s/, $librarynames;
                    222:                        $libnames = reverse_zap_duplicates_ref($libnames);
                    223:                } else {
1.3       espie     224:                        push @$libnames, basename($f);
1.1       espie     225:                }
                    226:                foreach my $libfile (@$libnames) {
1.4       espie     227:                        my $link = "$dir/$libfile";
                    228:                        LT::Trace::debug {"ln -s $f $link\n"};
1.7       espie     229:                        next if -f $link;
                    230:                        my $p = abs_path($f);
1.8     ! espie     231:                        if (!symlink($p, $link)) {
        !           232:                                die "Cannot create symlink($p, $link): $!\n"
        !           233:                                    unless  $!{EEXIST}
        !           234:                        }
1.1       espie     235:                }
                    236:        }
1.7       espie     237:        return $dir;
1.1       espie     238: }
                    239:
                    240: # try to guess libtool mode when it is not specified
                    241: sub guess_implicit_mode
                    242: {
                    243:        my $ltprog = shift;
                    244:        my $m = 0;
                    245:        for my $a (@$ltprog) {
                    246:           if ($a =~ m/(install([.-]sh)?|cp)$/) {
                    247:                $m = 'install';
                    248:           } elsif ($a =~ m/cc|c\+\+/) {        # XXX improve test
                    249:                if (grep { $_ eq '-c' } @ARGV) {
                    250:                        $m = 'compile';
                    251:                } else {
                    252:                        $m = 'link';
                    253:                }
                    254:           }
                    255:        }
                    256:        return $m;
                    257: }