2009-01-02 14:57:14 +08:00
|
|
|
#!/usr/bin/perl
|
|
|
|
use Getopt::Long;
|
2009-04-14 23:10:28 +08:00
|
|
|
use File::Temp qw'tempdir';
|
2009-01-02 14:57:14 +08:00
|
|
|
use File::Basename;
|
2009-04-10 12:29:25 +08:00
|
|
|
use File::Spec;
|
2009-01-02 14:57:14 +08:00
|
|
|
use strict;
|
|
|
|
|
2009-04-10 05:02:53 +08:00
|
|
|
sub dllname($;$);
|
2009-01-02 14:57:14 +08:00
|
|
|
|
2009-04-10 05:02:53 +08:00
|
|
|
my $static;
|
2009-04-12 11:19:52 +08:00
|
|
|
my $inverse;
|
|
|
|
my @exclude;
|
2009-04-10 05:02:53 +08:00
|
|
|
|
2009-04-12 11:19:52 +08:00
|
|
|
my ($ar, $as, $nm, $objcopy);
|
|
|
|
GetOptions('exclude=s'=>\@exclude, 'static!'=>\$static, 'v!'=>\$inverse,
|
|
|
|
'ar=s'=>\$ar, 'as=s'=>\$as,'nm=s'=>\$nm, 'objcopy=s'=>\$objcopy);
|
2009-03-28 12:55:36 +08:00
|
|
|
|
2009-04-12 11:19:52 +08:00
|
|
|
$_ = File::Spec->rel2abs($_) for @ARGV;
|
2009-04-10 05:02:53 +08:00
|
|
|
|
2009-04-12 11:19:52 +08:00
|
|
|
my $libdll = shift;
|
|
|
|
my $lib = pop;
|
2009-04-19 01:23:45 +08:00
|
|
|
(my $iname = basename $lib) =~ s/\.a$//o;
|
|
|
|
$iname = '_' . $iname . '_dll_iname';
|
2009-04-12 11:19:52 +08:00
|
|
|
|
|
|
|
open my $nm_fd, '-|', $nm, '-Apg', '--defined-only', @ARGV, $libdll or
|
2009-01-02 14:57:14 +08:00
|
|
|
die "$0: execution of $nm for object files failed - $!\n";
|
|
|
|
|
2009-04-10 05:02:53 +08:00
|
|
|
my %match_syms = ();
|
|
|
|
my $symfiles = ();
|
|
|
|
my $lastfn;
|
|
|
|
my %extract = ();
|
2009-04-12 11:19:52 +08:00
|
|
|
my $exclude_regex = @exclude ? join('|', @exclude) : '\\UnLiKeLy//';
|
|
|
|
$exclude_regex = qr/$exclude_regex/;
|
2009-04-19 01:23:45 +08:00
|
|
|
my $dllname;
|
2009-01-02 14:57:14 +08:00
|
|
|
while (<$nm_fd>) {
|
2009-04-10 05:02:53 +08:00
|
|
|
study;
|
2009-04-19 01:23:45 +08:00
|
|
|
if (/ I _(.*)_dll_iname/o) {
|
2009-11-30 23:40:23 +08:00
|
|
|
$dllname = $1;
|
2009-04-19 01:23:45 +08:00
|
|
|
} else {
|
|
|
|
my ($file, $member, $symbol) = m%^([^:]*):([^:]*(?=:))?.* T (.*)%o;
|
|
|
|
next if !defined($symbol) || $symbol =~ $exclude_regex;
|
|
|
|
if ($file ne $libdll) {
|
|
|
|
$match_syms{$symbol} = 1;
|
|
|
|
} elsif ($match_syms{$symbol} ? !$inverse : $inverse) {
|
|
|
|
$extract{$member} = 1;
|
|
|
|
}
|
|
|
|
}
|
2009-01-02 14:57:14 +08:00
|
|
|
}
|
|
|
|
close $nm_fd;
|
2009-04-19 01:23:45 +08:00
|
|
|
|
2009-01-02 14:57:14 +08:00
|
|
|
|
2009-04-10 05:02:53 +08:00
|
|
|
%extract or die "$0: couldn't find symbols for $lib\n";
|
|
|
|
|
2009-04-14 23:10:28 +08:00
|
|
|
my $dir = tempdir(CLEANUP => 1);
|
2009-01-02 14:57:14 +08:00
|
|
|
|
2009-04-10 05:02:53 +08:00
|
|
|
chdir $dir;
|
|
|
|
# print join(' ', '+', $ar, 'x', sort keys %extract), "\n";
|
|
|
|
my $res = system $ar, 'x', $libdll, sort keys %extract;
|
|
|
|
die "$0: $ar extraction exited with non-zero status\n" if $res;
|
|
|
|
unlink $lib;
|
2009-04-19 01:23:45 +08:00
|
|
|
|
|
|
|
# Add a dummy .idata object for libtool so that it will think
|
|
|
|
# this library is an import library.
|
|
|
|
my $iname_o = 'd000000.o';
|
|
|
|
$extract{$iname_o} = 1;
|
|
|
|
open my $as_fd, '|-', $as, '-R', '-o', $iname_o, "-";
|
|
|
|
print $as_fd <<EOF;
|
|
|
|
.section .idata\$7
|
|
|
|
.global $iname
|
|
|
|
$iname: .asciz "$dllname.dll"
|
|
|
|
EOF
|
|
|
|
close $as_fd or exit 1;
|
|
|
|
system $objcopy, '-j', '.idata$7', $iname_o;
|
|
|
|
|
2009-04-12 13:11:08 +08:00
|
|
|
$res = system $ar, 'crus', $lib, sort keys %extract;
|
|
|
|
unlink keys %extract;
|
|
|
|
die "$0: ar creation of $lib exited with non-zero status\n" if $res;
|
|
|
|
exit 0;
|
2011-02-12 02:00:55 +08:00
|
|
|
|
|
|
|
END {
|
|
|
|
chdir '/tmp'; # Allow $dir directory removal on Windows
|
|
|
|
}
|