1 | #!/usr/bin/perl |
---|
2 | # ========================================================= # |
---|
3 | # # |
---|
4 | # File : build_fat_tarball.pl # |
---|
5 | # Purpose : pack an executable with dynamic libs # |
---|
6 | # # |
---|
7 | # Coded by Ralf Westram (coder@reallysoft.de) in Jun 22 # |
---|
8 | # http://www.arb-home.de/ # |
---|
9 | # # |
---|
10 | # ========================================================= # |
---|
11 | |
---|
12 | use strict; |
---|
13 | use warnings; |
---|
14 | |
---|
15 | sub die_usage($) { |
---|
16 | my ($msg) = @_; |
---|
17 | |
---|
18 | print STDERR "Usage: build_fat_tarball.pl <binary> <readme> <tarball>\n"; |
---|
19 | print STDERR "Purpose: pack <binary> plus required dynamic libraries into <tarball>\n"; |
---|
20 | |
---|
21 | die "$msg\n "; |
---|
22 | } |
---|
23 | |
---|
24 | sub skip_lib($) { |
---|
25 | my ($lib) = @_; |
---|
26 | # result: 0=include lib, 1=skip lib, 2=include, but inactive |
---|
27 | |
---|
28 | return 1 if $lib =~ /^\/lib\//o; # ignore libs in /lib |
---|
29 | return 2 if $lib =~ /libglib/o; # deactivate libglib |
---|
30 | return 0; |
---|
31 | } |
---|
32 | |
---|
33 | sub find_dynamic_libs($) { |
---|
34 | my ($binary) = @_; |
---|
35 | # result: array of dynamic libraries to include |
---|
36 | # if library name starts with '-' => want library included, but deactivated |
---|
37 | |
---|
38 | my @libs = (); |
---|
39 | my $cmd = 'ldd '.$binary; |
---|
40 | open(LDD, $cmd.'|') || die "failed to fork '$cmd' (Reason: $!)"; |
---|
41 | my $line; |
---|
42 | my $reg = qr/\s*([^\s]*)\s*=>\s*([^\s]*)\s*\(.*\)/; |
---|
43 | while (defined($line=<LDD>)) { |
---|
44 | chomp($line); |
---|
45 | if ($line =~ /$reg/) { |
---|
46 | my ($libname,$libfull) = ($1,$2); |
---|
47 | |
---|
48 | if ($libfull =~ /^-/o) { die "library names may not start with '-' ($libfull)"; } # when this occurs: fix separator used here |
---|
49 | if (not -e $libfull) { die "dynamic library $libfull does not exist"; } |
---|
50 | |
---|
51 | my $skip = skip_lib($libfull); |
---|
52 | if ($skip==1) { |
---|
53 | print "- ignoring '$libfull'\n"; |
---|
54 | } |
---|
55 | else { |
---|
56 | print "- include '$libfull'"; |
---|
57 | if ($skip==2) { |
---|
58 | print " (inactive in subdir)"; |
---|
59 | $libfull = '-'.$libfull; |
---|
60 | } |
---|
61 | print "\n"; |
---|
62 | push @libs, $libfull; |
---|
63 | } |
---|
64 | } |
---|
65 | } |
---|
66 | close(LDD) || die "failed to execute '$cmd' (Reason: $! exitcode=$?)"; |
---|
67 | return @libs; |
---|
68 | } |
---|
69 | |
---|
70 | sub split_path_name($) { |
---|
71 | my ($file) = @_; |
---|
72 | if ($file =~ /^(.*)\/([^\/]*)$/o) { |
---|
73 | return ($1, $2); |
---|
74 | } |
---|
75 | else { |
---|
76 | die "failed to detect path of '$file'"; |
---|
77 | } |
---|
78 | } |
---|
79 | |
---|
80 | sub add_file_nopath($$) { |
---|
81 | my ($file, $mode) = @_; |
---|
82 | if (not -e $file) { die "no such file: $file (cannot add to tarball)"; } |
---|
83 | |
---|
84 | my ($path, $name) = split_path_name($file); |
---|
85 | |
---|
86 | if ($mode==2) { |
---|
87 | my ($path2, $name2) = split_path_name($path); |
---|
88 | ($path, $name) = ($path2, $name2.'/'.$name); |
---|
89 | } |
---|
90 | |
---|
91 | return '--directory='.$path.' '.$name; |
---|
92 | } |
---|
93 | |
---|
94 | sub main() { |
---|
95 | my $args = scalar(@ARGV); |
---|
96 | if ($args<3) { die_usage("Error: missing arguments"); } |
---|
97 | |
---|
98 | my $binary = shift(@ARGV); |
---|
99 | my $readme = shift(@ARGV); |
---|
100 | my $tarball = shift(@ARGV); |
---|
101 | |
---|
102 | if (not -x $binary) { |
---|
103 | if (-e $binary) { die "Not an executable: $binary"; } |
---|
104 | die "No such file: $binary"; |
---|
105 | } |
---|
106 | |
---|
107 | print "Pack fat tarball for $binary:\n"; |
---|
108 | |
---|
109 | my @dyna_libs = find_dynamic_libs($binary); |
---|
110 | if (scalar(@dyna_libs)<1) { die "$binary does not refer to any dynamic libs"; } |
---|
111 | |
---|
112 | my $cmd = "tar -zcf $tarball --owner=0 --group=0 --dereference ".add_file_nopath($binary, 1); |
---|
113 | $cmd .= ' '.add_file_nopath($readme, 1); |
---|
114 | foreach my $lib (@dyna_libs) { |
---|
115 | if ($lib =~ /^-/) { |
---|
116 | my $_LIB = $'; |
---|
117 | $cmd .= ' '.add_file_nopath($_LIB, 2); |
---|
118 | } |
---|
119 | else { |
---|
120 | $cmd .= ' '.add_file_nopath($lib, 1); |
---|
121 | } |
---|
122 | } |
---|
123 | |
---|
124 | system($cmd)==0 || die "error executing '$cmd' (exitcode=$?)\n"; |
---|
125 | |
---|
126 | print `ls -al -h $tarball`; |
---|
127 | } |
---|
128 | |
---|
129 | main(); |
---|