]>
Commit | Line | Data |
---|---|---|
944c817a CF |
1 | #!/usr/bin/perl |
2 | use Getopt::Long; | |
fcea4c1c | 3 | use File::Temp qw'tempdir'; |
944c817a | 4 | use File::Basename; |
1318037e | 5 | use File::Spec; |
944c817a CF |
6 | use strict; |
7 | ||
59328e28 | 8 | sub dllname($;$); |
944c817a | 9 | |
59328e28 | 10 | my $static; |
edd090a2 CF |
11 | my $inverse; |
12 | my @exclude; | |
59328e28 | 13 | |
61522196 | 14 | my ($cpu, $ar, $as, $nm, $objcopy); |
edd090a2 | 15 | GetOptions('exclude=s'=>\@exclude, 'static!'=>\$static, 'v!'=>\$inverse, |
61522196 | 16 | 'cpu=s'=>\$cpu, 'ar=s'=>\$ar, 'as=s'=>\$as,'nm=s'=>\$nm, 'objcopy=s'=>\$objcopy); |
03905921 | 17 | |
edd090a2 | 18 | $_ = File::Spec->rel2abs($_) for @ARGV; |
59328e28 | 19 | |
edd090a2 CF |
20 | my $libdll = shift; |
21 | my $lib = pop; | |
61522196 | 22 | my $uscore = ($cpu eq 'x86_64' ? undef : '_'); |
b978c43e | 23 | (my $iname = basename $lib) =~ s/\.a$//o; |
61522196 | 24 | $iname = $uscore . $iname . '_dll_iname'; |
edd090a2 CF |
25 | |
26 | open my $nm_fd, '-|', $nm, '-Apg', '--defined-only', @ARGV, $libdll or | |
944c817a CF |
27 | die "$0: execution of $nm for object files failed - $!\n"; |
28 | ||
59328e28 CF |
29 | my %match_syms = (); |
30 | my $symfiles = (); | |
31 | my $lastfn; | |
32 | my %extract = (); | |
edd090a2 CF |
33 | my $exclude_regex = @exclude ? join('|', @exclude) : '\\UnLiKeLy//'; |
34 | $exclude_regex = qr/$exclude_regex/; | |
b978c43e | 35 | my $dllname; |
944c817a | 36 | while (<$nm_fd>) { |
59328e28 | 37 | study; |
61522196 | 38 | if (/ I _?(.*)_dll_iname/o) { |
c84fd8fe | 39 | $dllname = $1; |
b978c43e CF |
40 | } else { |
41 | my ($file, $member, $symbol) = m%^([^:]*):([^:]*(?=:))?.* T (.*)%o; | |
42 | next if !defined($symbol) || $symbol =~ $exclude_regex; | |
43 | if ($file ne $libdll) { | |
44 | $match_syms{$symbol} = 1; | |
45 | } elsif ($match_syms{$symbol} ? !$inverse : $inverse) { | |
46 | $extract{$member} = 1; | |
47 | } | |
48 | } | |
944c817a CF |
49 | } |
50 | close $nm_fd; | |
b978c43e | 51 | |
944c817a | 52 | |
59328e28 CF |
53 | %extract or die "$0: couldn't find symbols for $lib\n"; |
54 | ||
fcea4c1c | 55 | my $dir = tempdir(CLEANUP => 1); |
944c817a | 56 | |
59328e28 CF |
57 | chdir $dir; |
58 | # print join(' ', '+', $ar, 'x', sort keys %extract), "\n"; | |
59 | my $res = system $ar, 'x', $libdll, sort keys %extract; | |
60 | die "$0: $ar extraction exited with non-zero status\n" if $res; | |
61 | unlink $lib; | |
b978c43e CF |
62 | |
63 | # Add a dummy .idata object for libtool so that it will think | |
64 | # this library is an import library. | |
65 | my $iname_o = 'd000000.o'; | |
66 | $extract{$iname_o} = 1; | |
67 | open my $as_fd, '|-', $as, '-R', '-o', $iname_o, "-"; | |
68 | print $as_fd <<EOF; | |
69 | .section .idata\$7 | |
70 | .global $iname | |
71 | $iname: .asciz "$dllname.dll" | |
72 | EOF | |
73 | close $as_fd or exit 1; | |
74 | system $objcopy, '-j', '.idata$7', $iname_o; | |
75 | ||
73bd5752 CF |
76 | $res = system $ar, 'crus', $lib, sort keys %extract; |
77 | unlink keys %extract; | |
78 | die "$0: ar creation of $lib exited with non-zero status\n" if $res; | |
79 | exit 0; | |
98525461 CF |
80 | |
81 | END { | |
82 | chdir '/tmp'; # Allow $dir directory removal on Windows | |
83 | } |