Annotation of src/usr.bin/libtool/libtool, Revision 1.43
1.1 espie 1: #!/usr/bin/perl
1.43 ! jca 2: # $OpenBSD: libtool,v 1.42 2014/03/19 02:16:22 afresh1 Exp $
1.1 espie 3:
4: # Copyright (c) 2007-2010 Steven Mestdagh <steven@openbsd.org>
1.13 espie 5: # Copyright (c) 2012 Marc Espie <espie@openbsd.org>
1.1 espie 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 feature qw(say switch state);
1.23 espie 22: use Cwd qw(getcwd);
1.1 espie 23: use File::Glob ':glob';
1.3 espie 24:
1.1 espie 25: use LT::Trace;
26: use LT::Exec;
27: use LT::Util;
1.23 espie 28: use LT::Getopt;
1.1 espie 29:
1.3 espie 30: $SIG{__DIE__} = sub {
31: require Carp;
32:
1.42 afresh1 33: my $message = pop @_;
34: $message =~ s/(.*)( at .*? line .*?\n$)/$1/s;
35: push @_, $message;
1.3 espie 36: die &Carp::longmess;
37: };
38:
1.16 jasper 39: package LT::OSConfig;
40:
41: use Config;
1.18 jasper 42: use LT::Util;
1.16 jasper 43:
1.35 espie 44: my @picflags =qw(-fPIC -DPIC);
45:
1.16 jasper 46: sub new
47: {
1.35 espie 48: my $class = shift;
49: # XXX: incomplete
1.37 espie 50: my $self = bless {
1.35 espie 51: machine_arch => $Config{ARCH},
52: ltdir => $ltdir,
53: version => $version,
54: objdir => $ltdir,
1.43 ! jca 55: build_libtool_libs => 'no',
1.35 espie 56: build_old_libs => 'yes',
57: pic_flags => join(' ', @picflags),
1.43 ! jca 58: elf => 1,
! 59: noshared => 0,
1.37 espie 60: }, $class;
1.35 espie 61: ($self->{gnu_arch} = $self->{machine_arch}) =~ s/amd64/x86_64/;
62:
1.37 espie 63: return $self;
1.35 espie 64: }
1.22 jasper 65:
1.35 espie 66: sub noshared
67: {
68: my $self = shift;
69: return $self->{noshared};
70: }
71:
72: sub host
73: {
74: my $self = shift;
75: if (!defined $self->{osversion}) {
76: chomp($self->{osversion} = `uname -r`);
77: }
78: return "$self->{gnu_arch}-unknown-openbsd$self->{osversion}";
79: }
80:
81: # XXX
82: sub picflags
83: {
84: my $self = shift;
85: return \@picflags;
86: }
87:
88: sub sharedflag
89: {
90: return '-shared';
91: }
92:
93: sub version
94: {
95: my $self = shift;
96: return $self->{version};
1.16 jasper 97: }
98:
1.20 jasper 99: sub dump
100: {
101: my $self = shift;
1.34 espie 102: for my $key (sort keys %$self) {
103: say "$key=$self->{$key}";
1.20 jasper 104: }
105: }
106:
1.19 espie 107: package LT::Mode;
1.23 espie 108: use LT::Util;
1.19 espie 109:
110: sub new
111: {
112: my ($class, $origin) = @_;
113: bless {origin => $origin }, $class;
114: }
115:
1.30 espie 116: sub load_subclass
117: {
118: my ($self, $class) = @_;
119: local $SIG{__DIE__} = 'DEFAULT';
120: eval "require $class;";
121: if ($@) {
122: unless ($@ =~ m/^Can't locate .* in \@INC/) {
123: say STDERR $@;
124: exit 1;
125: }
126: }
127: }
128:
1.19 espie 129: my $mode_maker = { compile => 'LT::Mode::Compile',
130: clean => 'LT::Mode::Clean',
131: execute => 'LT::Mode::Execute',
132: finish => 'LT::Mode::Finish',
133: install => 'LT::Mode::Install',
134: link => 'LT::Mode::Link',
135: uninstall => 'LT::Mode::Uninstall' };
136:
137: sub factory
138: {
139: my ($class, $mode, $origin) = @_;
1.30 espie 140: my $s = $mode_maker->{$mode};
141: if ($s) {
142: $class->load_subclass($s);
143: return $s->new($origin);
1.19 espie 144: } else {
1.23 espie 145: shortdie "Mode=$mode not implemented yet.\n";
1.19 espie 146: }
147: }
148:
1.26 espie 149: sub help
150: {
151: }
152:
153: sub help_all
154: {
1.30 espie 155: my $class = shift;
156: for my $s (sort values %$mode_maker) {
157: $class->load_subclass($s);
158: $s->help;
1.26 espie 159: }
160: }
161:
1.19 espie 162: package LT::Mode::Empty;
163: our @ISA = qw(LT::Mode);
164: sub run
165: {
166: exit 0;
167: }
168:
169: package LT::Mode::Clean;
170: our @ISA = qw(LT::Mode::Empty);
1.27 espie 171: sub help
172: {
173: print <<"EOH";
174:
175: Usage: $0 --mode=clean RM [RM-Option]... FILE...
176: has not been implemented.
177: It should remove files from the build directory.
178: EOH
179: }
180:
1.19 espie 181: package LT::Mode::Execute;
182: our @ISA = qw(LT::Mode);
183: sub run
184: {
1.35 espie 185: my ($class, $ltprog, $gp, $ltconfig) = @_;
1.19 espie 186: # XXX check whether this is right
187: LT::Exec->silent_run;
188: LT::Exec->execute(@$ltprog, @main::ARGV);
189: }
190:
1.27 espie 191: sub help
192: {
193: print <<"EOH";
194:
195: Usage: $0 --mode=execute COMMAND [ARGS...]
196: Run a program after setting correct library path.
197: EOH
198: }
199:
200:
1.19 espie 201: package LT::Mode::Finish;
202: our @ISA = qw(LT::Mode::Empty);
1.27 espie 203: sub help
204: {
205: print <<"EOH";
206:
207: Usage: $0 --mode=finish [LIBDIR}...
208: Complete the installation of libtool libraries.
209: Not needed for our usage.
210: EOH
211: }
1.19 espie 212:
213: package LT::Mode::Uninstall;
214: our @ISA = qw(LT::Mode::Empty);
1.27 espie 215: sub help
216: {
217: print <<"EOH";
218:
219: Usage: $0 --mode=uninstall RM [RM-OPTION]... FILE...
220: has not been implemented
221: It should remove libraries from an installation directory.
222: EOH
223: }
1.19 espie 224:
1.10 espie 225: package LT::Options;
1.23 espie 226: use LT::Util;
227: our @ISA = qw(LT::Getopt);
1.10 espie 228:
229: my @valid_modes = qw(compile clean execute finish install link uninstall);
1.19 espie 230:
1.10 espie 231: my @known_tags = qw(disable-shared disable-static CC CXX F77 FC GO GCJ RC);
232:
233: sub new
234: {
235: my $class = shift;
1.32 espie 236: my $o = bless {}, $class;
1.10 espie 237: return $o;
238: }
239:
240: sub add_tag
241: {
242: my ($self, $value) = @_;
243: if ($value =~ m/[^\-\w,\/]/) {
1.23 espie 244: shortdie "invalid tag name: $value";
1.10 espie 245: exit 1;
246: }
247: if (grep {$value eq $_} @known_tags) {
248: $self->{tags}{$value} = 1;
249: } else {
250: say STDERR "ignoring unknown tag: $value";
251: }
252: }
253:
254: sub has_tag
255: {
256: my ($self, $tag) = @_;
257: return defined $self->{tags}{$tag};
258: }
259:
260: sub is_abreviated_mode
261: {
262: my ($self, $arg) = @_;
1.15 jasper 263: return undef if !$arg;
1.10 espie 264: for my $m (@valid_modes) {
265: next if length $arg > length $m;
266: if ($arg eq substr($m, 0, length $arg)) {
1.19 espie 267: return LT::Mode->factory($m, $arg);
1.10 espie 268: }
269: }
270: return undef;
271: }
272:
273: # XXX this should always fail if we are libtool2 !
274: # try to guess libtool mode when it is not specified
275: sub guess_implicit_mode
276: {
277: my ($self, $ltprog) = @_;
278: my $m;
279: for my $a (@$ltprog) {
1.41 ajacouto 280: if ($a =~ m/(install([.-](sh|check))?|cp)$/) {
1.29 espie 281: $m = LT::Mode->factory('install', "implicit $a");
1.10 espie 282: } elsif ($a =~ m/cc|c\+\+/) { # XXX improve test
283: if (grep { $_ eq '-c' } @ARGV) {
1.29 espie 284: $m = LT::Mode->factory('compile', "implicit");
1.10 espie 285: } else {
1.29 espie 286: $m = LT::Mode->factory('link', "implicit");
1.10 espie 287: }
288: }
289: }
290: return $m;
291: }
292:
293: sub valid_modes
294: {
295: my $self = shift;
296: return join(' ', @valid_modes);
297: }
298:
299: package main;
1.1 espie 300:
1.17 espie 301: my $ltconfig = LT::OSConfig->new;
1.1 espie 302: my $cwd = getcwd();
303: my $mode;
304: my $verbose = 1;
1.26 espie 305: my $help = 0;
1.1 espie 306:
1.31 espie 307:
308: # XXX compat game to satisfy both libtool 1 and libtool 2
309: unless ($ARGV[0] eq 'install' && $ARGV[1] =~ m/^-[bcCdpSsBfgmo]/) {
310: if ($mode = LT::Options->is_abreviated_mode($ARGV[0])) {
311: shift @ARGV;
312: }
313: }
314:
1.1 espie 315: # just to be clear:
316: # when building a library:
317: # * -R libdir records libdir in dependency_libs
318: # * -rpath is the path where the (shared) library will be installed
319: # when building a program:
320: # * both -R libdir and -rpath libdir add libdir to the run-time path
321: # -Wl,-rpath,libdir will bypass libtool.
322:
1.10 espie 323: my $gp = LT::Options->new;
1.25 espie 324: $gp->handle_options(
325: '-config' => \&config,
326: '-debug|x' => sub {
327: LT::Trace->set(1);
328: LT::Exec->verbose_run;
329: },
330: '-dry-run|-dryrun|n' => sub { LT::Exec->dry_run; },
331: '-features' => sub {
1.35 espie 332: say "host: ", $ltconfig->host;
333: say "enable shared libraries" unless $ltconfig->noshared;
1.25 espie 334: say "enable static libraries";
335: exit 0;
336: },
1.29 espie 337: '-finish' => sub { $mode = LT::Mode->factory('finish', '--finish'); },
1.26 espie 338: '-help|?|h' => sub { $help = 1; },
339: '-help-all' => sub { basic_help(); LT::Mode->help_all; exit 0; },
1.25 espie 340: '-mode=' => sub {
341: $mode = LT::Mode->factory($_[2], "--mode=$_[2]");
342: },
343: '-quiet|-silent|-no-verbose' => sub { $verbose = 0; },
344: '-verbose|-no-silent|-no-quiet|v' => sub {$verbose = 1;},
345: '-tag=' => sub { $gp->add_tag($_[2]); },
346: '-version' => sub {
1.35 espie 347: say "libtool (not (GNU libtool)) ", $ltconfig->version;
1.25 espie 348: exit 0;
349: },
1.26 espie 350: '-no-warning|-no-warn' => sub {},
1.28 espie 351: # ignored
352: '-preserve-dup-deps',
353: '-dlopen=|dlopen=@',
1.25 espie 354: );
1.1 espie 355:
1.26 espie 356: if ($help) {
357: basic_help();
358: if ($mode) {
359: $mode->help;
360: }
361: exit 0;
362: }
1.10 espie 363: if ($verbose) {
1.1 espie 364: LT::Exec->verbose_run;
365: }
1.10 espie 366:
1.1 espie 367: # what are we going to run (cc, c++, ...)
368: my $ltprog = [];
369: # deal with multi-arg ltprog
1.10 espie 370: tsay {"ARGV = \"@ARGV\""};
1.1 espie 371: while (@ARGV) {
372: # just read arguments until the next option...
373: if ($ARGV[0] =~ m/^\-/) { last; }
374: # XXX improve checks
375: if ($ARGV[0] =~ m/^\S+\.la/) { last; }
376: my $arg = shift @ARGV;
377: push @$ltprog, $arg;
1.10 espie 378: tsay {"arg = \"$arg\""};
1.1 espie 379: # if the current argument is an install program, stop immediately
380: if ($arg =~ /cp$/) { last; }
1.41 ajacouto 381: if ($arg =~ /install([-.](sh|check))?$/) { last; }
1.1 espie 382: }
1.10 espie 383: tsay {"ltprog = \"@$ltprog\""};
1.14 espie 384:
385: # XXX compat game to satisfy both libtool 1 and libtool 2
386: # let libtool install work as both libtool 1 and libtool 2
1.19 espie 387: if (@$ltprog == 0 && defined $mode && $mode->{origin} eq 'install') {
388: $ltprog = [ 'install' ];
1.14 espie 389: }
1.31 espie 390:
1.6 jasper 391: if (@$ltprog == 0) { die "No libtool command given.\n" .
392: "Use `libtool --help' for more information.\n" };
1.1 espie 393: # make ltprog a list of elements without whitespace (prevent exec errors)
394: my @tmp_ltprog = @$ltprog;
395: @$ltprog = ();
396: for my $el (@tmp_ltprog) {
397: my @parts = split /\s+/, $el;
398: push @$ltprog, @parts;
399: }
400:
1.10 espie 401: if (!defined $mode) {
402: $mode = $gp->guess_implicit_mode($ltprog);
1.19 espie 403: tsay {"implicit mode: ", $mode->{origin}} if $mode;
1.28 espie 404: }
405:
406: if (!defined $mode) {
407: shortdie "no explicit mode, couldn't figure out implicit mode\n";
408: }
409:
410: if (!$mode->isa("LT::Mode::Execute")) {
1.29 espie 411: if ($gp->dlopen) {
1.28 espie 412: shortdie "Error: -dlopen FILE in generic libtool options is an error in non execute mode";
413: }
1.1 espie 414: }
415:
416: # from here, options may be intermixed with arguments
417:
1.35 espie 418: $mode->run($ltprog, $gp, $ltconfig);
1.1 espie 419:
420: if (LT::Exec->performed == 0) {
421: die "No commands to execute.\n"
422: }
423:
424: ###########################################################################
425:
1.26 espie 426: sub basic_help
1.1 espie 427: {
428: print <<EOF
429: Usage: $0 [options]
430: --config - print configuration
431: --debug - turn on debugging output
432: --dry-run - don't do anything, only show what would be done
433: --help - this message
434: --mode=MODE - use operation mode MODE
435: --quiet - do not print informational messages
436: --silent - same as `--quiet'
1.5 jasper 437: --tag=TAG - specify a configuration variable TAG
1.1 espie 438: --version - print version of libtool
439: EOF
440: ;
441: }
442:
443: sub config
444: {
1.20 jasper 445: $ltconfig->dump;
1.1 espie 446: exit 0;
447: }
448: