5 dh - debhelper command sequencer
10 use Debian::Debhelper::Dh_Lib;
14 B<dh> sequence [B<--until> I<cmd>] [B<--before> I<cmd>] [B<--after> I<cmd>] [B<--remaining>] [S<I<debhelper options>>]
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".
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.
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
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.
41 =item B<--until> I<cmd>
43 Run commands in the sequence until and including I<cmd>, then stop.
45 =item B<--before> I<cmd>
47 Run commands in the sequence before I<cmd>, then stop.
49 =item B<--after> I<cmd>
51 Run commands in the sequence that come after I<cmd>.
55 Run all commands in the sequence that have yet to be run.
59 All other options passed to dh are passed on to each command it runs. This
60 can be used to set an option like "-v" or "-X" or "-N", as well as for more
63 =head1 COMMAND SPECIFICATION
65 I<cmd> can be a full name of a debhelper command, or a substring. It'll first
66 search for a command in the sequence exactly matching the name, to avoid any
67 ambiguity. If there are multiple substring matches, the last one in the
68 sequence will be used.
76 foreach my $i (0..$#sequence) {
77 if ($command eq $sequence[$i]) {
83 foreach my $i (0..$#sequence) {
84 if ($sequence[$i] =~ /\Q$command\E/) {
89 error "command specification \"$command\" does not match any command in the sequence"
98 To see what commands are included in a sequence, without actually doing
101 dh binary-arch --no-act
103 This is a very simple rules file, for packages where the default seqences of
104 commands work with no additional options.
110 This is a simple rules file that is a good starting place for customisation.
111 (It's also available in F</usr/share/doc/debhelper/examples/rules.simple>
127 binary-indep: install
130 binary: binary-arch binary-indep
132 Often you'll want to pass an option to ./configure. This uses dh to run all
133 commands before L<dh_auto_configure(1)>, then runs that command by hand,
134 and then finished up by running the rest of the sequence. You could also
135 run ./configure by hand, instead of bothering with using dh_auto_configure.
136 And if necessary, you can add commands to run automake, etc here too.
139 dh build --before configure
140 dh_auto_configure --kitchen-sink=yes
141 dh build --after configure
143 Here's how to skip two automated in a row (configure and build), and
144 instead run the commands by hand.
147 dh build --before configure
149 make universe-explode-in-delight
150 dh build --after build
152 Another common case is wanting to run some code manually after a particular
153 debhelper command is run.
156 dh install --until dh_fixperms
157 # dh_fixperms has run, now override it for one program
158 chmod 4755 debian/foo/usr/bin/foo
160 dh install --after dh_fixperms
162 It's also fine to run debhelper commands early. Just make sure that at
163 least dh_prep is run from the squence first, and be sure to use the
164 B<--remaining> option to ensure that commands that normally come before
165 those in the sequence are still run.
168 dh install --until dh_prep
169 dh_installdocs README TODO
170 dh_installchangelogs Changes
171 dh install --remaining
175 dh binary-arch --remaining
179 # Stash this away before init modifies it.
185 # Definitions of sequences.
187 $sequences{build} = [qw{
193 $sequences{clean} = [qw{
198 $sequences{install} = [@{$sequences{build}}, qw{
247 $sequences{'binary-indep'} = [@{$sequences{install}}, @b];
248 $sequences{binary} = [@{$sequences{install}}, qw{
253 $sequences{'binary-arch'} = [@{$sequences{binary}}];
255 # Third-party commands can be listed in the sequences, but should be
256 # listed here as well. They will not be run if not present.
257 my %thirdparty=map { $_ => 1 } qw{
262 # Get the sequence of commands to run.
264 error "specify a sequence to run";
267 if (! exists $sequences{$sequence}) {
268 error "Unknown sequence $sequence (chose from: ".
269 join(" ", sort keys %sequences).")";
271 my @sequence=@{$sequences{$sequence}};
273 # The list of all packages that can be acted on.
274 my @packages=@{$dh{DOPACKAGES}};
276 # Get the options to pass to commands in the sequence.
277 # Filter out options intended only for this program.
279 if ($sequence eq 'binary-arch') {
281 # as an optimisation, remove from the list any packages
282 # that are not arch dependent
283 my %arch_packages = map { $_ => 1 } getpackages("arch");
284 @packages = grep { $arch_packages{$_} } @packages;
286 elsif ($sequence eq 'binary-indep') {
288 # ditto optimisation for arch indep
289 my %indep_packages = map { $_ => 1 } getpackages("indep");
290 @packages = grep { $indep_packages{$_} } @packages;
293 my $opt=shift @ARGV_orig;
294 next if $opt eq $sequence;
295 if ($opt =~ /^--?(after|until|before)$/) {
299 elsif ($opt =~ /^--?(no-act|remaining|(after|until|before)=)/) {
305 # Figure out at what point in the sequence to start for each package.
308 foreach my $package (@packages) {
309 my @log=loadlog($package);
311 # Run commands in the sequence that come after the
313 $startpoint{$package}=command_pos($dh{AFTER}, @sequence) + 1;
314 # Write a dummy log entry indicating that the specified
315 # command was, in fact, run. This handles the case where
316 # no commands remain to run after it, communicating to
317 # future dh instances that the specified command should not
319 writelog($package, $sequence[$startpoint{$package}-1]);
321 elsif ($dh{REMAINING}) {
322 # Start at the beginning so all remaining commands will get
324 $startpoint{$package}=0;
327 # Find the last logged command that is in the sequence, and
328 # continue with the next command after it. If no logged
329 # command is in the sequence, we're starting at the beginning..
330 $startpoint{$package}=0;
331 COMMAND: foreach my $command (reverse @log) {
332 foreach my $i (0..$#sequence) {
333 if ($command eq $sequence[$i]) {
334 $startpoint{$package}=$i+1;
342 # Figure out what point in the sequence to go to.
343 my $stoppoint=$#sequence;
345 $stoppoint=command_pos($dh{UNTIL}, @sequence);
347 elsif ($dh{BEFORE}) {
348 $stoppoint=command_pos($dh{BEFORE}, @sequence) - 1;
351 # Now run the commands in the sequence.
352 foreach my $i (0..$stoppoint) {
353 # Figure out which packages need to run this command.
355 foreach my $package (@packages) {
356 if ($startpoint{$package} > $i ||
357 $logged{$package}{$sequence[$i]}) {
358 push @exclude, $package;
362 if (@exclude eq @packages) {
363 # Command already done for all packages.
367 # Run command for all packages.
368 run($sequence[$i], @options);
371 # Run command for only a subset of packages.
372 run($sequence[$i], @options,
373 map { "-N$_" } @exclude);
381 # If a third party command is not in /usr/bin, don't try to run it.
382 if ($thirdparty{$command} && ! -x "/usr/bin/$command") {
386 # 3 space indent lines the command being run up under the
387 # sequence name after "dh ".
388 print " ".escape_shell($command, @options)."\n";
391 my $ret=system($command, @options);
392 if ($ret >> 8 != 0) {
403 my $ext=pkgext($package);
406 open(LOG, "<", "debian/${ext}debhelper.log") || return;
410 $logged{$package}{$_}=1;
419 my $ext=pkgext($package);
421 open(LOG, ">>", "debian/${ext}debhelper.log") || error("failed to write to log");
430 This program is a part of debhelper.
434 Joey Hess <joeyh@debian.org>