1# $OpenBSD: Library.pm,v 1.2 2012/11/09 10:55:01 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::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 @libflags; 46 my @cmd; 47 my $dst = ($odir eq '.') ? "$ltdir/$fname" : "$odir/$ltdir/$fname"; 48 if ($la =~ m/\.a$/) { 49 # probably just a convenience library 50 $dst = ($odir eq '.') ? "$fname" : "$odir/$fname"; 51 } 52 my $symlinkdir = $ltdir; 53 if ($odir ne '.') { 54 $symlinkdir = "$odir/$ltdir"; 55 } 56 mkdir $symlinkdir if ! -d $symlinkdir; 57 58 my ($staticlibs, $finalorderedlibs, $args) = 59 $linker->common1($parser, $gp, $deplibs, $libdirs, $dirs, $libs); 60 61 # static linking 62 if (!$shared) { 63 @cmd = ('ar', 'cru', $dst); 64 foreach my $a (@$staticlibs) { 65 if ($a =~ m/\.a$/ && $a !~ m/_pic\.a/) { 66 # extract objects from archive 67 my $libfile = basename($a); 68 my $xdir = "$odir/$ltdir/${la}x/$libfile"; 69 LT::Archive->extract($xdir, $a); 70 my @kobjs = LT::Archive->get_objlist($a); 71 map { $_ = "$xdir/$_"; } @kobjs; 72 push @libflags, @kobjs; 73 } 74 } 75 foreach my $k (@$finalorderedlibs) { 76 my $l = $libs->{$k}; 77 # XXX improve test 78 # this has to be done probably only with 79 # convenience libraries 80 next if !defined $l->{lafile}; 81 my $lainfo = LT::LaFile->parse($l->{lafile}); 82 next if ($lainfo->stringize('dlname') ne ''); 83 $l->resolve_library($dirs, 0, 0, ref($self)); 84 my $a = $l->{fullpath}; 85 if ($a =~ m/\.a$/ && $a !~ m/_pic\.a/) { 86 # extract objects from archive 87 my $libfile = basename $a; 88 my $xdir = "$odir/$ltdir/${la}x/$libfile"; 89 LT::Archive->extract($xdir, $a); 90 my @kobjs = LT::Archive->get_objlist($a); 91 map { $_ = "$xdir/$_"; } @kobjs; 92 push @libflags, @kobjs; 93 } 94 } 95 push @cmd, @libflags if @libflags; 96 push @cmd, @$objs if @$objs; 97 LT::Exec->link(@cmd); 98 LT::Exec->link('ranlib', $dst); 99 return; 100 } 101 102 my $tmp = []; 103 while (my $k = shift @$finalorderedlibs) { 104 my $l = $libs->{$k}; 105 $l->resolve_library($dirs, 1, $gp->static, ref($self)); 106 if ($l->{dropped}) { 107 # remove library if dependency on it has been dropped 108 delete $libs->{$k}; 109 } else { 110 push(@$tmp, $k); 111 } 112 } 113 $finalorderedlibs = $tmp; 114 115 my @libobjects = values %$libs; 116 tsay {"libs:\n", join("\n", (keys %$libs))}; 117 tsay {"libfiles:\n", 118 join("\n", map { $_->{fullpath}//'UNDEF' } @libobjects) }; 119 120 $linker->create_symlinks($symlinkdir, $libs); 121 my $prev_was_archive = 0; 122 my $libcounter = 0; 123 foreach my $k (@$finalorderedlibs) { 124 my $a = $libs->{$k}->{fullpath} || die "Link error: $k not found in \$libs\n"; 125 if ($a =~ m/\.a$/) { 126 # don't make a -lfoo out of a static library 127 push @libflags, '-Wl,-whole-archive' unless $prev_was_archive; 128 push @libflags, $a; 129 if ($libcounter == @$finalorderedlibs - 1) { 130 push @libflags, '-Wl,-no-whole-archive'; 131 } 132 $prev_was_archive = 1; 133 } else { 134 push @libflags, '-Wl,-no-whole-archive' if $prev_was_archive; 135 $prev_was_archive = 0; 136 push @libflags, $linker->infer_libparameter($a, $k); 137 } 138 $libcounter++; 139 } 140 141 @cmd = @$ltprog; 142 push @cmd, $ltconfig->sharedflag, @{$ltconfig->picflags}; 143 push @cmd, '-o', $dst; 144 push @cmd, '-pthread' if $parser->{pthread}; 145 push @cmd, @$args if $args; 146 push @cmd, @$objs if @$objs; 147 push @cmd, '-Wl,-whole-archive', @$staticlibs, '-Wl,-no-whole-archive' 148 if @$staticlibs; 149 push @cmd, "-L$symlinkdir", @libflags if @libflags; 150 151 my @e = $linker->export_symbols($ltconfig, 152 "$odir/$ltdir/$la", $gp, @$objs, @$staticlibs); 153 push(@cmd, join(',', "-Wl", @e)) if @e; 154 LT::Exec->link(@cmd); 155} 156 1571; 158