xref: /openbsd-src/usr.bin/libtool/LT/Mode/Link/Program.pm (revision 4c1e55dc91edd6e69ccc60ce855900fbc12cf34f)
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