1# $OpenBSD: Library.pm,v 1.5 2014/04/16 14:39:06 zhuk 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::LaFile; 23 24package LT::LaFile; 25sub link 26{ 27 return LT::Linker::LaFile->new->link(@_); 28} 29 30package LT::Linker::LaFile; 31our @ISA = qw(LT::Linker); 32 33use LT::Util; 34use LT::Trace; 35use File::Basename; 36 37sub link 38{ 39 my ($linker, $self, $ltprog, $ltconfig, $la, $fname, $odir, $shared, 40 $objs, $dirs, $libs, $deplibs, $libdirs, $parser, $gp) = @_; 41 42 tsay {"creating link command for library (linked ", 43 ($shared) ? "dynamically" : "statically", ")"}; 44 45 my $RPdirs = $self->{RPdirs}; 46 47 my @libflags; 48 my @cmd; 49 my $dst = ($odir eq '.') ? "$ltdir/$fname" : "$odir/$ltdir/$fname"; 50 if ($la =~ m/\.a$/) { 51 # probably just a convenience library 52 $dst = ($odir eq '.') ? "$fname" : "$odir/$fname"; 53 } 54 my $symlinkdir = $ltdir; 55 if ($odir ne '.') { 56 $symlinkdir = "$odir/$ltdir"; 57 } 58 mkdir $symlinkdir if ! -d $symlinkdir; 59 60 my ($staticlibs, $finalorderedlibs, $args) = 61 $linker->common1($parser, $gp, $deplibs, $libdirs, $dirs, $libs); 62 63 # static linking 64 if (!$shared) { 65 @cmd = ('ar', 'cru', $dst); 66 foreach my $a (@$staticlibs) { 67 if ($a =~ m/\.a$/ && $a !~ m/_pic\.a/) { 68 # extract objects from archive 69 my $libfile = basename($a); 70 my $xdir = "$odir/$ltdir/${la}x/$libfile"; 71 LT::Archive->extract($xdir, $a); 72 my @kobjs = LT::Archive->get_objlist($a); 73 map { $_ = "$xdir/$_"; } @kobjs; 74 push @libflags, @kobjs; 75 } 76 } 77 foreach my $k (@$finalorderedlibs) { 78 my $l = $libs->{$k}; 79 # XXX improve test 80 # this has to be done probably only with 81 # convenience libraries 82 next if !defined $l->{lafile}; 83 my $lainfo = LT::LaFile->parse($l->{lafile}); 84 next if ($lainfo->stringize('dlname') ne ''); 85 $l->resolve_library($dirs, 0, 0, ref($self)); 86 my $a = $l->{fullpath}; 87 if ($a =~ m/\.a$/ && $a !~ m/_pic\.a/) { 88 # extract objects from archive 89 my $libfile = basename $a; 90 my $xdir = "$odir/$ltdir/${la}x/$libfile"; 91 LT::Archive->extract($xdir, $a); 92 my @kobjs = LT::Archive->get_objlist($a); 93 map { $_ = "$xdir/$_"; } @kobjs; 94 push @libflags, @kobjs; 95 } 96 } 97 push @cmd, @libflags if @libflags; 98 push @cmd, @$objs if @$objs; 99 LT::Exec->link(@cmd); 100 LT::Exec->link('ranlib', $dst); 101 return; 102 } 103 104 my $tmp = []; 105 while (my $k = shift @$finalorderedlibs) { 106 my $l = $libs->{$k}; 107 $l->resolve_library($dirs, 1, $gp->static, ref($self)); 108 if ($l->{dropped}) { 109 # remove library if dependency on it has been dropped 110 delete $libs->{$k}; 111 } else { 112 push(@$tmp, $k); 113 } 114 } 115 $finalorderedlibs = $tmp; 116 117 my @libobjects = values %$libs; 118 tsay {"libs:\n", join("\n", (keys %$libs))}; 119 tsay {"libfiles:\n", 120 join("\n", map { $_->{fullpath}//'UNDEF' } @libobjects) }; 121 122 $linker->create_symlinks($symlinkdir, $libs); 123 my $prev_was_archive = 0; 124 my $libcounter = 0; 125 foreach my $k (@$finalorderedlibs) { 126 my $a = $libs->{$k}->{fullpath} || die "Link error: $k not found in \$libs\n"; 127 if ($a =~ m/\.a$/) { 128 # don't make a -lfoo out of a static library 129 push @libflags, '-Wl,-whole-archive' unless $prev_was_archive; 130 push @libflags, $a; 131 if ($libcounter == @$finalorderedlibs - 1) { 132 push @libflags, '-Wl,-no-whole-archive'; 133 } 134 $prev_was_archive = 1; 135 } else { 136 push @libflags, '-Wl,-no-whole-archive' if $prev_was_archive; 137 $prev_was_archive = 0; 138 push @libflags, $linker->infer_libparameter($a, $k); 139 } 140 $libcounter++; 141 } 142 143 # add libdirs to rpath if they are not in standard lib path 144 for my $l (@$libdirs) { 145 if (!LT::OSConfig->is_search_dir($l)) { 146 push @$RPdirs, $l; 147 } 148 } 149 150 my @linkeropts = (); 151 if (!$ltconfig->noshared) { 152 for my $d (@$RPdirs) { 153 push(@linkeropts, '-rpath', $d); 154 } 155 } 156 157 @cmd = @$ltprog; 158 push @cmd, $ltconfig->sharedflag, @{$ltconfig->picflags}; 159 push @cmd, '-o', $dst; 160 push @cmd, '-pthread' if $parser->{pthread}; 161 push @cmd, @$args if $args; 162 push @cmd, @$objs if @$objs; 163 push @cmd, '-Wl,-whole-archive', @$staticlibs, '-Wl,-no-whole-archive' 164 if @$staticlibs; 165 push @cmd, "-L$symlinkdir", @libflags if @libflags; 166 167 my @e = $linker->export_symbols($ltconfig, 168 "$odir/$ltdir/$la", $gp, @$objs, @$staticlibs); 169 push(@cmd, join(',', "-Wl", @e)) if @e; 170 push @cmd, join(',', "-Wl", @linkeropts) if @linkeropts; 171 LT::Exec->link(@cmd); 172} 173 1741; 175