=head1 SYNOPSIS
-B<dh> I<sequence> [B<--with> I<addon>[B<,>I<addon> ...]] [B<--list>] [B<--until> I<cmd>] [B<--before> I<cmd>] [B<--after> I<cmd>] [B<--remaining>] [S<I<debhelper options>>]
+B<dh> I<sequence> [B<--with> I<addon>[B<,>I<addon> ...]] [B<--list>] [S<I<debhelper options>>]
=head1 DESCRIPTION
B<build-indep>, B<build>, B<clean>, B<install-indep>, B<install-arch>,
B<install>, B<binary-arch>, B<binary-indep>, and B<binary>.
-Commands in the B<build-indep>, B<install-indep> and B<binary-indep>
-sequences are passed the B<-i> option to ensure they only work on
-architecture independent packages, and commands in the B<build-arch>,
-B<install-arch> and B<binary-arch> sequences are passed the B<-a>
-option to ensure they only work on architecture dependent packages.
+=head1 OVERRIDE TARGETS
+
+A F<debian/rules> file using B<dh> can override the command that is run
+at any step in a sequence, by defining an override target.
+
+To override I<dh_command>, add a target named B<override_>I<dh_command> to
+the rules file. When it would normally run I<dh_command>, B<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.)
-If F<debian/rules> contains a target with a name like B<override_>I<dh_command>,
-then when it would normally run I<dh_command>, B<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.)
+Override targets can also be defined to run only when building
+architecture dependent or architecture independent packages.
+Use targets with names like B<override_>I<dh_command>B<-arch>
+and B<override_>I<dh_command>B<-indep>.
+(Note that to use this feature, you should Build-Depend on
+debhelper 8.9.7 or above.)
=head1 OPTIONS
=item B<--without> I<addon>
-The inverse of B<--with>, disables using the given addon.
+The inverse of B<--with>, disables using the given addon. This option
+can be repeated more than once, or multiple addons to disable can be
+listed, separated by commas.
=item B<--list>, B<-l>
List all available addons.
-=item B<--until> I<cmd>
-
-Run commands in the sequence until and including I<cmd>, then stop.
-
-=item B<--before> I<cmd>
-
-Run commands in the sequence before I<cmd>, then stop.
-
-=item B<--after> I<cmd>
-
-Run commands in the sequence that come after I<cmd>.
-
-=item B<--remaining>
-
-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 B<dh> are passed on to each command it runs. This
+Other options passed to B<dh> are passed on to each command it runs. This
can be used to set an option like B<-v> or B<-X> or B<-N>, as well as for more
specialised options.
-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
-
-sub command_pos {
- my $command=shift;
- my @sequence=@_;
-
- foreach my $i (0..$#sequence) {
- if ($command eq $sequence[$i]) {
- return $i;
- }
- }
-
- my @matches;
- foreach my $i (0..$#sequence) {
- if ($sequence[$i] =~ /\Q$command\E/) {
- push @matches, $i;
- }
- }
- if (! @matches) {
- error "command specification \"$command\" does not match any command in the sequence"
- }
- else {
- return pop @matches;
- }
-}
-
=head1 EXAMPLES
To see what commands are included in a sequence, without actually doing
Often you'll want to pass an option to a specific debhelper command. The
easy way to do with is by adding an override target for that command.
-
+
#!/usr/bin/make -f
%:
dh $@
-
+
override_dh_strip:
dh_strip -Xfoo
-
- override_dh_installdocs:
- dh_installdocs README TODO
+
+ override_dh_auto_configure:
+ dh_auto_configure -- --with-foo --disable-bar
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
dh_fixperms
chmod 4755 debian/foo/usr/bin/foo
-If your package is a Python package, B<dh> will use B<dh_pysupport> by
-default. This is how to use B<dh_pycentral> instead.
-
- #!/usr/bin/make -f
- %:
- dh $@ --with python-central
-
If your package uses autotools and you want to freshen F<config.sub> and
F<config.guess> with newer versions from the B<autotools-dev> package
at build time, you can use some commands provided in B<autotools-dev>
%:
dh $@ --with autotools_dev
+Python tools are not run by dh by default, due to the continual change
+in that area. (Before compatibility level v9, dh does run B<dh_pysupport>.)
+Here is how to use B<dh_python2>.
+
+ #!/usr/bin/make -f
+ %:
+ dh $@ --with python2
+
Here is how to force use of Perl's B<Module::Build> build system,
which can be necessary if debhelper wrongly detects that the package
uses MakeMaker.
%:
dh $@ --buildsystem=perl_build
-To patch your package using quilt, you can tell B<dh> to use quilt's B<dh>
-sequence addons like this:
-
- #!/usr/bin/make -f
- %:
- dh $@ --with quilt
-
Here is an example of overriding where the B<dh_auto_>I<*> commands find
the package's source, for a package where the source is located in a
subdirectory.
# 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:
+A long build process for a separate documentation package can
+be separated out using architecture independent overrides.
+These will be skipped when running build-arch and binary-arch sequences.
#!/usr/bin/make -f
%:
dh $@
- override_dh_fixperms:
- dh_fixperms
- ifneq (,$(filter foo, $(shell dh_listpackages)))
- chmod 4755 debian/foo/usr/bin/foo
- endif
+ override_dh_auto_build-indep:
+ $(MAKE) -C docs
-Finally, remember that you are not limited to using override targets in the
-rules file when using B<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 when your package needs different B<build-arch> and B<build-indep> targets.
-For example, a package with a long document build process can put it in
-B<build-indep>.
+ # No tests needed for docs
+ override_dh_auto_test-indep:
- #!/usr/bin/make -f
- %:
- dh $@
-
- build-indep:
- $(MAKE) docs
- build-arch:
- $(MAKE) bins
+ override_dh_auto_install-indep:
+ $(MAKE) -C docs install
-Note that in the example above, dh will arrange for "debian/rules build"
-to call your build-indep and build-arch targets. You do not need to
-explicitly define the dependencies in the rules file when using dh with
-compatability level v9. This example would be more complicated with
-earlier compatability levels.
+Adding to the example above, suppose you need to chmod a file, but only
+when building the architecture dependent package, as it's not present
+when building only documentation.
+
+ override_dh_fixperms-arch:
+ dh_fixperms
+ chmod 4755 debian/foo/usr/bin/foo
=head1 INTERNALS
contents (and indeed, existence) of this environment variable, as the name
might suggest, is subject to change at any time.
+Commands in the B<build-indep>, B<install-indep> and B<binary-indep>
+sequences are passed the B<-i> option to ensure they only work on
+architecture independent packages, and commands in the B<build-arch>,
+B<install-arch> and B<binary-arch> sequences are passed the B<-a>
+option to ensure they only work on architecture dependent packages.
+
+=head1 DEPRECATED OPTIONS
+
+The following options are deprecated. It's much
+better to use override targets instead.
+
+=over 4
+
+=item B<--until> I<cmd>
+
+Run commands in the sequence until and including I<cmd>, then stop.
+
+=item B<--before> I<cmd>
+
+Run commands in the sequence before I<cmd>, then stop.
+
+=item B<--after> I<cmd>
+
+Run commands in the sequence that come after I<cmd>.
+
+=item B<--remaining>
+
+Run all commands in the sequence that have yet to be run.
+
+=back
+
+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
# Stash this away before init modifies it.
my @ARGV_orig=@ARGV;
-# python-support is enabled by default, at least for now
-# (and comes first so python-central loads later and can disable it).
-unshift @ARGV, "--with=python-support";
+if (compat(8, 1)) {
+ # python-support was enabled by default before v9.
+ # (and comes first so python-central loads later and can disable it).
+ unshift @ARGV, "--with=python-support";
+}
init(options => {
"until=s" => \$dh{UNTIL},
},
"without=s" => sub {
my ($option,$value)=@_;
- @{$dh{WITH}} = grep { $_ ne $value } @{$dh{WITH}};
+ my %without = map { $_ => 1 } split(",", $value);
+ @{$dh{WITH}} = grep { ! $without{$_} } @{$dh{WITH}};
},
"l" => \&list_addons,
"list" => \&list_addons,
bundling => 0,
);
inhibit_log();
-
+set_buildflags();
+warn_deprecated();
# If make is using a jobserver, but it is not available
# to this process, clean out MAKEFLAGS. This avoids
if (! compat(7)) {
# From v8, the sequence is the very first parameter.
$sequence=shift @ARGV_orig;
- if ($sequence=~/^-/) {
+ if (defined $sequence && $sequence=~/^-/) {
error "Unknown sequence $sequence (options should not come before the sequence)";
}
}
error "specify a sequence to run";
}
# make -B causes the rules file to be run as a target.
-# Also support completly empty override targets.
+# Also support completely empty override targets.
# Note: it's not safe to use rules_explicit_target before this check,
# since it causes dh to be run.
my $dummy_target="debhelper-fail-me";
dh_auto_build
dh_auto_test
};
-my @i_minimal = qw{
- dh_testroot
-};
my @i = qw{
dh_testroot
dh_prep
dh_makeshlibs
dh_shlibdeps
};
+if (! getpackages("arch")) {
+ @ba=();
+}
my @b=qw{
dh_installdeb
dh_gencontrol
$sequences{'build-arch'} = [@bd];
if (! compat(8)) {
# From v9, sequences take standard rules targets into account.
- if (rules_explicit_target('build-arch') ||
- rules_explicit_target('build-indep')) {
- # run sequences separately
- $sequences{build} = [@bd_minimal, rules("build-arch"), rules("build-indep")];
- }
- else {
- # run standard sequence (this is faster)
- $sequences{build} = [@bd];
- }
+ $sequences{build} = [@bd_minimal, rules("build-arch"), rules("build-indep")];
$sequences{'install-indep'} = [rules("build-indep"), @i];
$sequences{'install-arch'} = [rules("build-arch"), @i];
- if (rules_explicit_target('install-arch') ||
- rules_explicit_target('install-indep')) {
- # run sequences separately
- $sequences{'install'} = [rules("build"), @i_minimal, rules("install-arch"), rules("install-indep")];
- }
- else {
- # run standard sequence (this is faster)
- $sequences{'install'} = [rules("build"), @i, rules("install-arch"), rules("install-indep")];
- }
+ $sequences{'install'} = [rules("build"), rules("install-arch"), rules("install-indep")];
$sequences{'binary-indep'} = [rules("install-indep"), @b];
$sequences{'binary-arch'} = [rules("install-arch"), @ba, @b];
$sequences{binary} = [rules("install"), rules("binary-arch"), rules("binary-indep")];
# Now run the commands in the sequence.
foreach my $i (0..$stoppoint) {
+ my $command=$sequence[$i];
+
# Figure out which packages need to run this command.
- my @exclude;
+ my @todo;
+ my @opts=@options;
foreach my $package (@packages) {
if ($startpoint{$package} > $i ||
$logged{$package}{$sequence[$i]}) {
- push @exclude, $package;
+ push @opts, "-N$package";
+ }
+ else {
+ push @todo, $package;
}
}
-
- if (@exclude eq @packages) {
- # Command already done for all packages.
+ next unless @todo;
+
+ my $rules_target = rules_target($command);
+ if (defined $rules_target) {
+ # Don't pass DH_ environment variables, since this is
+ # a fresh invocation of debian/rules and any sub-dh commands.
+ delete $ENV{DH_INTERNAL_OPTIONS};
+ delete $ENV{DH_INTERNAL_OVERRIDE};
+ run("debian/rules", $rules_target);
next;
}
+
+ # Check for override targets in debian/rules, and run instead of
+ # the usual command. (The non-arch-specific override is tried first,
+ # for simplest semantics; mixing it with arch-specific overrides
+ # makes little sense.)
+ my @oldtodo=@todo;
+ foreach my $override_type (undef, "arch", "indep") {
+ @todo = run_override($override_type, $command, \@todo, @opts);
+ }
+ next unless @todo;
+
+ # No need to run the command for any packages handled by the
+ # override targets.
+ my %todo=map { $_ => 1 } @todo;
+ foreach my $package (@oldtodo) {
+ if (! $todo{$package}) {
+ push @opts, "-N$package";
+ }
+ }
- run($sequence[$i], \@packages, \@exclude, @options);
+ run($command, @opts);
}
sub run {
my $command=shift;
- my @packages=@{shift()};
- my @exclude=@{shift()};
my @options=@_;
-
- # If some packages are excluded, add flags
- # to prevent them from being acted on.
- push @options, map { "-N$_" } @exclude;
- # Check for override targets in debian/rules and
- # run them instead of running the command directly.
- my $override_command;
- my $has_explicit_target = rules_explicit_target("override_".$command);
+ # Include additional command options if any
+ unshift @options, @{$command_opts{$command}}
+ if exists $command_opts{$command};
- my $rules_target = rules_target($command);
- if (defined $rules_target) {
- # Don't pass DH_ environment variables, since this is
- # a fresh invocation of debian/rules and any sub-dh
- # commands.
- $override_command=$command;
- delete $ENV{DH_INTERNAL_OPTIONS};
- delete $ENV{DH_INTERNAL_OVERRIDE};
- $command="debian/rules";
- @options=$rules_target;
- }
- elsif (defined $has_explicit_target) {
- $override_command=$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);
- $ENV{DH_INTERNAL_OVERRIDE}=$command;
- $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";
+ return if $dh{NO_ACT};
+
+ my $ret=system($command, @options);
+ if ($ret >> 8 != 0) {
+ exit $ret >> 8;
}
- else {
- print " ", "# Skipping ", $override_command, " - empty override", "\n";
+ elsif ($ret) {
+ exit 1;
}
-
- if (! $dh{NO_ACT}) {
- if (defined $command) {
- my $ret=system($command, @options);
-
- if ($ret >> 8 != 0) {
- exit $ret >> 8;
+}
+
+# Tries to run an override target for a command. Returns the list of
+# packages that it was unable to run an override target for.
+sub run_override {
+ my $override_type=shift; # arch, indep, or undef
+ my $command=shift;
+ my @packages=@{shift()};
+ my @options=@_;
+
+ my $override="override_$command".
+ (defined $override_type ? "-".$override_type : "");
+
+ # Check which packages are of the right architecture for the
+ # override_type.
+ my (@todo, @rest);
+ if (defined $override_type) {
+ foreach my $package (@packages) {
+ my $isall=package_arch($package) eq 'all';
+ if (($override_type eq 'indep' && $isall) ||
+ ($override_type eq 'arch' && !$isall)) {
+ push @todo, $package;
}
- elsif ($ret) {
- exit 1;
+ else {
+ push @rest, $package;
+ push @options, "-N$package";
}
}
+ }
+ else {
+ @todo=@packages;
+ }
- if (defined $override_command) {
- # Update log for overridden command now that it has
- # finished successfully.
- # (But avoid logging for dh_clean since it removes
- # the log earlier.)
- if ($override_command ne 'dh_clean') {
- my %packages=map { $_ => 1 } @packages;
- map { delete $packages{$_} } @exclude;
- write_log($override_command, keys %packages);
- commit_override_log(keys %packages);
- }
+ my $has_explicit_target = rules_explicit_target($override);
+ return @packages unless defined $has_explicit_target; # no such override
+ return @rest if ! $has_explicit_target; # has empty override
+ return @rest unless @todo; # has override, but no packages to act on
- delete $ENV{DH_INTERNAL_OPTIONS};
- delete $ENV{DH_INTERNAL_OVERRIDE};
- }
+ if (defined $override_type) {
+ # Ensure appropriate -a or -i option is passed when running
+ # an arch-specific override target.
+ my $opt=$override_type eq "arch" ? "-a" : "-i";
+ push @options, $opt unless grep { $_ eq $opt } @options;
+ }
+
+ # This passes the options through to commands called
+ # inside the target.
+ $ENV{DH_INTERNAL_OPTIONS}=join("\x1e", @options);
+ $ENV{DH_INTERNAL_OVERRIDE}=$command;
+ run("debian/rules", $override);
+ delete $ENV{DH_INTERNAL_OPTIONS};
+ delete $ENV{DH_INTERNAL_OVERRIDE};
+
+ # Update log for overridden command now that it has
+ # finished successfully.
+ # (But avoid logging for dh_clean since it removes
+ # the log earlier.)
+ if (! $dh{NO_ACT} && $command ne 'dh_clean') {
+ write_log($command, @todo);
+ commit_override_log(@todo);
}
+
+ return @rest;
}
sub optimize_sequence {
}
sub rules {
- return "debian/rules ".@_;
+ return "debian/rules ".join(" ", @_);
}
{
}
else {
if (!$not_a_target && /^([^#:]+)::?\s*(.*)$/) {
- # Target is defined. NOTE: if it is a depenency of
+ # Target is defined. NOTE: if it is a dependency of
# .PHONY it will be defined too but that's ok.
# $2 contains target dependencies if any.
$current_target = $1;
if (defined $current_target) {
if (/^#/) {
# Check if target has commands to execute
- if (/^#\s*commands to execute/) {
+ if (/^#\s*(commands|recipe) to execute/) {
$targets{$current_target} = 1;
}
}
}
+sub warn_deprecated {
+ foreach my $deprecated ('until', 'after', 'before', 'remaining') {
+ if (defined $dh{uc $deprecated}) {
+ warning("The --$deprecated option is deprecated. Use override targets instead.");
+ }
+ }
+}
+
+sub command_pos {
+ my $command=shift;
+ my @sequence=@_;
+
+ foreach my $i (0..$#sequence) {
+ if ($command eq $sequence[$i]) {
+ return $i;
+ }
+ }
+
+ my @matches;
+ foreach my $i (0..$#sequence) {
+ if ($sequence[$i] =~ /\Q$command\E/) {
+ push @matches, $i;
+ }
+ }
+ if (! @matches) {
+ error "command specification \"$command\" does not match any command in the sequence"
+ }
+ else {
+ return pop @matches;
+ }
+}
+
=head1 SEE ALSO
L<debhelper(7)>