]> git.donarmstrong.com Git - debhelper.git/blob - dh_strip
reorder
[debhelper.git] / dh_strip
1 #!/usr/bin/perl -w
2
3 =head1 NAME
4
5 dh_strip - strip executables, shared libraries, and some static libraries
6
7 =cut
8
9 use strict;
10 use File::Find;
11 use Debian::Debhelper::Dh_Lib;
12
13 =head1 SYNOPSIS
14
15 B<dh_strip> [S<I<debhelper options>>] [B<-X>I<item>] [B<--dbg-package=>I<package>] [B<--keep-debug>]
16
17 =head1 DESCRIPTION
18
19 B<dh_strip> is a debhelper program that is responsible for stripping
20 executables, shared libraries, and static libraries that are not used for
21 debugging.
22
23 This program examines your package build directories and works out what
24 to strip on its own. It uses L<file(1)> and file permissions and filenames
25 to figure out what files are shared libraries (F<*.so>), executable binaries,
26 and static (F<lib*.a>) and debugging libraries (F<lib*_g.a>, F<debug/*.so>), and
27 strips each as much as is possible. (Which is not at all for debugging
28 libraries.) In general it seems to make very good guesses, and will do the
29 right thing in almost all cases.
30
31 Since it is very hard to automatically guess if a file is a
32 module, and hard to determine how to strip a module, B<dh_strip> does not
33 currently deal with stripping binary modules such as F<.o> files.
34
35 =head1 OPTIONS
36
37 =over 4
38
39 =item B<-X>I<item>, B<--exclude=>I<item>
40
41 Exclude files that contain I<item> anywhere in their filename from being
42 stripped. You may use this option multiple times to build up a list of
43 things to exclude.
44
45 =item B<--dbg-package=>I<package>
46
47 Causes B<dh_strip> to save debug symbols stripped from the packages it acts on
48 as independent files in the package build directory of the specified debugging
49 package.
50
51 For example, if your packages are libfoo and foo and you want to include a
52 I<foo-dbg> package with debugging symbols, use B<dh_strip --dbg-package=>I<foo-dbg>.
53
54 Note that this option behaves significantly different in debhelper
55 compatibility levels 4 and below. Instead of specifying the name of a debug
56 package to put symbols in, it specifies a package (or packages) which
57 should have separated debug symbols, and the separated symbols are placed
58 in packages with B<-dbg> added to their name.
59
60 =item B<-k>, B<--keep-debug>
61
62 Debug symbols will be retained, but split into an independent
63 file in F<usr/lib/debug/> in the package build directory. B<--dbg-package>
64 is easier to use than this option, but this option is more flexible.
65
66 =back
67
68 =head1 NOTES
69
70 If the B<DEB_BUILD_OPTIONS> environment variable contains B<nostrip>, nothing
71 will be stripped, in accordance with Debian policy (section 10.1
72 "Binaries").
73
74 =head1 CONFORMS TO
75
76 Debian policy, version 3.0.1
77
78 =cut
79
80 init(options => {
81         "keep-debug" => \$dh{K_FLAG},
82 });
83
84 # This variable can be used to turn off stripping (see Policy).
85 if (get_buildoption('nostrip')) {
86         exit;
87 }
88
89 my $objcopy = cross_command("objcopy");
90 my $strip = cross_command("strip");
91
92 # I could just use `file $_[0]`, but this is safer
93 sub get_file_type {
94         my $file=shift;
95         open (FILE, '-|') # handle all filenames safely
96                 || exec('file', $file)
97                 || die "can't exec file: $!";
98         my $type=<FILE>;
99         close FILE;
100         return $type;
101 }
102
103 # Check if a file is an elf binary, shared library, or static library,
104 # for use by File::Find. It'll fill the following 3 arrays with anything
105 # it finds:
106 my (@shared_libs, @executables, @static_libs);
107 sub testfile {
108         return if -l $_ or -d $_; # Skip directories and symlinks always.
109         
110         # See if we were asked to exclude this file.
111         # Note that we have to test on the full filename, including directory.
112         my $fn="$File::Find::dir/$_";
113         foreach my $f (@{$dh{EXCLUDE}}) {
114                 return if ($fn=~m/\Q$f\E/);
115         }
116
117         # Is it a debug library in a debug subdir?
118         return if $fn=~m/debug\/.*\.so/;
119
120         # Does its filename look like a shared library?
121         # (*.cmxs are OCaml native code shared libraries)
122         if (m/.*\.(so.*?|cmxs$)/) {
123                 # Ok, do the expensive test.
124                 my $type=get_file_type($_);
125                 if ($type=~m/.*ELF.*shared.*/) {
126                         push @shared_libs, $fn;
127                         return;
128                 }
129         }
130         
131         # Is it executable? -x isn't good enough, so we need to use stat.
132         my (undef,undef,$mode,undef)=stat(_);
133         if ($mode & 0111) {
134                 # Ok, expensive test.
135                 my $type=get_file_type($_);
136                 if ($type=~m/.*ELF.*(executable|shared).*/) {
137                         push @executables, $fn;
138                         return;
139                 }
140         }
141         
142         # Is it a static library, and not a debug library?
143         if (m/lib.*\.a$/ && ! m/.*_g\.a$/) {
144                 # Is it a binary file, or something else (maybe a liner
145                 # script on Hurd, for example? I don't use file, because
146                 # file returns a variety of things on static libraries.
147                 if (-B $_) {
148                         push @static_libs, $fn;
149                         return;
150                 }
151         }
152 }
153
154 sub make_debug {
155         my $file=shift;
156         my $tmp=shift;
157         my $desttmp=shift;
158         
159         # Don't try to copy debug symbols out if the file is already
160         # stripped.
161         return unless get_file_type($file) =~ /not stripped/;
162
163         my ($base_file)=$file=~/^\Q$tmp\E(.*)/;
164         my $debug_path;
165         if (! compat(8) && 
166             `readelf -n $file`=~ /^\s+Build ID: ([0-9a-f]{2})([0-9a-f]+)$/m) {
167                 $debug_path=$desttmp."/usr/lib/debug/.build-id/$1/$2.debug"
168         }
169         else {
170                 $debug_path=$desttmp."/usr/lib/debug/".$base_file;
171         }
172         my $debug_dir=dirname($debug_path);
173         if (! -d $debug_dir) {
174                 doit("install", "-d", $debug_dir);
175         }
176         if (compat(8)) {
177                 doit($objcopy, "--only-keep-debug", $file, $debug_path);
178         }
179         else {
180                 doit($objcopy, "--only-keep-debug", "--compress-debug-sections", $file, $debug_path);
181         }
182         # No reason for this to be executable.
183         doit("chmod", 644, $debug_path);
184         return $debug_path;
185 }
186
187 sub attach_debug {
188         my $file=shift;
189         my $debug_path=shift;
190         doit($objcopy, "--add-gnu-debuglink", $debug_path, $file);
191 }
192
193 foreach my $package (@{$dh{DOPACKAGES}}) {
194         my $tmp=tmpdir($package);
195
196         # Support for keeping the debugging symbols in a detached file.
197         my $keep_debug=$dh{K_FLAG};
198         my $debugtmp=$tmp;
199         if (! compat(4)) {
200                 if (ref $dh{DEBUGPACKAGES}) {
201                         $keep_debug=1;
202                         # Note that it's only an array for the v4 stuff;
203                         # for v5 only one value is used.
204                         my $debugpackage=@{$dh{DEBUGPACKAGES}}[0];
205                         if (! grep { $_ eq $debugpackage } getpackages()) {
206                                 error("debug package $debugpackage is not listed in the control file");
207                         }
208                         $debugtmp=tmpdir($debugpackage);
209                 }
210         }
211         else {
212                 if (ref $dh{DEBUGPACKAGES} && grep { $_ eq $package } @{$dh{DEBUGPACKAGES}}) {
213                         $keep_debug=1;
214                         $debugtmp=tmpdir($package."-dbg");
215                 }
216         }
217         
218         @shared_libs=@executables=@static_libs=();
219         find(\&testfile,$tmp);
220
221         foreach (@shared_libs) {
222                 my $debug_path = make_debug($_, $tmp, $debugtmp) if $keep_debug;
223                 # Note that all calls to strip on shared libs
224                 # *must* inclde the --strip-unneeded.
225                 doit($strip,"--remove-section=.comment",
226                         "--remove-section=.note","--strip-unneeded",$_);
227                 attach_debug($_, $debug_path) if defined $debug_path;
228         }
229         
230         foreach (@executables) {
231                 my $debug_path = make_debug($_, $tmp, $debugtmp) if $keep_debug;
232                 doit($strip,"--remove-section=.comment",
233                         "--remove-section=.note",$_);
234                 attach_debug($_, $debug_path) if defined $debug_path;
235         }
236
237         foreach (@static_libs) {
238                 doit($strip,"--strip-debug",$_);
239         }
240 }
241
242 =head1 SEE ALSO
243
244 L<debhelper(7)>
245
246 This program is a part of debhelper.
247
248 =head1 AUTHOR
249
250 Joey Hess <joeyh@debian.org>
251
252 =cut