]> git.donarmstrong.com Git - debhelper.git/blob - dh
releasing version 7.2.8
[debhelper.git] / dh
1 #!/usr/bin/perl -w
2
3 =head1 NAME
4
5 dh - debhelper command sequencer
6
7 =cut
8
9 use strict;
10 use Debian::Debhelper::Dh_Lib;
11
12 =head1 SYNOPSIS
13
14 B<dh> sequence [B<--with> I<addon>] [B<--until> I<cmd>] [B<--before> I<cmd>] [B<--after> I<cmd>] [B<--remaining>] [S<I<debhelper options>>]
15
16 =head1 DESCRIPTION
17
18 dh runs a sequence of debhelper commands. The supported sequences
19 correspond to the targets of a debian/rules file: "build", "clean",
20 "install", "binary-arch", "binary-indep", and "binary".
21
22 Commands in the binary-indep sequence are passed the "-i" option to ensure
23 they only work on binary independent packages, and commands in the
24 binary-arch sequences are passed the "-a" option to ensure they only work
25 on architecture dependent packages.
26
27 Each debhelper command will record when it's successfully run in
28 debian/package.debhelper.log. (Which dh_clean deletes.) So dh can tell
29 which commands have already been run, for which packages, and skip running
30 those commands again.
31
32 Each time dh is run, it examines the log, and finds the last logged command
33 that is in the specified sequence. It then continues with the next command
34 in the sequence. The B<--until>, B<--before>, B<--after>, and B<--remaining>
35 options can override this behavior.
36
37 If debian/rules contains a target with a name like "override_I<dh_command>",
38 then when it gets to that command in the sequence, dh will run that
39 target from the rules file, rather than running the actual command. The
40 override target can then run the command with additional options, or run
41 entirely different commands instead. (Note that to use this feature,
42 you should Build-Depend on debhelper 7.0.50 or above.)
43
44 =head1 OPTIONS
45
46 =over 4
47
48 =item B<--with> I<addon>
49
50 Add the debhelper commands specified by the given addon to appropriate places
51 in the sequence of commands that is run. This option can be repeated more
52 than once, and is used when there is a third-party package that provides
53 debhelper commands. See the PROGRAMMING file for documentation about
54 the sequence addon interface.
55
56 =item B<--until> I<cmd>
57
58 Run commands in the sequence until and including I<cmd>, then stop.
59
60 =item B<--before> I<cmd>
61
62 Run commands in the sequence before I<cmd>, then stop.
63
64 =item B<--after> I<cmd>
65
66 Run commands in the sequence that come after I<cmd>.
67
68 =item B<--remaining>
69
70 Run all commands in the sequence that have yet to be run.
71
72 =back
73
74 All other options passed to dh are passed on to each command it runs. This
75 can be used to set an option like "-v" or "-X" or "-N", as well as for more
76 specialised options.
77
78 =head1 COMMAND SPECIFICATION
79
80 I<cmd> can be a full name of a debhelper command, or a substring. It'll first
81 search for a command in the sequence exactly matching the name, to avoid any
82 ambiguity. If there are multiple substring matches, the last one in the
83 sequence will be used.
84
85 =cut
86
87 sub command_pos {
88         my $command=shift;
89         my @sequence=@_;
90
91         foreach my $i (0..$#sequence) {
92                 if ($command eq $sequence[$i]) {
93                         return $i;
94                 }
95         }
96
97         my @matches;
98         foreach my $i (0..$#sequence) {
99                 if ($sequence[$i] =~ /\Q$command\E/) {
100                         push @matches, $i;
101                 }
102         }
103         if (! @matches) {
104                 error "command specification \"$command\" does not match any command in the sequence"
105         }
106         else {
107                 return pop @matches;
108         }
109 }
110
111 =head1 EXAMPLES
112
113 To see what commands are included in a sequence, without actually doing
114 anything:
115
116         dh binary-arch --no-act
117
118 This is a very simple rules file, for packages where the default sequences of
119 commands work with no additional options.
120
121         #!/usr/bin/make -f
122         %:
123                 dh $@
124
125 Often you'll want to pass an option to a specific debhelper command. The
126 easy way to do with is by adding an override target for that command.
127         
128         #!/usr/bin/make -f
129         %:
130                 dh $@
131
132         override_dh_strip:
133                 dh_strip -Xfoo
134                 
135         override_dh_installdocs:
136                 dh_installdocs README TODO
137
138 Sometimes the automated dh_auto_configure and dh_auto_build can't guess
139 what to do for a strange package. Here's how to avoid running either
140 and instead run your own commands.
141
142         #!/usr/bin/make -f
143         %:
144                 dh $@
145
146         override_dh_auto_configure:
147                 ./mondoconfig
148
149         override_dh_auto_build:
150                 make universe-explode-in-delight
151
152 Another common case is wanting to do something manually before or
153 after a particular debhelper command is run.
154
155         #!/usr/bin/make -f
156         %:
157                 dh $@
158
159         override_dh_fixperms:
160                 dh_fixperms
161                 chmod 4755 debian/foo/usr/bin/foo
162
163 If your package is a python package, dh will use dh_pysupport by
164 default. This is how to use dh_pycentral instead.
165
166         #!/usr/bin/make -f
167         %:
168                 dh --with python-central $@
169
170 =cut
171
172 # Stash this away before init modifies it.
173 my @ARGV_orig=@ARGV;
174
175 init(options => {
176         "until=s" => \$dh{UNTIL},
177         "after=s" => \$dh{AFTER},
178         "before=s" => \$dh{BEFORE},
179         "remaining" => \$dh{REMAINING},
180         "with=s" => sub {
181                 my ($option,$value)=@_;
182                 push @{$dh{WITH}},$value;
183         },
184 });
185 inhibit_log();
186
187 # Definitions of sequences.
188 my %sequences;
189 $sequences{build} = [qw{
190         dh_testdir
191         dh_auto_configure
192         dh_auto_build
193         dh_auto_test
194 }],
195 $sequences{clean} = [qw{
196         dh_testdir
197         dh_auto_clean
198         dh_clean
199 }];
200 $sequences{install} = [@{$sequences{build}}, qw{
201         dh_testroot
202         dh_prep
203         dh_installdirs
204         dh_auto_install
205
206         dh_install
207         dh_installdocs
208         dh_installchangelogs
209         dh_installexamples
210         dh_installman
211
212         dh_installcatalogs
213         dh_installcron
214         dh_installdebconf
215         dh_installcatalogs
216         dh_installemacsen
217         dh_installifupdown
218         dh_installinfo
219         dh_installinit
220         dh_installmenu
221         dh_installmime
222         dh_installmodules
223         dh_installlogcheck
224         dh_installlogrotate
225         dh_installpam
226         dh_installppp
227         dh_installudev
228         dh_installwm
229         dh_installxfonts
230         dh_bugfiles
231         dh_lintian
232         dh_gconf
233         dh_icons
234         dh_perl
235         dh_scrollkeeper
236         dh_usrlocal
237
238         dh_link
239         dh_compress
240         dh_fixperms
241 }];
242 my @b=qw{
243         dh_installdeb
244         dh_gencontrol
245         dh_md5sums
246         dh_builddeb
247 };
248 $sequences{'binary-indep'} = [@{$sequences{install}}, @b];
249 $sequences{binary} = [@{$sequences{install}}, qw{
250         dh_strip
251         dh_makeshlibs
252         dh_shlibdeps
253 }, @b];
254 $sequences{'binary-arch'} = [@{$sequences{binary}}];
255
256 # --with python-support is enabled by default, at least for now
257 unshift @{$dh{WITH}}, "python-support";
258
259 # sequence addon interface
260 sub _insert {
261         my $offset=shift;
262         my $existing=shift;
263         my $new=shift;
264         foreach my $sequence (keys %sequences) {
265                 my @list=@{$sequences{$sequence}};
266                 next unless grep $existing, @list;
267                 my @new;
268                 foreach my $command (@list) {
269                         if ($command eq $existing) {
270                                 push @new, $new if $offset < 0;
271                                 push @new, $command;
272                                 push @new, $new if $offset > 0;
273                         }
274                         else {
275                                 push @new, $command;
276                         }
277                 }
278                 $sequences{$sequence}=\@new;
279         }
280 }
281 sub insert_before {
282         _insert(-1, @_);
283 }
284 sub insert_after {
285         _insert(1, @_);
286 }
287 sub remove_command {
288         my $command=shift;
289         foreach my $sequence (keys %sequences) {
290                 $sequences{$sequence}=[grep { $_ ne $command } @{$sequences{$sequence}}];
291         }
292         
293 }
294 foreach my $addon (@{$dh{WITH}}) {
295         my $mod="Debian::Debhelper::Sequence::$addon";
296         $mod=~s/-/_/g;
297         eval "use $mod";
298         if ($@) {
299                 error("--with $addon not supported or failed to load module $mod");
300         }
301 }
302
303 # Get the sequence of commands to run.
304 if (! @ARGV) {
305         error "specify a sequence to run";
306 }
307 my $sequence=shift;
308 if ($sequence eq 'debian/rules' ||
309     $sequence =~ /^override_dh_/) {
310         # make -B causes the rules file to be run as a target
311         # and support completly empty override targets
312         exit 0
313 }       
314 elsif (! exists $sequences{$sequence}) {
315         error "Unknown sequence $sequence (choose from: ".
316                 join(" ", sort keys %sequences).")";
317 }
318 my @sequence=@{$sequences{$sequence}};
319
320 # The list of all packages that can be acted on.
321 my @packages=@{$dh{DOPACKAGES}};
322
323 # Get the options to pass to commands in the sequence.
324 # Filter out options intended only for this program.
325 my @options;
326 if ($sequence eq 'binary-arch') {
327         push @options, "-a";
328         # as an optimisation, remove from the list any packages
329         # that are not arch dependent
330         my %arch_packages = map { $_ => 1 } getpackages("arch");
331         @packages = grep { $arch_packages{$_} } @packages;
332 }
333 elsif ($sequence eq 'binary-indep') {
334         push @options, "-i";
335         # ditto optimisation for arch indep
336         my %indep_packages = map { $_ => 1 } getpackages("indep");
337         @packages = grep { $indep_packages{$_} } @packages;
338 }
339 while (@ARGV_orig) {
340         my $opt=shift @ARGV_orig;
341         next if $opt eq $sequence;
342         if ($opt =~ /^--?(after|until|before|with)$/) {
343                 shift @ARGV_orig;
344                 next;
345         }
346         elsif ($opt =~ /^--?(no-act|remaining|(after|until|before|with)=)/) {
347                 next;
348         }
349         push @options, $opt;
350 }
351
352 # Figure out at what point in the sequence to start for each package.
353 my %logged;
354 my %startpoint;
355 foreach my $package (@packages) {
356         my @log=load_log($package, \%logged);
357         if ($dh{AFTER}) {
358                 # Run commands in the sequence that come after the
359                 # specified command.
360                 $startpoint{$package}=command_pos($dh{AFTER}, @sequence) + 1;
361                 # Write a dummy log entry indicating that the specified
362                 # command was, in fact, run. This handles the case where
363                 # no commands remain to run after it, communicating to
364                 # future dh instances that the specified command should not
365                 # be run again.
366                 write_log($sequence[$startpoint{$package}-1], $package);
367         }
368         elsif ($dh{REMAINING}) {
369                 # Start at the beginning so all remaining commands will get
370                 # run.
371                 $startpoint{$package}=0;
372         }
373         else {
374                 # Find the last logged command that is in the sequence, and
375                 # continue with the next command after it. If no logged
376                 # command is in the sequence, we're starting at the beginning..                         
377                 $startpoint{$package}=0;
378 COMMAND:        foreach my $command (reverse @log) {
379                         foreach my $i (0..$#sequence) {
380                                 if ($command eq $sequence[$i]) {
381                                         $startpoint{$package}=$i+1;
382                                         last COMMAND;
383                                 }
384                         }
385                 }
386         }
387 }
388
389 # Figure out what point in the sequence to go to.
390 my $stoppoint=$#sequence;
391 if ($dh{UNTIL}) {
392         $stoppoint=command_pos($dh{UNTIL}, @sequence);
393 }
394 elsif ($dh{BEFORE}) {
395         $stoppoint=command_pos($dh{BEFORE}, @sequence) - 1;
396 }
397
398 # Now run the commands in the sequence.
399 foreach my $i (0..$stoppoint) {
400         # Figure out which packages need to run this command.
401         my @exclude;
402         foreach my $package (@packages) {
403                 if ($startpoint{$package} > $i ||
404                     $logged{$package}{$sequence[$i]}) {
405                         push @exclude, $package;
406                 }
407         }
408         
409         if (@exclude eq @packages) {
410                 # Command already done for all packages.
411                 next;
412         }
413
414         run($sequence[$i], \@packages, \@exclude, @options);
415 }
416
417 sub run {
418         my $command=shift;
419         my @packages=@{shift()};
420         my @exclude=@{shift()};
421         my @options=@_;
422         
423         # If some packages are excluded, add flags
424         # to prevent them from being acted on.
425         push @options, map { "-N$_" } @exclude;
426
427         # Check for override targets in debian/rules and
428         # run them instead of running the command directly.
429         my $override_command;
430         if (rules_explicit_target("override_".$command)) {
431                 $override_command=$command;
432                 # This passes the options through to commands called
433                 # inside the target.
434                 $ENV{DH_INTERNAL_OPTIONS}=join(" ", @options);
435                 $command="debian/rules";
436                 @options="override_".$override_command;
437         }
438
439         # 3 space indent lines the command being run up under the 
440         # sequence name after "dh ".
441         print "   ".escape_shell($command, @options)."\n";
442
443         if (! $dh{NO_ACT}) {
444                 my $ret=system($command, @options);
445                 if ($ret >> 8 != 0) {
446                         exit $ret >> 8;
447                 }
448                 elsif ($ret) {
449                         exit 1;
450                 }
451
452                 if (defined $override_command) {
453                         delete $ENV{DH_INTERNAL_OPTIONS};
454                         # Need to handle logging for overriden commands here,
455                         # because the actual debhelper command may not have
456                         # been run by the rules file target.
457                         my %packages=map { $_ => 1 } @packages;
458                         map { delete $packages{$_} } @exclude;
459                         write_log($override_command, keys %packages);
460                 }
461         }
462 }
463
464 {
465 my %targets;
466 my $rules_parsed;
467
468 sub rules_explicit_target {
469         # Checks if a specified target exists as an explicit target
470         # in debian/rules. 
471         my $target=shift;
472         
473         if (! $rules_parsed) {  
474                 my $processing_targets = 0;
475                 my $not_a_target = 0;
476                 open(MAKE, "LC_ALL=C make -Rrnpsf debian/rules debhelper-fail-me 2>/dev/null |");
477                 while (<MAKE>) {
478                         if ($processing_targets) {
479                                 if (/^# Not a target:/) {
480                                         $not_a_target = 1;
481                                 }
482                                 else {
483                                         if (!$not_a_target && /^([^#:]+)::?/) {
484                                                 # Target is defined.
485                                                 # NOTE: if it is a depenency
486                                                 # of .PHONY it will be
487                                                 # defined too but that's ok.
488                                                 $targets{$1} = 1;
489                                         }
490                                         # "Not a target:" is always followed by
491                                         # a target name, so resetting this one
492                                         # here is safe.
493                                         $not_a_target = 0;
494                                 }
495                         } elsif (/^# Files$/) {
496                                 $processing_targets = 1;
497                         }
498                 }
499                 close MAKE;
500                 $rules_parsed = 1;
501         }
502
503         return exists $targets{$target};
504 }
505
506 }
507
508 =head1 SEE ALSO
509
510 L<debhelper(7)>
511
512 This program is a part of debhelper.
513
514 =head1 AUTHOR
515
516 Joey Hess <joeyh@debian.org>
517
518 =cut