1# $OpenBSD: Program.pm,v 1.1 2012/07/13 11:56:13 espie Exp $ 2 3# Copyright (c) 2007-2010 Steven Mestdagh <steven@openbsd.org> 4# Copyright (c) 2012 Marc Espie <espie@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 18use strict; 19use warnings; 20use feature qw(say); 21 22use LT::Program; 23 24package LT::Program; 25 26sub link 27{ 28 return LT::Linker::Program->new->link(@_); 29} 30 31package LT::Linker::Program; 32our @ISA = qw(LT::Linker); 33 34use LT::Trace; 35use LT::Util; 36use File::Basename; 37 38sub link 39{ 40 my ($linker, $self, $ltprog, $ltconfig, $dirs, $libs, $deplibs, 41 $libdirs, $parser, $gp) = @_; 42 43 tsay {"linking program (", ($gp->static ? "not " : ""), 44 "dynamically linking not-installed libtool libraries)"}; 45 46 my $fpath = $self->{outfilepath}; 47 my $RPdirs = $self->{RPdirs}; 48 49 my $odir = dirname($fpath); 50 my $fname = basename($fpath); 51 52 my @libflags; 53 my @cmd; 54 my $dst; 55 56 my ($staticlibs, $finalorderedlibs, $args) = 57 $linker->common1($parser, $gp, $deplibs, $libdirs, $dirs, $libs); 58 59 my $symlinkdir = $ltdir; 60 if ($odir ne '.') { 61 $symlinkdir = "$odir/$ltdir"; 62 } 63 mkdir $symlinkdir if ! -d $symlinkdir; 64 if ($parser->{seen_la_shared}) { 65 $dst = ($odir eq '.') ? "$ltdir/$fname" : "$odir/$ltdir/$fname"; 66 $self->write_wrapper; 67 } else { 68 $dst = ($odir eq '.') ? $fname : "$odir/$fname"; 69 } 70 71 my $symbolsfile; 72 if ($gp->export_symbols) { 73 $symbolsfile = $gp->export_symbols; 74 } elsif ($gp->export_symbols_regex) { 75 ($symbolsfile = "$odir/$ltdir/$fname") =~ s/\.la$/.exp/; 76 LT::Archive->get_symbollist($symbolsfile, $gp->export_symbols_regex, $self->{objlist}); 77 } 78 $libdirs = reverse_zap_duplicates_ref($libdirs); 79 my $rpath_link = {}; 80 # add libdirs to rpath if they are not in standard lib path 81 for my $l (@$libdirs) { 82 if (LT::OSConfig->is_search_dir($l)) { 83 $rpath_link->{$l} = 1; 84 } else { 85 push @$RPdirs, $l; 86 } 87 } 88 $RPdirs = reverse_zap_duplicates_ref($RPdirs); 89 foreach my $k (keys %$libs) { 90 tprint {"key = $k - "}; 91 my $r = ref($libs->{$k}); 92 tsay {"ref = $r"}; 93 $libs->create($k)->resolve_library($dirs, 1, $gp->static, 94 ref($self)); 95 } 96 97 my @libobjects = values %$libs; 98 tsay {"libs:\n", join("\n", keys %$libs)}; 99 tsay {"libfiles:\n", join("\n", map { $_->{fullpath} } @libobjects)}; 100 101 $linker->create_symlinks($symlinkdir, $libs); 102 foreach my $k (@$finalorderedlibs) { 103 my $a = $libs->{$k}->{fullpath} || die "Link error: $k not found in \$libs\n"; 104 if ($a =~ m/\.a$/) { 105 # don't make a -lfoo out of a static library 106 push @libflags, $a; 107 } else { 108 push @libflags, $linker->infer_libparameter($a, $k); 109 } 110 } 111 112 my @linkeropts = (); 113 for my $d (@$RPdirs) { 114 push(@linkeropts, '-rpath', $d); 115 } 116 for my $d (keys %$rpath_link) { 117 push(@linkeropts, '-rpath-link', $d); 118 } 119 if ($symbolsfile) { 120 push(@linkeropts, '-retain-symbols-file', $symbolsfile); 121 } 122 @cmd = @$ltprog; 123 push @cmd, '-o', $dst; 124 push @cmd, '-pthread' if $parser->{pthread}; 125 push @cmd, @$args if $args; 126 push @cmd, @{$self->{objlist}} if @{$self->{objlist}}; 127 push @cmd, @$staticlibs if @$staticlibs; 128 push @cmd, "-L$symlinkdir", @libflags if @libflags; 129 push @cmd, '-Wl,'. join(',', @linkeropts) if @linkeropts; 130 LT::Exec->link(@cmd); 131} 1321; 133