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