]> git.donarmstrong.com Git - debhelper.git/blob - dh
dh: The --before --after --until and --remaining options are deprecated. Use override...
[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> I<sequence> [B<--with> I<addon>[B<,>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 B<dh> runs a sequence of debhelper commands. The supported I<sequence>s
19 correspond to the targets of a F<debian/rules> file: B<build-arch>,
20 B<build-indep>, B<build>, B<clean>, B<install-indep>, B<install-arch>,
21 B<install>, B<binary-arch>, B<binary-indep>, and B<binary>.
22
23 Commands in the B<build-indep>, B<install-indep> and B<binary-indep>
24 sequences are passed the B<-i> option to ensure they only work on
25 architecture independent packages, and commands in the B<build-arch>,
26 B<install-arch> and B<binary-arch> sequences are passed the B<-a>
27 option to ensure they only work on architecture dependent packages.
28
29 If F<debian/rules> contains a target with a name like B<override_>I<dh_command>,
30 then when it would normally run I<dh_command>, B<dh> will instead call that
31 target. The override target can then run the command with additional options,
32 or run entirely different commands instead. See examples below. (Note that to
33 use this feature, you should Build-Depend on debhelper 7.0.50 or above.)
34
35 =head1 OPTIONS
36
37 =over 4
38
39 =item B<--with> I<addon>[B<,>I<addon> ...]
40
41 Add the debhelper commands specified by the given addon to appropriate places
42 in the sequence of commands that is run. This option can be repeated more
43 than once, or multiple addons can be listed, separated by commas.
44 This is used when there is a third-party package that provides
45 debhelper commands. See the F<PROGRAMMING> file for documentation about
46 the sequence addon interface.
47
48 =item B<--without> I<addon>
49
50 The inverse of B<--with>, disables using the given addon.
51
52 =item B<--list>, B<-l>
53
54 List all available addons.
55
56 =item B<--until> I<cmd>
57
58 Run commands in the sequence until and including I<cmd>, then stop.
59 (Deprecated)
60
61 =item B<--before> I<cmd>
62
63 Run commands in the sequence before I<cmd>, then stop.
64 (Deprecated)
65
66 =item B<--after> I<cmd>
67
68 Run commands in the sequence that come after I<cmd>.
69 (Deprecated)
70
71 =item B<--remaining>
72
73 Run all commands in the sequence that have yet to be run.
74 (Deprecated)
75
76 =item B<--no-act>
77
78 Prints commands that would run for a given sequence, but does not run them.
79
80 =back
81
82 All other options passed to B<dh> are passed on to each command it runs. This
83 can be used to set an option like B<-v> or B<-X> or B<-N>, as well as for more
84 specialised options.
85
86 In the above options, I<cmd> can be a full name of a debhelper command, or
87 a substring. It'll first search for a command in the sequence exactly
88 matching the name, to avoid any ambiguity. If there are multiple substring
89 matches, the last one in the sequence will be used.
90
91 =cut
92
93 sub command_pos {
94         my $command=shift;
95         my @sequence=@_;
96
97         foreach my $i (0..$#sequence) {
98                 if ($command eq $sequence[$i]) {
99                         return $i;
100                 }
101         }
102
103         my @matches;
104         foreach my $i (0..$#sequence) {
105                 if ($sequence[$i] =~ /\Q$command\E/) {
106                         push @matches, $i;
107                 }
108         }
109         if (! @matches) {
110                 error "command specification \"$command\" does not match any command in the sequence"
111         }
112         else {
113                 return pop @matches;
114         }
115 }
116
117 =head1 EXAMPLES
118
119 To see what commands are included in a sequence, without actually doing
120 anything:
121
122         dh binary-arch --no-act
123
124 This is a very simple rules file, for packages where the default sequences of
125 commands work with no additional options.
126
127         #!/usr/bin/make -f
128         %:
129                 dh $@
130
131 Often you'll want to pass an option to a specific debhelper command. The
132 easy way to do with is by adding an override target for that command.
133         
134         #!/usr/bin/make -f
135         %:
136                 dh $@
137
138         override_dh_strip:
139                 dh_strip -Xfoo
140                 
141         override_dh_installdocs:
142                 dh_installdocs README TODO
143
144 Sometimes the automated L<dh_auto_configure(1)> and L<dh_auto_build(1)>
145 can't guess what to do for a strange package. Here's how to avoid running
146 either and instead run your own commands.
147
148         #!/usr/bin/make -f
149         %:
150                 dh $@
151
152         override_dh_auto_configure:
153                 ./mondoconfig
154
155         override_dh_auto_build:
156                 make universe-explode-in-delight
157
158 Another common case is wanting to do something manually before or
159 after a particular debhelper command is run.
160
161         #!/usr/bin/make -f
162         %:
163                 dh $@
164
165         override_dh_fixperms:
166                 dh_fixperms
167                 chmod 4755 debian/foo/usr/bin/foo
168
169 Python tools are not run by dh by default, due to the continual change
170 in that area. (Before compatability level v9, dh does run B<dh_pysupport>.)
171 Here is how to use B<dh_python2>.
172
173         #!/usr/bin/make -f
174         %:
175                 dh $@ --with python2
176
177 If your package uses autotools and you want to freshen F<config.sub> and
178 F<config.guess> with newer versions from the B<autotools-dev> package
179 at build time, you can use some commands provided in B<autotools-dev>
180 that automate it, like this.
181
182         #!/usr/bin/make -f
183         %:
184                 dh $@ --with autotools_dev
185
186 Here is how to force use of Perl's B<Module::Build> build system,
187 which can be necessary if debhelper wrongly detects that the package
188 uses MakeMaker.
189
190         #!/usr/bin/make -f
191         %:
192                 dh $@ --buildsystem=perl_build
193
194 To patch your package using quilt, you can tell B<dh> to use quilt's B<dh>
195 sequence addons like this:
196         
197         #!/usr/bin/make -f
198         %:
199                 dh $@ --with quilt
200
201 Here is an example of overriding where the B<dh_auto_>I<*> commands find
202 the package's source, for a package where the source is located in a
203 subdirectory.
204
205         #!/usr/bin/make -f
206         %:
207                 dh $@ --sourcedirectory=src
208
209 And here is an example of how to tell the B<dh_auto_>I<*> commands to build
210 in a subdirectory, which will be removed on B<clean>.
211
212         #!/usr/bin/make -f
213         %:
214                 dh $@ --builddirectory=build
215
216 If your package can be built in parallel, you can support parallel building
217 as follows. Then B<dpkg-buildpackage -j> will work.
218
219         #!/usr/bin/make -f
220         %:
221                 dh $@ --parallel
222
223 Here is a way to prevent B<dh> from running several commands that you don't
224 want it to run, by defining empty override targets for each command.
225
226         #!/usr/bin/make -f
227         %:
228                 dh $@
229         
230         # Commands not to run:
231         override_dh_auto_test override_dh_compress override_dh_fixperms:
232
233 Sometimes, you may need to make an override target only run commands when a
234 particular package is being built. This can be accomplished using
235 L<dh_listpackages(1)> to test what is being built. For example:
236
237         #!/usr/bin/make -f
238         %:
239                 dh $@
240         
241         override_dh_fixperms:
242                 dh_fixperms
243         ifneq (,$(filter foo, $(shell dh_listpackages)))
244                 chmod 4755 debian/foo/usr/bin/foo
245         endif
246
247 Finally, remember that you are not limited to using override targets in the
248 rules file when using B<dh>. You can also explicitly define any of the regular
249 rules file targets when it makes sense to do so. A common reason to do this
250 is when your package needs different B<build-arch> and B<build-indep> targets.
251 For example, a package with a long document build process can put it in
252 B<build-indep>.
253
254         #!/usr/bin/make -f
255         %:
256                 dh $@
257         
258         build-indep:
259                 $(MAKE) docs
260         build-arch:
261                 $(MAKE) bins
262
263 Note that in the example above, dh will arrange for "debian/rules build"
264 to call your build-indep and build-arch targets. You do not need to
265 explicitly define those dependencies in the rules file when using dh with
266 compatibility level v9. This example would be more complicated with
267 earlier compatibility levels.
268
269 =head1 INTERNALS
270
271 If you're curious about B<dh>'s internals, here's how it works under the hood.
272
273 Each debhelper command will record when it's successfully run in
274 F<debian/package.debhelper.log>. (Which B<dh_clean> deletes.) So B<dh> can tell
275 which commands have already been run, for which packages, and skip running
276 those commands again.
277
278 Each time B<dh> is run, it examines the log, and finds the last logged command
279 that is in the specified sequence. It then continues with the next command
280 in the sequence. The B<--until>, B<--before>, B<--after>, and B<--remaining>
281 options can override this behavior.
282
283 A sequence can also run dependent targets in debian/rules.  For
284 example, the "binary" sequence runs the "install" target.
285
286 B<dh> sets environment variables listed by B<dpkg-buildflags>, unless
287 they are already set. It supports DEB_BUILD_OPTIONS=noopt too.
288
289 B<dh> uses the B<DH_INTERNAL_OPTIONS> environment variable to pass information
290 through to debhelper commands that are run inside override targets. The
291 contents (and indeed, existence) of this environment variable, as the name
292 might suggest, is subject to change at any time.
293
294 =cut
295
296 # Stash this away before init modifies it.
297 my @ARGV_orig=@ARGV;
298
299 if (compat(8)) {
300         # python-support was enabled by default before v9.
301         # (and comes first so python-central loads later and can disable it).
302         unshift @ARGV, "--with=python-support";
303 }
304                 
305 init(options => {
306                 "until=s" => \$dh{UNTIL},
307                 "after=s" => \$dh{AFTER},
308                 "before=s" => \$dh{BEFORE},
309                 "remaining" => \$dh{REMAINING},
310                 "with=s" => sub {
311                         my ($option,$value)=@_;
312                         push @{$dh{WITH}},split(",", $value);
313                 },
314                 "without=s" => sub {
315                         my ($option,$value)=@_;
316                         @{$dh{WITH}} = grep { $_ ne $value } @{$dh{WITH}};
317                 },
318                 "l" => \&list_addons,
319                 "list" => \&list_addons,
320         },
321         # Disable complaints about unknown options; they are passed on to 
322         # the debhelper commands.
323         ignore_unknown_options => 1,
324         # Bundling does not work well since there are unknown options.
325         bundling => 0,
326 );
327 inhibit_log();
328 set_buildflags();
329 warn_deprecated();
330
331 # If make is using a jobserver, but it is not available
332 # to this process, clean out MAKEFLAGS. This avoids
333 # ugly warnings when calling make.
334 if (is_make_jobserver_unavailable()) {
335         clean_jobserver_makeflags();
336 }
337
338 # Process the sequence parameter.
339 my $sequence;
340 if (! compat(7)) {
341         # From v8, the sequence is the very first parameter.
342         $sequence=shift @ARGV_orig;
343         if (defined $sequence && $sequence=~/^-/) {
344                 error "Unknown sequence $sequence (options should not come before the sequence)";
345         }
346 }
347 else {
348         # Before v8, the sequence could be at any position in the parameters,
349         # so was what was left after parsing.
350         $sequence=shift;
351         if (defined $sequence) {
352                 @ARGV_orig=grep { $_ ne $sequence } @ARGV_orig;
353         }
354 }
355 if (! defined $sequence) {
356         error "specify a sequence to run";
357 }
358 # make -B causes the rules file to be run as a target.
359 # Also support completly empty override targets.
360 # Note: it's not safe to use rules_explicit_target before this check,
361 # since it causes dh to be run.
362 my $dummy_target="debhelper-fail-me";
363 if ($sequence eq 'debian/rules' ||
364     $sequence =~ /^override_dh_/ ||
365     $sequence eq $dummy_target) {
366         exit 0;
367 }
368
369
370 # Definitions of sequences.
371 my %sequences;
372 my @bd_minimal = qw{
373         dh_testdir
374 };
375 my @bd = qw{
376         dh_testdir
377         dh_auto_configure
378         dh_auto_build
379         dh_auto_test
380 };
381 my @i = qw{
382         dh_testroot
383         dh_prep
384         dh_installdirs
385         dh_auto_install
386
387         dh_install
388         dh_installdocs
389         dh_installchangelogs
390         dh_installexamples
391         dh_installman
392
393         dh_installcatalogs
394         dh_installcron
395         dh_installdebconf
396         dh_installemacsen
397         dh_installifupdown
398         dh_installinfo
399         dh_installinit
400         dh_installmenu
401         dh_installmime
402         dh_installmodules
403         dh_installlogcheck
404         dh_installlogrotate
405         dh_installpam
406         dh_installppp
407         dh_installudev
408         dh_installwm
409         dh_installxfonts
410         dh_installgsettings
411         dh_bugfiles
412         dh_ucf
413         dh_lintian
414         dh_gconf
415         dh_icons
416         dh_perl
417         dh_usrlocal
418
419         dh_link
420         dh_compress
421         dh_fixperms
422 };
423 my @ba=qw{
424         dh_strip
425         dh_makeshlibs
426         dh_shlibdeps
427 };
428 my @b=qw{
429         dh_installdeb
430         dh_gencontrol
431         dh_md5sums
432         dh_builddeb
433 };
434 $sequences{clean} = [qw{
435         dh_testdir
436         dh_auto_clean
437         dh_clean
438 }];
439 $sequences{'build-indep'} = [@bd];
440 $sequences{'build-arch'} = [@bd];
441 if (! compat(8)) {
442         # From v9, sequences take standard rules targets into account.
443         $sequences{build} = [@bd_minimal, rules("build-arch"), rules("build-indep")];
444         $sequences{'install-indep'} = [rules("build-indep"), @i];
445         $sequences{'install-arch'} = [rules("build-arch"), @i];
446         $sequences{'install'} = [rules("build"), rules("install-arch"), rules("install-indep"), @i];
447         $sequences{'binary-indep'} = [rules("install-indep"), @b];
448         $sequences{'binary-arch'} = [rules("install-arch"), @ba, @b];
449         $sequences{binary} = [rules("install"), rules("binary-arch"), rules("binary-indep")];
450 }
451 else {
452         $sequences{build} = [@bd];
453         $sequences{'install'} = [@{$sequences{build}}, @i];
454         $sequences{'install-indep'} = [@{$sequences{'build-indep'}}, @i];
455         $sequences{'install-arch'} = [@{$sequences{'build-arch'}}, @i];
456         $sequences{binary} = [@{$sequences{install}}, @ba, @b];
457         $sequences{'binary-indep'} = [@{$sequences{'install-indep'}}, @b];
458         $sequences{'binary-arch'} = [@{$sequences{'install-arch'}}, @ba, @b];
459 }
460
461 # Additional command options
462 my %command_opts;
463
464 # sequence addon interface
465 sub _insert {
466         my $offset=shift;
467         my $existing=shift;
468         my $new=shift;
469         foreach my $sequence (keys %sequences) {
470                 my @list=@{$sequences{$sequence}};
471                 next unless grep $existing, @list;
472                 my @new;
473                 foreach my $command (@list) {
474                         if ($command eq $existing) {
475                                 push @new, $new if $offset < 0;
476                                 push @new, $command;
477                                 push @new, $new if $offset > 0;
478                         }
479                         else {
480                                 push @new, $command;
481                         }
482                 }
483                 $sequences{$sequence}=\@new;
484         }
485 }
486 sub insert_before {
487         _insert(-1, @_);
488 }
489 sub insert_after {
490         _insert(1, @_);
491 }
492 sub remove_command {
493         my $command=shift;
494         foreach my $sequence (keys %sequences) {
495                 $sequences{$sequence}=[grep { $_ ne $command } @{$sequences{$sequence}}];
496         }
497         
498 }
499 sub add_command {
500         my $command=shift;
501         my $sequence=shift;
502         unshift @{$sequences{$sequence}}, $command;
503 }
504 sub add_command_options {
505         my $command=shift;
506         push @{$command_opts{$command}}, @_;
507 }
508 sub remove_command_options {
509         my $command=shift;
510         if (@_) {
511                 # Remove only specified options
512                 if (my $opts = $command_opts{$command}) {
513                         foreach my $opt (@_) {
514                                 $opts = [ grep { $_ ne $opt } @$opts ];
515                         }
516                         $command_opts{$command} = $opts;
517                 }
518         }
519         else {
520                 # Clear all additional options
521                 delete $command_opts{$command};
522         }
523 }
524
525 sub list_addons {
526         my %addons;
527
528         for my $inc (@INC) {
529                 eval q{use File::Spec};
530                 my $path = File::Spec->catdir($inc, "Debian/Debhelper/Sequence");
531                 if (-d $path) {
532                         for my $module_path (glob "$path/*.pm") {
533                                 my $name = basename($module_path);
534                                 $name =~ s/\.pm$//;
535                                 $name =~ s/_/-/g;
536                                 $addons{$name} = 1;
537                         }
538                 }
539         }
540
541         for my $name (sort keys %addons) {
542                 print "$name\n";
543         }
544
545         exit 0;
546 }
547
548 # Load addons, which can modify sequences.
549 foreach my $addon (@{$dh{WITH}}) {
550         my $mod="Debian::Debhelper::Sequence::$addon";
551         $mod=~s/-/_/g;
552         eval "use $mod";
553         if ($@) {
554                 error("unable to load addon $addon: $@");
555         }
556 }
557
558 if (! exists $sequences{$sequence}) {
559         error "Unknown sequence $sequence (choose from: ".
560                 join(" ", sort keys %sequences).")";
561 }
562 my @sequence=optimize_sequence(@{$sequences{$sequence}});
563
564 # The list of all packages that can be acted on.
565 my @packages=@{$dh{DOPACKAGES}};
566
567 # Get the options to pass to commands in the sequence.
568 # Filter out options intended only for this program.
569 my @options;
570 if ($sequence eq 'build-arch' ||
571     $sequence eq 'install-arch' ||
572     $sequence eq 'binary-arch') {
573         push @options, "-a";
574         # as an optimisation, remove from the list any packages
575         # that are not arch dependent
576         my %arch_packages = map { $_ => 1 } getpackages("arch");
577         @packages = grep { $arch_packages{$_} } @packages;
578 }
579 elsif ($sequence eq 'build-indep' ||
580        $sequence eq 'install-indep' ||
581        $sequence eq 'binary-indep') {
582         push @options, "-i";
583         # ditto optimisation for arch indep
584         my %indep_packages = map { $_ => 1 } getpackages("indep");
585         @packages = grep { $indep_packages{$_} } @packages;
586 }
587 while (@ARGV_orig) {
588         my $opt=shift @ARGV_orig;
589         if ($opt =~ /^--?(after|until|before|with|without)$/) {
590                 shift @ARGV_orig;
591                 next;
592         }
593         elsif ($opt =~ /^--?(no-act|remaining|(after|until|before|with|without)=)/) {
594                 next;
595         }
596         elsif ($opt=~/^-/) {
597                 push @options, "-O".$opt;
598         }
599         elsif (@options) {
600                 if ($options[$#options]=~/^-O--/) {
601                         $options[$#options].="=".$opt;
602                 }
603                 else {
604                         $options[$#options].=$opt;
605                 }
606         }
607 }
608
609 # Figure out at what point in the sequence to start for each package.
610 my %logged;
611 my %startpoint;
612 foreach my $package (@packages) {
613         my @log=load_log($package, \%logged);
614         if ($dh{AFTER}) {
615                 # Run commands in the sequence that come after the
616                 # specified command.
617                 $startpoint{$package}=command_pos($dh{AFTER}, @sequence) + 1;
618                 # Write a dummy log entry indicating that the specified
619                 # command was, in fact, run. This handles the case where
620                 # no commands remain to run after it, communicating to
621                 # future dh instances that the specified command should not
622                 # be run again.
623                 write_log($sequence[$startpoint{$package}-1], $package);
624         }
625         elsif ($dh{REMAINING}) {
626                 # Start at the beginning so all remaining commands will get
627                 # run.
628                 $startpoint{$package}=0;
629         }
630         else {
631                 # Find the last logged command that is in the sequence, and
632                 # continue with the next command after it. If no logged
633                 # command is in the sequence, we're starting at the beginning..                         
634                 $startpoint{$package}=0;
635 COMMAND:        foreach my $command (reverse @log) {
636                         foreach my $i (0..$#sequence) {
637                                 if ($command eq $sequence[$i]) {
638                                         $startpoint{$package}=$i+1;
639                                         last COMMAND;
640                                 }
641                         }
642                 }
643         }
644 }
645
646 # Figure out what point in the sequence to go to.
647 my $stoppoint=$#sequence;
648 if ($dh{UNTIL}) {
649         $stoppoint=command_pos($dh{UNTIL}, @sequence);
650 }
651 elsif ($dh{BEFORE}) {
652         $stoppoint=command_pos($dh{BEFORE}, @sequence) - 1;
653 }
654
655 # Now run the commands in the sequence.
656 foreach my $i (0..$stoppoint) {
657         # Figure out which packages need to run this command.
658         my @exclude;
659         foreach my $package (@packages) {
660                 if ($startpoint{$package} > $i ||
661                     $logged{$package}{$sequence[$i]}) {
662                         push @exclude, $package;
663                 }
664         }
665         
666         if (@exclude eq @packages) {
667                 # Command already done for all packages.
668                 next;
669         }
670
671         run($sequence[$i], \@packages, \@exclude, @options);
672 }
673
674 sub run {
675         my $command=shift;
676         my @packages=@{shift()};
677         my @exclude=@{shift()};
678         my @options=@_;
679         
680         # If some packages are excluded, add flags
681         # to prevent them from being acted on.
682         push @options, map { "-N$_" } @exclude;
683
684         # Check for override targets in debian/rules and
685         # run them instead of running the command directly.
686         my $override_command;
687         my $has_explicit_target = rules_explicit_target("override_".$command);
688
689         my $rules_target = rules_target($command);
690         if (defined $rules_target) {
691                 # Don't pass DH_ environment variables, since this is
692                 # a fresh invocation of debian/rules and any sub-dh
693                 # commands.
694                 $override_command=$command;
695                 delete $ENV{DH_INTERNAL_OPTIONS};
696                 delete $ENV{DH_INTERNAL_OVERRIDE};
697                 $command="debian/rules";
698                 @options=$rules_target;
699         }
700         elsif (defined $has_explicit_target) {
701                 $override_command=$command;
702                 # Check if target isn't noop
703                 if ($has_explicit_target) {
704                         # This passes the options through to commands called
705                         # inside the target.
706                         $ENV{DH_INTERNAL_OPTIONS}=join("\x1e", @options);
707                         $ENV{DH_INTERNAL_OVERRIDE}=$command;
708                         $command="debian/rules";
709                         @options="override_".$override_command;
710                 }
711                 else {
712                         $command = undef;
713                 }
714         }
715         else {
716                 # Pass additional command options if any
717                 unshift @options, @{$command_opts{$command}} if exists $command_opts{$command};
718         }
719
720         if (defined $command) {
721                 # 3 space indent lines the command being run up under the
722                 # sequence name after "dh ".
723                 print "   ".escape_shell($command, @options)."\n";
724         }
725         else {
726                 print "   ", "# Skipping ", $override_command, " - empty override", "\n";
727         }
728                                 
729         if (! $dh{NO_ACT}) {
730                 if (defined $command) {
731                         my $ret=system($command, @options);
732                         
733                         if ($ret >> 8 != 0) {
734                                 exit $ret >> 8;
735                         }
736                         elsif ($ret) {
737                                 exit 1;
738                         }
739                 }
740
741                 if (defined $override_command) {
742                         # Update log for overridden command now that it has
743                         # finished successfully.
744                         # (But avoid logging for dh_clean since it removes
745                         # the log earlier.)
746                         if ($override_command ne 'dh_clean') {
747                                 my %packages=map { $_ => 1 } @packages;
748                                 map { delete $packages{$_} } @exclude;
749                                 write_log($override_command, keys %packages);
750                                 commit_override_log(keys %packages);
751                         }
752
753                         delete $ENV{DH_INTERNAL_OPTIONS};
754                         delete $ENV{DH_INTERNAL_OVERRIDE};
755                 }
756         }
757 }
758
759 sub optimize_sequence {
760         my @sequence;
761         my %seen;
762         my $add=sub {
763                 # commands can appear multiple times when sequences are
764                 # inlined together; only the first should be needed
765                 my $command=shift;
766                 if (! $seen{$command}) {
767                         $seen{$command}=1;
768                         push @sequence, $command;
769                 }
770         };
771         foreach my $command (@_) {
772                 my $rules_target=rules_target($command);
773                 if (defined $rules_target &&
774                     ! defined rules_explicit_target($rules_target)) {
775                         # inline the sequence for this implicit target
776                         $add->($_) foreach optimize_sequence(@{$sequences{$rules_target}});
777                 }
778                 else {
779                         $add->($command);
780                 }
781         }
782         return @sequence;
783 }
784
785 sub rules_target {
786         my $command=shift;
787         if ($command =~ /^debian\/rules\s+(.*)/) {
788                 return $1
789         }
790         else {
791                 return undef;
792         }
793 }
794
795 sub rules {
796         return "debian/rules ".join(" ", @_);
797 }
798
799 {
800 my %targets;
801 my $rules_parsed;
802
803 sub rules_explicit_target {
804         # Checks if a specified target exists as an explicit target
805         # in debian/rules.
806         # undef is returned if target does not exist, 0 if target is noop
807         # and 1 if target has dependencies or executes commands.
808         my $target=shift;
809
810         if (! $rules_parsed) {
811                 my $processing_targets = 0;
812                 my $not_a_target = 0;
813                 my $current_target;
814                 open(MAKE, "LC_ALL=C make -Rrnpsf debian/rules $dummy_target 2>/dev/null |");
815                 while (<MAKE>) {
816                         if ($processing_targets) {
817                                 if (/^# Not a target:/) {
818                                         $not_a_target = 1;
819                                 }
820                                 else {
821                                         if (!$not_a_target && /^([^#:]+)::?\s*(.*)$/) {
822                                                 # Target is defined. NOTE: if it is a depenency of
823                                                 # .PHONY it will be defined too but that's ok.
824                                                 # $2 contains target dependencies if any.
825                                                 $current_target = $1;
826                                                 $targets{$current_target} = ($2) ? 1 : 0;
827                                         }
828                                         else {
829                                                 if (defined $current_target) {
830                                                         if (/^#/) {
831                                                                 # Check if target has commands to execute
832                                                                 if (/^#\s*(commands|recipe) to execute/) {
833                                                                         $targets{$current_target} = 1;
834                                                                 }
835                                                         }
836                                                         else {
837                                                                 # Target parsed.
838                                                                 $current_target = undef;
839                                                         }
840                                                 }
841                                         }
842                                         # "Not a target:" is always followed by
843                                         # a target name, so resetting this one
844                                         # here is safe.
845                                         $not_a_target = 0;
846                                 }
847                         }
848                         elsif (/^# Files$/) {
849                                 $processing_targets = 1;
850                         }
851                 }
852                 close MAKE;
853                 $rules_parsed = 1;
854         }
855
856         return $targets{$target};
857 }
858
859 }
860
861 sub warn_deprecated {
862         foreach my $deprecated ('until', 'after', 'before', 'remaining') {
863                 if (defined $dh{uc $deprecated}) {
864                         warning("The --$deprecated option is deprecated. Use override targets instead.");
865                 }
866         }
867 }
868
869 =head1 SEE ALSO
870
871 L<debhelper(7)>
872
873 This program is a part of debhelper.
874
875 =head1 AUTHOR
876
877 Joey Hess <joeyh@debian.org>
878
879 =cut