Package: debhelper
Version: 8.1.6
Severity: normal
Tags: patch
Hi Joey,
I think I may have proposed something similar to this patch before, but
I can't find it in the BTS. This was something I was working on last
year WRT the build-arch/build-indep patches you applied already.
Possibly it was included as part of the patch set in one of the closed
bugs. I'm probably just being blind. The attached patches are reworked
to apply on top of the current git master.
The dh "sequences" don't behave well if you have the catch-all
%:
dh $@
in your debian/rules /plus/ additional rules such as "build", even if
the additional rules such as this ultimately call back into dh via e.g.
"dh build".
The sequences as currently implemented simply concatenate the jobs for
dependent sequences. E.g. the "binary" sequence contains all of the
"install" sequence jobs, plus its own. And the "install" sequence
contains all of the "build" sequence jobs, plus its own. This can lead
to inconsistent builds depending upon the order in which you invoke the
make rules, which is quite easily preventable.
The main issue here is that if one runs by hand
fakeroot debian/rules binary
and this calls "dh binary", it will run all the jobs in the binary
sequence. /However/, it will never call "debian/rules build" to do
the build, so if the user wrote a custom build rule, it will never
be called. The fact that the binary sequence included all the
build sequence jobs is not a sufficient substitute for the lack of
a call of the build target in debian/rules.
Given that dpkg-buildpackage always calls "debian/rules build" before
"debian/rules binary*", the user's build target will be called /if/
they built via dpkg-buildpackage. But, other targets such as
build-arch and build-indep will /not/. The same applies to binary-arch
and binary-indep targets etc..
What this patch does is to make dh sequences restricted to their
particular job, and not include the dependent sequence jobs. Instead
it invokes dh recursively via debian/rules. i.e. dh build would,
instead of including the install targets, run "debian/rules install*"
which (if the user hasn't includes their own) will then run
"dh install*". This in turn will call the appropriate build targets.
While this does have a small overhead of running additional instances
of make and dh, the overhead is fairly insignificant in the context of
the number of sub-makes run during a typical build. And the benefits
it provides outweigh the tiny overhead.
This patch permits the user to naturally use policy-defined rules in
a completely transparent and clean way, which makes dh behave
identically irrespectively of the order in which the sequences are
called. All the standard debian/rules targets will be called when
needed, and will not be bypassed.
The second patch allows less transparent addition of custom rules to
make custom stuff happen for arch-dependent and independent packages
following the invocation of the corresponding dh_ command. I think
you weren't too happy with this patch in the past, but I can't find
a reference to it now. I've just included it anyway, but the first
patch is the more important one.
Regards,
Roger
-- System Information:
Debian Release: 6.0.1
APT prefers stable
APT policy: (500, 'stable')
Architecture: i386 (i686)
Kernel: Linux 2.6.32.27-kvm-i386-20110114 (SMP w/1 CPU core)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
>From f6563b39ab7379cfd800cd58f72d6fca15c98810 Mon Sep 17 00:00:00 2001
From: Roger Leigh <[email protected]>
Date: Fri, 3 Jun 2011 20:41:30 +0100
Subject: [PATCH 1/2] dh: Add sequence dependency support
---
dh | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 113 insertions(+), 16 deletions(-)
diff --git a/dh b/dh
index 50e0f14..fe6a245 100755
--- a/dh
+++ b/dh
@@ -151,6 +151,16 @@ either and instead run your own commands.
override_dh_auto_build:
make universe-explode-in-delight
+If running a configure script, it may be necessary to prevent it being
+run twice, once for architecture-independent packages, and again for
+architecture-dependent packages. This may be accomplished by
+overriding L<dh_autoconfigure(1)>:
+
+ override_dh_auto_configure: config.status
+
+ config.status:
+ dh_auto_configure -- $configure_options
+
Another common case is wanting to do something manually before or
after a particular debhelper command is run.
@@ -273,6 +283,16 @@ 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.
+A sequence can also have dependencies. For example, the "binary"
+sequence depends upon the "binary-arch" and "binary-indep" sequences,
+and the "binary-arch" sequence depends upon the "install-arch"
+sequence which in turn depends upon the "build-arch" sequence. These
+will, by default, be run via "debian/rules <sequence>" and so may be
+overridden or extended there, or else will run dh again to execute the
+depending sequence. For example, "dh binary-arch" will run
+"debian/rules install-arch" which will run "dh install-arch" unless a
+custom install-arch target replaces the default target.
+
B<dh> uses the B<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
@@ -321,14 +341,15 @@ if (is_make_jobserver_unavailable()) {
# Definitions of sequences.
my %sequences;
-$sequences{build} = [qw{
+my @bd = qw{
dh_testdir
dh_auto_configure
dh_auto_build
dh_auto_test
-}],
-$sequences{'build-indep'} = [@{$sequences{build}}];
-$sequences{'build-arch'} = [@{$sequences{build}}];
+};
+$sequences{build} = [@bd];
+$sequences{'build-indep'} = [@bd];
+$sequences{'build-arch'} = [@bd];
$sequences{clean} = [qw{
dh_testdir
dh_auto_clean
@@ -376,9 +397,9 @@ my @i = qw{
dh_compress
dh_fixperms
};
-$sequences{'install'} = [@{$sequences{build}}, @i];
-$sequences{'install-indep'} = [@{$sequences{'build-indep'}}, @i];
-$sequences{'install-arch'} = [@{$sequences{'build-arch'}}, @i];
+$sequences{'install'} = [@i];
+$sequences{'install-indep'} = [@i];
+$sequences{'install-arch'} = [@i];
my @ba=qw{
dh_strip
dh_makeshlibs
@@ -390,9 +411,19 @@ my @b=qw{
dh_md5sums
dh_builddeb
};
-$sequences{binary} = [@{$sequences{install}}, @ba, @b];
-$sequences{'binary-indep'} = [@{$sequences{'install-indep'}}, @b];
-$sequences{'binary-arch'} = [@{$sequences{'install-arch'}}, @ba, @b];
+$sequences{binary} = [@ba, @b];
+$sequences{'binary-indep'} = [@b];
+$sequences{'binary-arch'} = [@ba, @b];
+
+# Sequence dependencies
+my %sequence_deps;
+$sequence_deps{build} = ['build-arch', 'build-indep'];
+$sequence_deps{install} = ['install-arch', 'install-indep'];
+$sequence_deps{'install-arch'} = ['build-arch'];
+$sequence_deps{'install-indep'} = ['build-indep'];
+$sequence_deps{binary} = ['binary-arch', 'binary-indep'];
+$sequence_deps{'binary-arch'} = ['install-arch'];
+$sequence_deps{'binary-indep'} = ['install-indep'];
# Additional command options
my %command_opts;
@@ -521,6 +552,29 @@ elsif (! exists $sequences{$sequence}) {
}
my @sequence=@{$sequences{$sequence}};
+# Recursively invoke sequence dependencies before any further processing.
+# The dh options are not passed in the environment, to ensure that the
+# behaviour is the same if invoked directly.
+my $deps = undef;
+$deps = $sequence_deps{$sequence}
+ if (exists($sequence_deps{$sequence}));
+if (defined($deps)) {
+ foreach my $dep (@$deps) {
+ my $command = 'debian/rules';
+ my @dep_options = ($dep);
+ print " ".escape_shell($command, @dep_options)."\n";
+ if (! $dh{NO_ACT}) {
+ my $ret=system($command, @dep_options);
+ if ($ret >> 8 != 0) {
+ exit $ret >> 8;
+ }
+ elsif ($ret) {
+ exit 1;
+ }
+ }
+ }
+}
+
# The list of all packages that can be acted on.
my @packages=@{$dh{DOPACKAGES}};
@@ -641,20 +695,57 @@ sub run {
# to prevent them from being acted on.
push @options, map { "-N$_" } @exclude;
+ my $arch = grep {$_ eq '-a'} @options;
+ my $indep = grep {$_ eq '-i'} @options;
+ my $orig_command = $command;
+
+ # Check for override targets in debian/rules and
+ # run them instead of running the command directly.
+ my $has_explicit_target =
rules_explicit_target("override_".$orig_command);
+ if (defined $has_explicit_target) {
+ run_hook("override_".$orig_command, \@packages, \@exclude,
@options);
+ }
+ else {
+ # Pass additional command options if any
+ unshift @options, @{$command_opts{$command}} if exists
$command_opts{$command};
+ if (defined $command) {
+ # 3 space indent lines the command being run up under
the
+ # sequence name after "dh ".
+ print " ".escape_shell($command, @options)."\n";
+ }
+
+ if (! $dh{NO_ACT}) {
+ if (defined $command) {
+ my $ret=system($command, @options);
+ if ($ret >> 8 != 0) {
+ exit $ret >> 8;
+ }
+ elsif ($ret) {
+ exit 1;
+ }
+ }
+ }
+ }
+}
+
+sub run_hook {
+ my $command=shift;
+ my @packages=@{shift()};
+ my @exclude=@{shift()};
+ my @options=@_;
+
+ my @orig_options = @options;
+
# 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);
+ my $has_explicit_target = rules_explicit_target($command);
if (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;
+ @options=$override_command;
}
else {
$command = undef;
@@ -676,6 +767,10 @@ sub run {
if (! $dh{NO_ACT}) {
if (defined $command) {
+ # This passes the options through to commands called
+ # inside the target.
+ $ENV{DH_INTERNAL_OPTIONS}=join("\x1e", @orig_options);
+ $ENV{DH_INTERNAL_OVERRIDE}=$command;
my $ret=system($command, @options);
if ($ret >> 8 != 0) {
@@ -684,6 +779,8 @@ sub run {
elsif ($ret) {
exit 1;
}
+ delete $ENV{DH_INTERNAL_OPTIONS};
+ delete $ENV{DH_INTERNAL_OVERRIDE};
}
if (defined $override_command) {
--
1.7.5.3
>From 5177ebf140861620e010d59fcf4141e51e59ac51 Mon Sep 17 00:00:00 2001
From: Roger Leigh <[email protected]>
Date: Fri, 3 Jun 2011 20:42:50 +0100
Subject: [PATCH 2/2] dh: Add hook support
---
dh | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 65 insertions(+), 0 deletions(-)
diff --git a/dh b/dh
index fe6a245..b539ef0 100755
--- a/dh
+++ b/dh
@@ -32,6 +32,18 @@ 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
+I<dh_command>B<_hook>, I<dh_command>B<_indep_hook> or
+I<dh_command>B<_arch_hook>, these targets will be called I<after>
+I<dh_command> has been run. I<dh_command_hook> will be run for all
+packages, while I<dh_command_indep_hook> will only be run for
+architecture independent packages and I<dh_command_arch_hook> will
+only be run for architecture dependent packages. The hook targets may
+be used to run additional commands after the I<dh_command> has
+run. See examples below. (Note that to use this feature, you should
+Build-Depend on debhelper 8.1.0 or above.)
+
+
=head1 OPTIONS
=over 4
@@ -249,6 +261,31 @@ L<dh_listpackages(1)> to test what is being built. For
example:
chmod 4755 debian/foo/usr/bin/foo
endif
+Or using a hook, run after dh_fixperms:
+
+ #!/usr/bin/make -f
+ %:
+ dh $@
+
+ dh_fixperms_hook:
+ ifneq (,$(filter foo, $(shell dh_listpackages)))
+ chmod 4755 debian/foo/usr/bin/foo
+ endif
+
+It may also be possible to do this more simply using a more specific
+hook:
+
+ #!/usr/bin/make -f
+ %:
+ dh $@
+
+ dh_fixperms_arch_hook:
+ chmod 4755 debian/foo/usr/bin/foo
+
+This is for the case where foo is an architecture dependent package;
+if foo is an architecture independent package then
+dh_fixperms_indep_hook would be the correct target to use.
+
Finally, remember that you are not limited to using override targets in the
rules file when using B<dh>. You can also explicitly define the regular
rules file targets when it makes sense to do so. A common reason to do this
@@ -269,6 +306,15 @@ B<build-indep>.
build-arch:
$(MAKE) bins
+Or alternatively, using hooks:
+
+ dh_auto_build_indep_hook:
+ $(MAKE) docs
+
+ dh_auto_build_arch_hook:
+ $(MAKE) bins
+
+
=head1 INTERNALS
If you're curious about B<dh>'s internals, here's how it works under the hood.
@@ -726,6 +772,25 @@ sub run {
}
}
}
+
+ if ($arch || $indep) {
+ $has_explicit_target = rules_explicit_target($orig_command."_hook");
+ if (defined $has_explicit_target) {
+ run_hook($orig_command."_hook", \@packages, \@exclude,
@options);
+ }
+ }
+ if ($arch) {
+ $has_explicit_target =
rules_explicit_target($orig_command."_arch_hook");
+ if (defined $has_explicit_target) {
+ run_hook($orig_command."_arch_hook", \@packages, \@exclude,
@options);
+ }
+ }
+ if ($indep) {
+ $has_explicit_target =
rules_explicit_target($orig_command."_indep_hook");
+ if (defined $has_explicit_target) {
+ run_hook($orig_command."_indep_hook", \@packages, \@exclude,
@options);
+ }
+ }
}
sub run_hook {
--
1.7.5.3