eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' & eval 'exec perl -S $0 $argv:q' if 0; # $Id$ # # Drop-in replacement for "ld" that supports munching. # # The first three lines above let this script run without specifying the # full path to perl, as long as it is in the user's PATH. # Taken from perlrun man page. $usage = "usage: $0 [-? | [[-c ] [-m ] [-n ]] [-f]]]\n"; #### #### process command line args #### while ( $#ARGV >= 0 && $ARGV[0] =~ /^-/ ) { if ( $ARGV[0] eq '-c' ) { if ( $ARGV[1] !~ /^[-].+$/ ) { $compile = $ARGV[1]; shift; } else { print STDERR "$0: must provide argument for -c option\n"; die $usage; } } elsif ( $ARGV[0] eq '-m' ) { if ( $ARGV[1] !~ /^[-].+$/ ) { $munch = $ARGV[1]; shift; } else { print STDERR "$0: must provide argument for -m option\n"; die $usage; } } elsif ( $ARGV[0] eq '-n' ) { if ( $ARGV[1] !~ /^[-].+$/ ) { $nm = $ARGV[1]; shift; } else { print STDERR "$0: must provide argument for -n option\n"; die $usage; } } elsif ( $ARGV[0] eq '-?' ) { print "$usage"; exit; } else { warn "$0: unknown option $ARGV[0]\n"; die $usage; } shift; } #### #### Save link command, i.e., current @ARGV, for use below. #### @args = @ARGV; #### #### Find full path to each library. #### @libDirs = (); $current_dir_in_libDirs = 0; @libs = (); @objs = ''; foreach $arg (@ARGV) { if ($arg =~ /^['"]?-L([\S]+)/) { ($dir = $1) =~ s%/+$%%; #### trim any trailing slashes push (@libDirs, $dir); $current_dir_in_libDirs = 1 if $dir eq '.'; } elsif ($arg =~ /^['"]?-l([\S]+)/) { push (@libs, $1); } elsif ($arg =~ /\.o$/) { push (@objs, $arg); } } #### Add . to libDirs if it doesn't already have it. push (@libDirs, ".") unless $current_dir_in_libDirs; foreach $lib (@libs) { foreach $libDir (@libDirs) { if (-e "$libDir/lib$lib.a") { $full_path{$lib} = "$libDir/lib$lib.a"; last; } } } #### #### Set up signal handler. #### $done = 0; $SIG{'HUP'} = $SIG{'INT'} = $SIG{'QUIT'} = $SIG{'TERM'} = 'cleanup'; #### #### Munch, if $munch is non-null. #### if ($munch) { $munch_objs = join (' ', @objs); $munch_libs = join (' ', values %full_path); open (MUNCH, "$nm $munch_objs $munch_libs | $munch |") || &fail ("$0: unable to run \"$nm\" or \"$munch\"\n"); open (CTORDTOR, "> __ctordtor.c") || &fail ("$0: unable to open \"__ctordtor.c\"\n"); while () { #### Filter out munch output that contains '.cpp'. It results from #### .cpp files that have no text or data, e.g., .cpp files that #### only contain template instantiations. These lines confuse g++. print CTORDTOR unless /\.cpp/; } close CTORDTOR || &fail ("$0: unable to write \"__ctordtor.c\"\n"); close MUNCH; system ("$compile -o .obj/__ctordtor.o __ctordtor.c") && &fail ("$0: \"$compile\" failed\n"); } #### #### Construct the link command from @args and perform the link. #### if ($munch) { #### Insert ctordtor object file before first library in link command. $arg_lib = 0; foreach $arg (@ARGV) { if ($arg =~ /^['"]?-l/) { last; } ++$arg_lib; } splice (@args, $arg_lib, 0, ".obj/__ctordtor.o"); } $link_command = join (' ', @args); system ("$link_command") && &fail ("$0: $link_command failed\n"); $done = 1; &cleanup; #### #### #### sub fail { local ($message) = @_; warn $message; &cleanup; } #### #### clean up when done or on signal #### sub cleanup { unlink "__ctordtor.c", ".obj/__ctordtor.o"; if ($done) { exit 0; } else { exit 1; } } #### EOF