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