]> git.donarmstrong.com Git - debhelper.git/blob - dh
dh: Document --no-act. Closes: #557505
[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>[,I<addon>,...]] [B<--list>] [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>[,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, or multiple addons can be listed, separated by commas.
53 This is used when there is a third-party package that provides
54 debhelper commands. See the PROGRAMMING file for documentation about
55 the sequence addon interface.
56
57 =item B<--without> I<addon>
58
59 The inverse of --with, disables using the given addon.
60
61 =item B<--list>, B<-l>
62
63 List all available addons.
64
65 =item B<--until> I<cmd>
66
67 Run commands in the sequence until and including I<cmd>, then stop.
68
69 =item B<--before> I<cmd>
70
71 Run commands in the sequence before I<cmd>, then stop.
72
73 =item B<--after> I<cmd>
74
75 Run commands in the sequence that come after I<cmd>.
76
77 =item B<--remaining>
78
79 Run all commands in the sequence that have yet to be run.
80
81 =item B<--no-act>
82
83 Prints commands that would run for a given sequence, but does not run them.
84
85 =back
86
87 All other options passed to dh are passed on to each command it runs. This
88 can be used to set an option like "-v" or "-X" or "-N", as well as for more
89 specialised options.
90
91 =head1 COMMAND SPECIFICATION
92
93 I<cmd> can be a full name of a debhelper command, or a substring. It'll first
94 search for a command in the sequence exactly matching the name, to avoid any
95 ambiguity. If there are multiple substring matches, the last one in the
96 sequence will be used.
97
98 =cut
99
100 sub command_pos {
101         my $command=shift;
102         my @sequence=@_;
103
104         foreach my $i (0..$#sequence) {
105                 if ($command eq $sequence[$i]) {
106                         return $i;
107                 }
108         }
109
110         my @matches;
111         foreach my $i (0..$#sequence) {
112                 if ($sequence[$i] =~ /\Q$command\E/) {
113                         push @matches, $i;
114                 }
115         }
116         if (! @matches) {
117                 error "command specification \"$command\" does not match any command in the sequence"
118         }
119         else {
120                 return pop @matches;
121         }
122 }
123
124 =head1 EXAMPLES
125
126 To see what commands are included in a sequence, without actually doing
127 anything:
128
129         dh binary-arch --no-act
130
131 This is a very simple rules file, for packages where the default sequences of
132 commands work with no additional options.
133
134         #!/usr/bin/make -f
135         %:
136                 dh $@
137
138 Often you'll want to pass an option to a specific debhelper command. The
139 easy way to do with is by adding an override target for that command.
140         
141         #!/usr/bin/make -f
142         %:
143                 dh $@
144
145         override_dh_strip:
146                 dh_strip -Xfoo
147                 
148         override_dh_installdocs:
149                 dh_installdocs README TODO
150
151 Sometimes the automated dh_auto_configure and dh_auto_build can't guess
152 what to do for a strange package. Here's how to avoid running either
153 and instead run your own commands.
154
155         #!/usr/bin/make -f
156         %:
157                 dh $@
158
159         override_dh_auto_configure:
160                 ./mondoconfig
161
162         override_dh_auto_build:
163                 make universe-explode-in-delight
164
165 Another common case is wanting to do something manually before or
166 after a particular debhelper command is run.
167
168         #!/usr/bin/make -f
169         %:
170                 dh $@
171
172         override_dh_fixperms:
173                 dh_fixperms
174                 chmod 4755 debian/foo/usr/bin/foo
175
176 If your package is a python package, dh will use dh_pysupport by
177 default. This is how to use dh_pycentral instead.
178
179         #!/usr/bin/make -f
180         %:
181                 dh --with python-central $@
182
183 To patch your package using quilt, you can tell dh to use quilt's dh
184 sequence addons like this:
185         
186         #!/usr/bin/make -f
187         %:
188                 dh --with quilt $@
189
190 Here is an example of overriding where the dh_auto_* commands find
191 the package's source, for a package where the source is located in a
192 subdirectory. It also forces use of perl's Module::Build build system,
193 which can be necessary if debhelper wrongly detects that the package
194 uses MakeMaker.
195
196         #!/usr/bin/make -f
197         %:
198                 dh --sourcedirectory=src --buildsystem=perl_build $@
199
200 =cut
201
202 # Stash this away before init modifies it.
203 my @ARGV_orig=@ARGV;
204
205 # python-support is enabled by default, at least for now
206 # (and comes first so python-central loads later and can disable it).
207 unshift @ARGV, "--with=python-support";
208                 
209 # Disable complaints about unknown options for both dh and the commands
210 # it runs. This is done because dh accepts and passes on options that may
211 # be specific to only some debhelper commands.
212 $ENV{DH_IGNORE_UNKNOWN_OPTIONS}=1;
213
214 init(options => {
215         "until=s" => \$dh{UNTIL},
216         "after=s" => \$dh{AFTER},
217         "before=s" => \$dh{BEFORE},
218         "remaining" => \$dh{REMAINING},
219         "with=s" => sub {
220                 my ($option,$value)=@_;
221                 push @{$dh{WITH}},split(",", $value);
222         },
223         "without=s" => sub {
224                 my ($option,$value)=@_;
225                 @{$dh{WITH}} = grep { $_ ne $value } @{$dh{WITH}};
226         },
227         "l" => \$dh{LIST},
228         "list" => \$dh{LIST},
229 });
230 inhibit_log();
231
232 # If make is using a jobserver, but it is not available
233 # to this process, clean out MAKEFLAGS. This avoids
234 # ugly warnings when calling make.
235 if (is_make_jobserver_unavailable()) {
236         clean_jobserver_makeflags();
237 }
238
239 # Definitions of sequences.
240 my %sequences;
241 $sequences{build} = [qw{
242         dh_testdir
243         dh_auto_configure
244         dh_auto_build
245         dh_auto_test
246 }],
247 $sequences{clean} = [qw{
248         dh_testdir
249         dh_auto_clean
250         dh_clean
251 }];
252 $sequences{install} = [@{$sequences{build}}, qw{
253         dh_testroot
254         dh_prep
255         dh_installdirs
256         dh_auto_install
257
258         dh_install
259         dh_installdocs
260         dh_installchangelogs
261         dh_installexamples
262         dh_installman
263
264         dh_installcatalogs
265         dh_installcron
266         dh_installdebconf
267         dh_installemacsen
268         dh_installifupdown
269         dh_installinfo
270         dh_installinit
271         dh_installmenu
272         dh_installmime
273         dh_installmodules
274         dh_installlogcheck
275         dh_installlogrotate
276         dh_installpam
277         dh_installppp
278         dh_installudev
279         dh_installwm
280         dh_installxfonts
281         dh_bugfiles
282         dh_lintian
283         dh_gconf
284         dh_icons
285         dh_perl
286         dh_usrlocal
287
288         dh_link
289         dh_compress
290         dh_fixperms
291 }];
292 my @b=qw{
293         dh_installdeb
294         dh_gencontrol
295         dh_md5sums
296         dh_builddeb
297 };
298 $sequences{'binary-indep'} = [@{$sequences{install}}, @b];
299 $sequences{binary} = [@{$sequences{install}}, qw{
300         dh_strip
301         dh_makeshlibs
302         dh_shlibdeps
303 }, @b];
304 $sequences{'binary-arch'} = [@{$sequences{binary}}];
305
306 # Additional command options
307 my %command_opts;
308
309 # sequence addon interface
310 sub _insert {
311         my $offset=shift;
312         my $existing=shift;
313         my $new=shift;
314         foreach my $sequence (keys %sequences) {
315                 my @list=@{$sequences{$sequence}};
316                 next unless grep $existing, @list;
317                 my @new;
318                 foreach my $command (@list) {
319                         if ($command eq $existing) {
320                                 push @new, $new if $offset < 0;
321                                 push @new, $command;
322                                 push @new, $new if $offset > 0;
323                         }
324                         else {
325                                 push @new, $command;
326                         }
327                 }
328                 $sequences{$sequence}=\@new;
329         }
330 }
331 sub insert_before {
332         _insert(-1, @_);
333 }
334 sub insert_after {
335         _insert(1, @_);
336 }
337 sub remove_command {
338         my $command=shift;
339         foreach my $sequence (keys %sequences) {
340                 $sequences{$sequence}=[grep { $_ ne $command } @{$sequences{$sequence}}];
341         }
342         
343 }
344 sub add_command {
345         my $command=shift;
346         my $sequence=shift;
347         unshift @{$sequences{$sequence}}, $command;
348 }
349 sub add_command_options {
350         my $command=shift;
351         push @{$command_opts{$command}}, @_;
352 }
353 sub remove_command_options {
354         my $command=shift;
355         if (@_) {
356                 # Remove only specified options
357                 if (my $opts = $command_opts{$command}) {
358                         foreach my $opt (@_) {
359                                 $opts = [ grep { $_ ne $opt } @$opts ];
360                         }
361                         $command_opts{$command} = $opts;
362                 }
363         }
364         else {
365                 # Clear all additional options
366                 delete $command_opts{$command};
367         }
368 }
369
370 if ($dh{LIST}) {
371         my %addons;
372
373         for my $inc (@INC) {
374                 eval q{use File::Spec};
375                 my $path = File::Spec->catdir($inc, "Debian/Debhelper/Sequence");
376                 if (-d $path) {
377                         for my $module_path (glob "$path/*.pm") {
378                                 my $name = basename($module_path);
379                                 $name =~ s/\.pm$//;
380                                 $name =~ s/_/-/g;
381                                 $addons{$name} = 1;
382                         }
383                 }
384         }
385
386         for my $name (sort keys %addons) {
387                 print "$name\n";
388         }
389
390         exit 0;
391 }
392
393 foreach my $addon (@{$dh{WITH}}) {
394         my $mod="Debian::Debhelper::Sequence::$addon";
395         $mod=~s/-/_/g;
396         eval "use $mod";
397         if ($@) {
398                 error("unable to load addon $addon: $@");
399         }
400 }
401
402 # Get the sequence of commands to run.
403 if (! @ARGV) {
404         error "specify a sequence to run";
405 }
406 my $sequence=shift;
407 if ($sequence eq 'debian/rules' ||
408     $sequence =~ /^override_dh_/) {
409         # make -B causes the rules file to be run as a target
410         # and support completly empty override targets
411         exit 0
412 }       
413 elsif (! exists $sequences{$sequence}) {
414         error "Unknown sequence $sequence (choose from: ".
415                 join(" ", sort keys %sequences).")";
416 }
417 my @sequence=@{$sequences{$sequence}};
418
419 # The list of all packages that can be acted on.
420 my @packages=@{$dh{DOPACKAGES}};
421
422 # Get the options to pass to commands in the sequence.
423 # Filter out options intended only for this program.
424 my @options;
425 if ($sequence eq 'binary-arch') {
426         push @options, "-a";
427         # as an optimisation, remove from the list any packages
428         # that are not arch dependent
429         my %arch_packages = map { $_ => 1 } getpackages("arch");
430         @packages = grep { $arch_packages{$_} } @packages;
431 }
432 elsif ($sequence eq 'binary-indep') {
433         push @options, "-i";
434         # ditto optimisation for arch indep
435         my %indep_packages = map { $_ => 1 } getpackages("indep");
436         @packages = grep { $indep_packages{$_} } @packages;
437 }
438 while (@ARGV_orig) {
439         my $opt=shift @ARGV_orig;
440         next if $opt eq $sequence;
441         if ($opt =~ /^--?(after|until|before|with|without)$/) {
442                 shift @ARGV_orig;
443                 next;
444         }
445         elsif ($opt =~ /^--?(no-act|remaining|(after|until|before|with|without)=)/) {
446                 next;
447         }
448         push @options, $opt;
449 }
450
451 # Figure out at what point in the sequence to start for each package.
452 my %logged;
453 my %startpoint;
454 foreach my $package (@packages) {
455         my @log=load_log($package, \%logged);
456         if ($dh{AFTER}) {
457                 # Run commands in the sequence that come after the
458                 # specified command.
459                 $startpoint{$package}=command_pos($dh{AFTER}, @sequence) + 1;
460                 # Write a dummy log entry indicating that the specified
461                 # command was, in fact, run. This handles the case where
462                 # no commands remain to run after it, communicating to
463                 # future dh instances that the specified command should not
464                 # be run again.
465                 write_log($sequence[$startpoint{$package}-1], $package);
466         }
467         elsif ($dh{REMAINING}) {
468                 # Start at the beginning so all remaining commands will get
469                 # run.
470                 $startpoint{$package}=0;
471         }
472         else {
473                 # Find the last logged command that is in the sequence, and
474                 # continue with the next command after it. If no logged
475                 # command is in the sequence, we're starting at the beginning..                         
476                 $startpoint{$package}=0;
477 COMMAND:        foreach my $command (reverse @log) {
478                         foreach my $i (0..$#sequence) {
479                                 if ($command eq $sequence[$i]) {
480                                         $startpoint{$package}=$i+1;
481                                         last COMMAND;
482                                 }
483                         }
484                 }
485         }
486 }
487
488 # Figure out what point in the sequence to go to.
489 my $stoppoint=$#sequence;
490 if ($dh{UNTIL}) {
491         $stoppoint=command_pos($dh{UNTIL}, @sequence);
492 }
493 elsif ($dh{BEFORE}) {
494         $stoppoint=command_pos($dh{BEFORE}, @sequence) - 1;
495 }
496
497 # Now run the commands in the sequence.
498 foreach my $i (0..$stoppoint) {
499         # Figure out which packages need to run this command.
500         my @exclude;
501         foreach my $package (@packages) {
502                 if ($startpoint{$package} > $i ||
503                     $logged{$package}{$sequence[$i]}) {
504                         push @exclude, $package;
505                 }
506         }
507         
508         if (@exclude eq @packages) {
509                 # Command already done for all packages.
510                 next;
511         }
512
513         run($sequence[$i], \@packages, \@exclude, @options);
514 }
515
516 sub run {
517         my $command=shift;
518         my @packages=@{shift()};
519         my @exclude=@{shift()};
520         my @options=@_;
521         
522         # If some packages are excluded, add flags
523         # to prevent them from being acted on.
524         push @options, map { "-N$_" } @exclude;
525
526         # Check for override targets in debian/rules and
527         # run them instead of running the command directly.
528         my $override_command;
529         if (rules_explicit_target("override_".$command)) {
530                 $override_command=$command;
531                 # This passes the options through to commands called
532                 # inside the target.
533                 $ENV{DH_INTERNAL_OPTIONS}=join("\x1e", @options);
534                 $command="debian/rules";
535                 @options="override_".$override_command;
536         }
537         else {
538                 # Pass additional command options if any
539                 unshift @options, @{$command_opts{$command}} if exists $command_opts{$command};
540         }
541
542         # 3 space indent lines the command being run up under the 
543         # sequence name after "dh ".
544         print "   ".escape_shell($command, @options)."\n";
545
546         if (! $dh{NO_ACT}) {
547                 my $ret=system($command, @options);
548                 if ($ret >> 8 != 0) {
549                         exit $ret >> 8;
550                 }
551                 elsif ($ret) {
552                         exit 1;
553                 }
554
555                 if (defined $override_command) {
556                         delete $ENV{DH_INTERNAL_OPTIONS};
557                         # Need to handle logging for overriden commands here,
558                         # because the actual debhelper command may not have
559                         # been run by the rules file target.
560                         # (But avoid logging for dh_clean since it removes
561                         # the log earlier.)
562                         if ($override_command ne 'dh_clean') {
563                                 my %packages=map { $_ => 1 } @packages;
564                                 map { delete $packages{$_} } @exclude;
565                                 write_log($override_command, keys %packages);
566                         }
567                 }
568         }
569 }
570
571 {
572 my %targets;
573 my $rules_parsed;
574
575 sub rules_explicit_target {
576         # Checks if a specified target exists as an explicit target
577         # in debian/rules. 
578         my $target=shift;
579         
580         if (! $rules_parsed) {  
581                 my $processing_targets = 0;
582                 my $not_a_target = 0;
583                 open(MAKE, "LC_ALL=C make -Rrnpsf debian/rules debhelper-fail-me 2>/dev/null |");
584                 while (<MAKE>) {
585                         if ($processing_targets) {
586                                 if (/^# Not a target:/) {
587                                         $not_a_target = 1;
588                                 }
589                                 else {
590                                         if (!$not_a_target && /^([^#:]+)::?/) {
591                                                 # Target is defined.
592                                                 # NOTE: if it is a depenency
593                                                 # of .PHONY it will be
594                                                 # defined too but that's ok.
595                                                 $targets{$1} = 1;
596                                         }
597                                         # "Not a target:" is always followed by
598                                         # a target name, so resetting this one
599                                         # here is safe.
600                                         $not_a_target = 0;
601                                 }
602                         } elsif (/^# Files$/) {
603                                 $processing_targets = 1;
604                         }
605                 }
606                 close MAKE;
607                 $rules_parsed = 1;
608         }
609
610         return exists $targets{$target};
611 }
612
613 }
614
615 =head1 SEE ALSO
616
617 L<debhelper(7)>
618
619 This program is a part of debhelper.
620
621 =head1 AUTHOR
622
623 Joey Hess <joeyh@debian.org>
624
625 =cut