]> git.donarmstrong.com Git - debhelper.git/blob - dh
Fix typo in French translation, about debian/package.README.Debian files.
[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<--until> I<cmd>] [B<--before> I<cmd>] [B<--after> I<cmd>] [B<--remaining>] [B<--with> I<addon>] [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 =head1 OPTIONS
38
39 =over 4
40
41 =item B<--until> I<cmd>
42
43 Run commands in the sequence until and including I<cmd>, then stop.
44
45 =item B<--before> I<cmd>
46
47 Run commands in the sequence before I<cmd>, then stop.
48
49 =item B<--after> I<cmd>
50
51 Run commands in the sequence that come after I<cmd>.
52
53 =item B<--remaining>
54
55 Run all commands in the sequence that have yet to be run.
56
57 =item B<--with> I<addon>
58
59 Add the debhelper commands specified by the given addon to appropriate places
60 in the sequence of commands that is run. This option can be repeated more
61 than once, and is used when there is a third-party package that provides
62 debhelper commands. See "SEQUENCE ADDONS" below for documentation about what
63 such packages should do to be supported by --with.
64
65 =back
66
67 All other options passed to dh are passed on to each command it runs. This
68 can be used to set an option like "-v" or "-X" or "-N", as well as for more
69 specialised options.
70
71 =head1 COMMAND SPECIFICATION
72
73 I<cmd> can be a full name of a debhelper command, or a substring. It'll first
74 search for a command in the sequence exactly matching the name, to avoid any
75 ambiguity. If there are multiple substring matches, the last one in the
76 sequence will be used.
77
78 =head1 SEQUENCE ADDONS
79
80 When B<--with> I<addon> is used, dh loads the perl module
81 Debian::Debhelper::Sequence::I<addon>. Two functions are provided to let
82 the module add its commands to sequences:
83
84 =over 4
85
86 =item Debian::Debhelper::Dh_Lib::insert_before(existing_command, new_command)
87
88 Insert I<new_command> in sequences before I<existing_command>.
89
90 =item Debian::Debhelper::Dh_Lib::insert_after(existing_command, new_command)
91
92 Insert I<new_command> in sequences after I<existing_command>.
93
94 =item Debian::Debhelper::Dh_Lib::remove_command(existing_command)
95
96 Remove I<existing_command> from the list of commands to run.
97
98 =back
99
100 =cut
101
102 sub command_pos {
103         my $command=shift;
104         my @sequence=@_;
105
106         foreach my $i (0..$#sequence) {
107                 if ($command eq $sequence[$i]) {
108                         return $i;
109                 }
110         }
111
112         my @matches;
113         foreach my $i (0..$#sequence) {
114                 if ($sequence[$i] =~ /\Q$command\E/) {
115                         push @matches, $i;
116                 }
117         }
118         if (! @matches) {
119                 error "command specification \"$command\" does not match any command in the sequence"
120         }
121         else {
122                 return pop @matches;
123         }
124 }
125
126 =head1 EXAMPLES
127
128 To see what commands are included in a sequence, without actually doing
129 anything:
130
131         dh binary-arch --no-act
132
133 This is a very simple rules file, for packages where the default sequences of
134 commands work with no additional options.
135
136         #!/usr/bin/make -f
137         %:
138                 dh $@
139
140 This is a simple rules file that is a good starting place for customisation.
141 (It's also available in F</usr/share/doc/debhelper/examples/rules.simple>
142
143         #!/usr/bin/make -f
144
145         build: build-stamp
146                 dh build
147                 touch build-stamp
148
149         clean:
150                 dh clean
151
152         install: build install-stamp
153         install-stamp:
154                 dh install
155                 touch install-stamp
156
157         binary-arch: install
158                 dh binary-arch
159
160         binary-indep: install
161                 dh binary-indep
162
163         binary: binary-arch binary-indep
164
165 Often you'll want to pass an option to ./configure. This uses dh to run all
166 commands before L<dh_auto_configure(1)>, then runs that command by hand,
167 and then finished up by running the rest of the sequence. You could also
168 run ./configure by hand, instead of bothering with using dh_auto_configure.
169 And if necessary, you can add commands to run automake, etc here too.
170
171         build: build-stamp
172         build-stamp:
173                 dh build --before configure
174                 dh_auto_configure -- --kitchen-sink=yes
175                 dh build --after configure
176                 touch build-stamp
177
178 Here's how to skip two automated in a row (configure and build), and
179 instead run the commands by hand.
180
181         build: build-stamp
182         build-stamp:
183                 dh build --before configure
184                 ./mondoconfig
185                 make universe-explode-in-delight
186                 dh build --after build
187                 touch build-stamp
188
189 Another common case is wanting to run some code manually after a particular
190 debhelper command is run.
191
192         install: build install-stamp
193         install-stamp:
194                 dh install --until dh_fixperms
195                 # dh_fixperms has run, now override it for one program
196                 chmod 4755 debian/foo/usr/bin/foo
197                 # and continue
198                 dh install --after dh_fixperms
199                 touch install-stamp
200
201 It's also fine to run debhelper commands early. Just make sure that at
202 least dh_prep is run from the sequence first, and be sure to use the
203 B<--remaining> option to ensure that commands that normally come before
204 those in the sequence are still run.
205
206         install: build install-stamp
207         install-stamp:
208                 dh install --until dh_prep
209                 dh_installdocs README TODO
210                 dh_installchangelogs Changes
211                 dh install --remaining
212                 touch install-stamp
213
214         binary-arch: install
215                 dh_strip -X foo
216                 dh binary-arch --remaining
217
218 =cut
219
220 # Stash this away before init modifies it.
221 my @ARGV_orig=@ARGV;
222
223 init();
224 inhibit_log();
225
226 # Definitions of sequences.
227 my %sequences;
228 $sequences{build} = [qw{
229         dh_testdir
230         dh_auto_configure
231         dh_auto_build
232         dh_auto_test
233 }],
234 $sequences{clean} = [qw{
235         dh_testdir
236         dh_auto_clean
237         dh_clean
238 }];
239 $sequences{install} = [@{$sequences{build}}, qw{
240         dh_testroot
241         dh_prep
242         dh_installdirs
243         dh_auto_install
244
245         dh_install
246         dh_installdocs
247         dh_installchangelogs
248         dh_installexamples
249         dh_installman
250
251         dh_installcatalogs
252         dh_installcron
253         dh_installdebconf
254         dh_installcatalogs
255         dh_installemacsen
256         dh_installifupdown
257         dh_installinfo
258         dh_installinit
259         dh_installmenu
260         dh_installmime
261         dh_installmodules
262         dh_installlogcheck
263         dh_installlogrotate
264         dh_installpam
265         dh_installppp
266         dh_installudev
267         dh_installwm
268         dh_installxfonts
269         dh_lintian
270         dh_desktop
271         dh_gconf
272         dh_icons
273         dh_perl
274         dh_scrollkeeper
275         dh_usrlocal
276
277         dh_link
278         dh_compress
279         dh_fixperms
280 }];
281 my @b=qw{
282         dh_installdeb
283         dh_gencontrol
284         dh_md5sums
285         dh_builddeb
286 };
287 $sequences{'binary-indep'} = [@{$sequences{install}}, @b];
288 $sequences{binary} = [@{$sequences{install}}, qw{
289         dh_strip
290         dh_makeshlibs
291         dh_shlibdeps
292 }, @b];
293 $sequences{'binary-arch'} = [@{$sequences{binary}}];
294
295 # --with python-support is enabled by default, at least for now
296 unshift @{$dh{WITH}}, "python-support";
297
298 # sequence addon interface
299 sub _insert {
300         my $offset=shift;
301         my $existing=shift;
302         my $new=shift;
303         foreach my $sequence (keys %sequences) {
304                 my @list=@{$sequences{$sequence}};
305                 next unless grep $existing, @list;
306                 my @new;
307                 foreach my $command (@list) {
308                         if ($command eq $existing) {
309                                 push @new, $new if $offset < 0;
310                                 push @new, $command;
311                                 push @new, $new if $offset > 0;
312                         }
313                         else {
314                                 push @new, $command;
315                         }
316                 }
317                 $sequences{$sequence}=\@new;
318         }
319 }
320 sub insert_before {
321         _insert(-1, @_);
322 }
323 sub insert_after {
324         _insert(1, @_);
325 }
326 sub remove_command {
327         my $command=shift;
328         foreach my $sequence (keys %sequences) {
329                 $sequences{$sequence}=[grep { $_ ne $command } @{$sequences{$sequence}}];
330         }
331         
332 }
333 foreach my $addon (@{$dh{WITH}}) {
334         my $mod="Debian::Debhelper::Sequence::$addon";
335         $mod=~s/-/_/g;
336         eval "use $mod";
337         if ($@) {
338                 error("--with $addon not supported or failed to load module $mod");
339         }
340 }
341
342 # Get the sequence of commands to run.
343 if (! @ARGV) {
344         error "specify a sequence to run";
345 }
346 my $sequence=shift;
347 if (! exists $sequences{$sequence}) {
348         error "Unknown sequence $sequence (chose from: ".
349                 join(" ", sort keys %sequences).")";
350 }
351 my @sequence=@{$sequences{$sequence}};
352
353 # The list of all packages that can be acted on.
354 my @packages=@{$dh{DOPACKAGES}};
355
356 # Get the options to pass to commands in the sequence.
357 # Filter out options intended only for this program.
358 my @options;
359 if ($sequence eq 'binary-arch') {
360         push @options, "-a";
361         # as an optimisation, remove from the list any packages
362         # that are not arch dependent
363         my %arch_packages = map { $_ => 1 } getpackages("arch");
364         @packages = grep { $arch_packages{$_} } @packages;
365 }
366 elsif ($sequence eq 'binary-indep') {
367         push @options, "-i";
368         # ditto optimisation for arch indep
369         my %indep_packages = map { $_ => 1 } getpackages("indep");
370         @packages = grep { $indep_packages{$_} } @packages;
371 }
372 while (@ARGV_orig) {
373         my $opt=shift @ARGV_orig;
374         next if $opt eq $sequence;
375         if ($opt =~ /^--?(after|until|before|with)$/) {
376                 shift @ARGV_orig;
377                 next;
378         }
379         elsif ($opt =~ /^--?(no-act|remaining|(after|until|before|with)=)/) {
380                 next;
381         }
382         push @options, $opt;
383 }
384
385 # Figure out at what point in the sequence to start for each package.
386 my %logged;
387 my %startpoint;
388 foreach my $package (@packages) {
389         my @log=loadlog($package);
390         if ($dh{AFTER}) {
391                 # Run commands in the sequence that come after the
392                 # specified command.
393                 $startpoint{$package}=command_pos($dh{AFTER}, @sequence) + 1;
394                 # Write a dummy log entry indicating that the specified
395                 # command was, in fact, run. This handles the case where
396                 # no commands remain to run after it, communicating to
397                 # future dh instances that the specified command should not
398                 # be run again.
399                 writelog($package, $sequence[$startpoint{$package}-1]);
400         }
401         elsif ($dh{REMAINING}) {
402                 # Start at the beginning so all remaining commands will get
403                 # run.
404                 $startpoint{$package}=0;
405         }
406         else {
407                 # Find the last logged command that is in the sequence, and
408                 # continue with the next command after it. If no logged
409                 # command is in the sequence, we're starting at the beginning..                         
410                 $startpoint{$package}=0;
411 COMMAND:        foreach my $command (reverse @log) {
412                         foreach my $i (0..$#sequence) {
413                                 if ($command eq $sequence[$i]) {
414                                         $startpoint{$package}=$i+1;
415                                         last COMMAND;
416                                 }
417                         }
418                 }
419         }
420 }
421
422 # Figure out what point in the sequence to go to.
423 my $stoppoint=$#sequence;
424 if ($dh{UNTIL}) {
425         $stoppoint=command_pos($dh{UNTIL}, @sequence);
426 }
427 elsif ($dh{BEFORE}) {
428         $stoppoint=command_pos($dh{BEFORE}, @sequence) - 1;
429 }
430
431 # Now run the commands in the sequence.
432 foreach my $i (0..$stoppoint) {
433         # Figure out which packages need to run this command.
434         my @exclude;
435         foreach my $package (@packages) {
436                 if ($startpoint{$package} > $i ||
437                     $logged{$package}{$sequence[$i]}) {
438                         push @exclude, $package;
439                 }
440         }
441         
442         if (@exclude eq @packages) {
443                 # Command already done for all packages.
444                 next;
445         }
446         elsif (! @exclude) {
447                 # Run command for all packages.
448                 run($sequence[$i], @options);
449         }
450         else {
451                 # Run command for only a subset of packages.
452                 run($sequence[$i], @options,
453                         map { "-N$_" } @exclude);
454         }
455 }
456
457 sub run {
458         my $command=shift;
459         my @options=@_;
460         
461         # 3 space indent lines the command being run up under the 
462         # sequence name after "dh ".
463         print "   ".escape_shell($command, @options)."\n";
464
465         if (! $dh{NO_ACT}) {
466                 my $ret=system($command, @options);
467                 if ($ret >> 8 != 0) {
468                         exit $ret >> 8;
469                 }
470                 elsif ($ret) {
471                         exit 1;
472                 }
473         }
474 }
475
476 sub loadlog {
477         my $package=shift;
478         my $ext=pkgext($package);
479         
480         my @log;
481         open(LOG, "<", "debian/${ext}debhelper.log") || return;
482         while (<LOG>) {
483                 chomp;
484                 push @log, $_;
485                 $logged{$package}{$_}=1;
486         }
487         close LOG;
488         return @log;
489 }
490                 
491 sub writelog {
492         my $package=shift;
493         my $cmd=shift;
494         my $ext=pkgext($package);
495         
496         open(LOG, ">>", "debian/${ext}debhelper.log") || error("failed to write to log");
497         print LOG $cmd."\n";
498         close LOG;
499 }
500
501 =head1 SEE ALSO
502
503 L<debhelper(7)>
504
505 This program is a part of debhelper.
506
507 =head1 AUTHOR
508
509 Joey Hess <joeyh@debian.org>
510
511 =cut