binary-arch sequences are passed the "-a" option to ensure they only work
on architecture dependent packages.
-Each debhelper command will record when it's successfully run in
-debian/package.debhelper.log. (Which dh_clean deletes.) So dh can tell
-which commands have already been run, for which packages, and skip running
-those commands again.
-
-Each time dh is run, it examines the log, and finds the last logged command
-that is in the specified sequence. It then continues with the next command
-in the sequence. The B<--until>, B<--before>, B<--after>, and B<--remaining>
-options can override this behavior.
-
If debian/rules contains a target with a name like "override_I<dh_command>",
-then when it gets to that command in the sequence, dh will run that
-target from the rules file, rather than running the actual command. The
-override target can then run the command with additional options, or run
-entirely different commands instead. (Note that to use this feature,
-you should Build-Depend on debhelper 7.0.50 or above.)
+then when it would normally run I<dh_command>, dh will instead call that
+target. The override target can then run the command with additional options,
+or run entirely different commands instead. See examples below. (Note that to
+use this feature, you should Build-Depend on debhelper 7.0.50 or above.)
=head1 OPTIONS
Run all commands in the sequence that have yet to be run.
+=item B<--no-act>
+
+Prints commands that would run for a given sequence, but does not run them.
+
=back
All other options passed to dh are passed on to each command it runs. This
can be used to set an option like "-v" or "-X" or "-N", as well as for more
specialised options.
-=head1 COMMAND SPECIFICATION
-
-I<cmd> can be a full name of a debhelper command, or a substring. It'll first
-search for a command in the sequence exactly matching the name, to avoid any
-ambiguity. If there are multiple substring matches, the last one in the
-sequence will be used.
+In the above options, I<cmd> can be a full name of a debhelper command, or
+a substring. It'll first search for a command in the sequence exactly
+matching the name, to avoid any ambiguity. If there are multiple substring
+matches, the last one in the sequence will be used.
=cut
override_dh_installdocs:
dh_installdocs README TODO
-Sometimes the automated dh_auto_configure and dh_auto_build can't guess
-what to do for a strange package. Here's how to avoid running either
-and instead run your own commands.
+Sometimes the automated L<dh_auto_configure(1)> and L<dh_auto_build(1)>
+can't guess what to do for a strange package. Here's how to avoid running
+either and instead run your own commands.
#!/usr/bin/make -f
%:
#!/usr/bin/make -f
%:
- dh --with python-central $@
+ dh $@ --with python-central
+
+If your package uses autotools and you want to freshen config.sub and
+config.guess with newer versions from the autotools-dev package
+at build time, you can use some commands provided in autotools-dev
+that automate it, like this.
+
+ #!/usr/bin/make -f
+ %:
+ dh $@ --with autotools_dev
+
+Here is how to force use of perl's Module::Build build system,
+which can be necessary if debhelper wrongly detects that the package
+uses MakeMaker.
+
+ #!/usr/bin/make -f
+ %:
+ dh $@ --buildsystem=perl_build
To patch your package using quilt, you can tell dh to use quilt's dh
sequence addons like this:
#!/usr/bin/make -f
%:
- dh --with quilt $@
+ dh $@ --with quilt
Here is an example of overriding where the dh_auto_* commands find
the package's source, for a package where the source is located in a
-subdirectory. It also forces use of perl's Module::Build build system,
-which can be necessary if debhelper wrongly detects that the package
-uses MakeMaker.
+subdirectory.
+
+ #!/usr/bin/make -f
+ %:
+ dh $@ --sourcedirectory=src
+
+And here is an example of how to tell the dh_auto_* commands to build
+in a subdirectory, which will be removed on clean.
+
+ #!/usr/bin/make -f
+ %:
+ dh $@ --builddirectory=build
+
+If your package can be built in parallel, you can support parallel building
+as follows. Then I<dpkg-buildpackage -j> will work.
+
+ #!/usr/bin/make -f
+ %:
+ dh $@ --parallel
+
+Here is a way to prevent dh from running several commands that you don't
+want it to run, by defining empty override targets for each command.
#!/usr/bin/make -f
%:
- dh --sourcedirectory=src --buildsystem=perl_build $@
+ dh $@
+
+ # Commands not to run:
+ override_dh_auto_test override_dh_compress override_dh_fixperms:
+
+Sometimes, you may need to make an override target only run commands when a
+particular package is being built. This can be accomplished using
+L<dh_listpackages(1)> to test what is being built. For example:
+
+ #!/usr/bin/make -f
+ %:
+ dh $@
+
+ override_dh_fixperms:
+ dh_fixperms
+ ifneq (,$(findstring foo, $(shell dh_listpackages)))
+ chmod 4755 debian/foo/usr/bin/foo
+ endif
+
+Finally, remember that you are not limited to using override targets in the
+rules file when using dh. You can also explicitly define any of the regular
+rules file targets when it makes sense to do so. A common reason to do this
+is if your package needs different build-arch and build-indep targets. For
+example, a package with a long document build process can put it in
+build-indep to avoid build daemons redundantly building the documentation.
+
+ #!/usr/bin/make -f
+ %:
+ dh $@
+
+ build: build-arch build-indep ;
+ build-indep:
+ $(MAKE) docs
+ build-arch:
+ $(MAKE) bins
+
+=head1 INTERNALS
+
+If you're curious about dh's internals, here's how it works under the hood.
+
+Each debhelper command will record when it's successfully run in
+debian/package.debhelper.log. (Which dh_clean deletes.) So dh can tell
+which commands have already been run, for which packages, and skip running
+those commands again.
+
+Each time dh is run, it examines the log, and finds the last logged command
+that is in the specified sequence. It then continues with the next command
+in the sequence. The B<--until>, B<--before>, B<--after>, and B<--remaining>
+options can override this behavior.
+
+dh uses the DH_INTERNAL_OPTIONS environment variable to pass information
+through to debhelper commands that are run inside override targets. The
+contents (and indeed, existence) of this environment variable, as the name
+might suggest, is subject to change at any time.
=cut
# (and comes first so python-central loads later and can disable it).
unshift @ARGV, "--with=python-support";
-# Disable complaints about unknown options for both dh and the commands
-# it runs. This is done because dh accepts and passes on options that may
-# be specific to only some debhelper commands.
-$ENV{DH_IGNORE_UNKNOWN_OPTIONS}=1;
-
init(options => {
- "until=s" => \$dh{UNTIL},
- "after=s" => \$dh{AFTER},
- "before=s" => \$dh{BEFORE},
- "remaining" => \$dh{REMAINING},
- "with=s" => sub {
- my ($option,$value)=@_;
- push @{$dh{WITH}},split(",", $value);
+ "until=s" => \$dh{UNTIL},
+ "after=s" => \$dh{AFTER},
+ "before=s" => \$dh{BEFORE},
+ "remaining" => \$dh{REMAINING},
+ "with=s" => sub {
+ my ($option,$value)=@_;
+ push @{$dh{WITH}},split(",", $value);
+ },
+ "without=s" => sub {
+ my ($option,$value)=@_;
+ @{$dh{WITH}} = grep { $_ ne $value } @{$dh{WITH}};
+ },
+ "l" => \&list_addons,
+ "list" => \&list_addons,
},
- "without=s" => sub {
- my ($option,$value)=@_;
- @{$dh{WITH}} = grep { $_ ne $value } @{$dh{WITH}};
- },
- "l" => \$dh{LIST},
- "list" => \$dh{LIST},
-});
+ # Disable complaints about unknown options; they are passed on to
+ # the debhelper commands.
+ ignore_unknown_options => 1,
+ # Bundling does not work well since there are unknown options.
+ bundling => 0,
+);
inhibit_log();
+
+# If make is using a jobserver, but it is not available
+# to this process, clean out MAKEFLAGS. This avoids
+# ugly warnings when calling make.
+if (is_make_jobserver_unavailable()) {
+ clean_jobserver_makeflags();
+}
+
# Definitions of sequences.
my %sequences;
$sequences{build} = [qw{
dh_installcatalogs
dh_installcron
dh_installdebconf
- dh_installcatalogs
dh_installemacsen
dh_installifupdown
dh_installinfo
}, @b];
$sequences{'binary-arch'} = [@{$sequences{binary}}];
+# Additional command options
+my %command_opts;
+
# sequence addon interface
sub _insert {
my $offset=shift;
my $sequence=shift;
unshift @{$sequences{$sequence}}, $command;
}
+sub add_command_options {
+ my $command=shift;
+ push @{$command_opts{$command}}, @_;
+}
+sub remove_command_options {
+ my $command=shift;
+ if (@_) {
+ # Remove only specified options
+ if (my $opts = $command_opts{$command}) {
+ foreach my $opt (@_) {
+ $opts = [ grep { $_ ne $opt } @$opts ];
+ }
+ $command_opts{$command} = $opts;
+ }
+ }
+ else {
+ # Clear all additional options
+ delete $command_opts{$command};
+ }
+}
-if ($dh{LIST}) {
+sub list_addons {
my %addons;
for my $inc (@INC) {
}
}
-# Get the sequence of commands to run.
-if (! @ARGV) {
+my $sequence;
+if (! compat(7)) {
+ # From v8, the sequence is the very first parameter.
+ $sequence=shift @ARGV_orig;
+ if ($sequence=~/^-/) {
+ error "Unknown sequence $sequence (options should not come before the sequence)";
+ }
+}
+else {
+ # Before v8, the sequence could be at any position in the parameters,
+ # so was what was left after parsing.
+ $sequence=shift;
+ if (defined $sequence) {
+ @ARGV_orig=grep { $_ ne $sequence } @ARGV_orig;
+ }
+}
+if (! defined $sequence) {
error "specify a sequence to run";
}
-my $sequence=shift;
if ($sequence eq 'debian/rules' ||
$sequence =~ /^override_dh_/) {
- # make -B causes the rules file to be run as a target
- # and support completly empty override targets
- exit 0
-}
+ # make -B causes the rules file to be run as a target.
+ # Also support completly empty override targets.
+ exit 0;
+}
elsif (! exists $sequences{$sequence}) {
error "Unknown sequence $sequence (choose from: ".
join(" ", sort keys %sequences).")";
}
while (@ARGV_orig) {
my $opt=shift @ARGV_orig;
- next if $opt eq $sequence;
if ($opt =~ /^--?(after|until|before|with|without)$/) {
shift @ARGV_orig;
next;
elsif ($opt =~ /^--?(no-act|remaining|(after|until|before|with|without)=)/) {
next;
}
- push @options, $opt;
+ elsif ($opt=~/^-/) {
+ push @options, "-O".$opt;
+ }
+ elsif (@options) {
+ if ($options[$#options]=~/^-O--/) {
+ $options[$#options].="=".$opt;
+ }
+ else {
+ $options[$#options].=$opt;
+ }
+ }
}
# Figure out at what point in the sequence to start for each package.
# Check for override targets in debian/rules and
# run them instead of running the command directly.
my $override_command;
- if (rules_explicit_target("override_".$command)) {
+ my $has_explicit_target = rules_explicit_target("override_".$command);
+ if (defined $has_explicit_target) {
$override_command=$command;
- # This passes the options through to commands called
- # inside the target.
- $ENV{DH_INTERNAL_OPTIONS}=join("\x1e", @options);
- $command="debian/rules";
- @options="override_".$override_command;
+ # Check if target isn't noop
+ if ($has_explicit_target) {
+ # This passes the options through to commands called
+ # inside the target.
+ $ENV{DH_INTERNAL_OPTIONS}=join("\x1e", @options);
+ $command="debian/rules";
+ @options="override_".$override_command;
+ }
+ else {
+ $command = undef;
+ }
+ }
+ else {
+ # Pass additional command options if any
+ unshift @options, @{$command_opts{$command}} if exists $command_opts{$command};
}
- # 3 space indent lines the command being run up under the
- # sequence name after "dh ".
- print " ".escape_shell($command, @options)."\n";
+ if (defined $command) {
+ # 3 space indent lines the command being run up under the
+ # sequence name after "dh ".
+ print " ".escape_shell($command, @options)."\n";
+ }
+ else {
+ print " ", "# Skipping ", $override_command, " - empty override", "\n";
+ }
if (! $dh{NO_ACT}) {
- my $ret=system($command, @options);
- if ($ret >> 8 != 0) {
- exit $ret >> 8;
- }
- elsif ($ret) {
- exit 1;
+ if (defined $command) {
+ my $ret=system($command, @options);
+ if ($ret >> 8 != 0) {
+ exit $ret >> 8;
+ }
+ elsif ($ret) {
+ exit 1;
+ }
}
if (defined $override_command) {
sub rules_explicit_target {
# Checks if a specified target exists as an explicit target
- # in debian/rules.
+ # in debian/rules.
+ # undef is returned if target does not exist, 0 if target is noop
+ # and 1 if target has dependencies or executes commands.
my $target=shift;
-
- if (! $rules_parsed) {
+
+ if (! $rules_parsed) {
my $processing_targets = 0;
my $not_a_target = 0;
+ my $current_target;
open(MAKE, "LC_ALL=C make -Rrnpsf debian/rules debhelper-fail-me 2>/dev/null |");
while (<MAKE>) {
if ($processing_targets) {
$not_a_target = 1;
}
else {
- if (!$not_a_target && /^([^#:]+)::?/) {
- # Target is defined.
- # NOTE: if it is a depenency
- # of .PHONY it will be
- # defined too but that's ok.
- $targets{$1} = 1;
+ if (!$not_a_target && /^([^#:]+)::?\s*(.*)$/) {
+ # Target is defined. NOTE: if it is a depenency of
+ # .PHONY it will be defined too but that's ok.
+ # $2 contains target dependencies if any.
+ $current_target = $1;
+ $targets{$current_target} = ($2) ? 1 : 0;
+ }
+ else {
+ if (defined $current_target) {
+ if (/^#/) {
+ # Check if target has commands to execute
+ if (/^#\s*commands to execute/) {
+ $targets{$current_target} = 1;
+ }
+ }
+ else {
+ # Target parsed.
+ $current_target = undef;
+ }
+ }
}
# "Not a target:" is always followed by
# a target name, so resetting this one
# here is safe.
$not_a_target = 0;
}
- } elsif (/^# Files$/) {
+ }
+ elsif (/^# Files$/) {
$processing_targets = 1;
}
}
$rules_parsed = 1;
}
- return exists $targets{$target};
+ return $targets{$target};
}
}