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