1#!@PERL@ -w 2 3# Merges several static libraries (*.a) into a single library. Tries 4# to maintain the order of the members as it was in the original 5# libraries. Multiple members of the same name may be present in 6# different input libraries and correctly packaged. However, if 7# multiple members with the same name reside in the same input 8# library, only the last one will be used. 9 10use strict; 11 12my $usageString = "unpack.pl <tmpdir> lib1.a lib2.a ... 13Unpacks all .o files from lib1.a, lib2.a, etc into <tmpdir> and prints the list 14of .o files on the standard output"; 15 16if($#ARGV < 1) { 17 print STDERR "temp dir and at least 1 input name must be given.\n"; 18 print STDERR "$usageString\n"; 19 exit 1; 20} 21 22my $tmpDir = $ARGV[0]; 23my @inFiles = @ARGV[1..$#ARGV]; 24 25my $currDir = `pwd`; $currDir =~ s/\n//g; 26 27# Create the database of members: mappings of each file to the 28# respective library name, and to the list of members in the original 29# order 30 31my %libName=(); 32my %members=(); 33my $countLibs=0; 34my $countMembers=0; 35 36# List of input files without repetition 37my @tmp = (); 38 39for(my $i=0; $i<=$#inFiles; $i++) { 40 # Skip the library if we've seen it already 41 if(!defined($libName{$inFiles[$i]})) { 42 push @tmp, $inFiles[$i]; 43 $countLibs++; 44 if($inFiles[$i] =~ m/lib(\w+).a$/) { 45 $libName{$inFiles[$i]} = $1; 46 my $lines=`ar t '$inFiles[$i]'`; 47 my @lines = split(/\n/, $lines); 48 $countMembers += ($#lines + 1); 49 $members{$inFiles[$i]} = [@lines]; 50 } else { 51 print STDERR "Weird library name: $inFiles[$i]; skipping it"; 52 } 53 } else { 54 print STDERR "Repeated input (ignored): $inFiles[$i]\n"; 55 } 56} 57 58print STDERR "Found $countMembers members in $countLibs libraries\n"; 59 60# Update the list of input files (remove repetitions) 61@inFiles = @tmp; 62 63# Given a possibly relative path, compute the full path 64sub fullPath { 65 my ($name) = @_; 66 if($name =~ m@^/@) { 67 # It's already the full path 68 return $name; 69 } else { 70 return "$currDir/$name"; 71 } 72} 73 74# Unpack files and create the list of members with relative paths into tmpDir 75my @allMembers=(); 76 77mkdir($tmpDir, 0755) or die "Cannot create $tmpDir/: $?"; 78for(my $i=0; $i<=$#inFiles; $i++) { 79 my $libName = $libName{$inFiles[$i]}; 80 my $file = fullPath($inFiles[$i]); 81 print STDERR "Unpacking $libName\n"; 82 mkdir("$tmpDir/$libName", 0755) 83 or die "Cannot create $tmpDir/$libName: $?"; 84 system("cd '$tmpDir/$libName'; ar x '$file'") 85 && die "Cannot extract from archive $file: $?"; 86 my @names=@{$members{$inFiles[$i]}}; 87 for(my $j=0; $j<=$#names; $j++) { 88 if ($names[$j] =~ /^.*\.o/i) { 89 push @allMembers, "'$tmpDir/$libName/$names[$j]'"; 90 } 91 } 92} 93 94# Create the list of all members 95my $allMembers = join(" ", @allMembers); 96print "$allMembers"; 97