On Tue, Jun 07, 2011 at 01:47:41PM +0100, Roger Leigh wrote:
> On Tue, Jun 07, 2011 at 08:12:15AM -0400, Joey Hess wrote:
> > Roger Leigh wrote:
> > > I think I may have proposed something similar to this patch before, but
> > > I can't find it in the BTS.
> > 
> > It caused significant slowdown (due to running every debhelper command
> > twice with -a and -i) and quite likely broke packages due to
> > running make install twice, so was removed.
> > 
> > http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=604563#77
> > 
> > 657852b56b0d835afd4e45407d6e8d217c63ab20
> 
> I'm sure we can improve the performance with some additional work.
> 
> Currently we have the "sequence dependencies" as a separate
> list, not associated with the sequences themselves.  It would be
> possible to put them directly into the sequence list, e.g. with
> a prefix such as "rules:build" which would make dh invoke
> "debian/rules build" rather than the command directly.  This would
> permit the rules targets to be run at any point in a sequence.

Patch attached which includes the rules in the sequences.  This should,
as far as I can tell with my testing, eliminate the performance issues
you mentioned above.  With the rules targets in the sequence list, it
also means you can potentially also use them as sequence points for
--before etc.

Note that there's one issue with the code that confuses me.  This might
be a pre-existing issue with dh that the patch exposes:

% fakeroot dh binary --no-act
   debian/rules install
   debian/rules override_dh_strip
   dh_makeshlibs
   dh_shlibdeps
   dh_installdeb
   dh_gencontrol
   dh_md5sums
   dh_builddeb
   debian/rules binary-arch
   debian/rules binary-indep
% fakeroot dh binary
[build completes]
% fakeroot dh binary --no-act 
   debian/rules binary-arch
   debian/rules binary-indep

Notice that the initial 'debian/rules install' performed
by dh binary isn't repeated on the second invocation.  But AFAICS
there's no .log file that would make dh skip this, so I'm unsure
why it's skipped.  The same applies to the override to an extent
(at least here the override is for a single specific purpose which
we can assume was completed if the .log exists); install is rather
more generic and I would expect it to be called even if it
subsequently does nothing due to being up-to-date).  Not yet found
which bit of the code causes this to be skipped.

Note that the documentation about dependencies is now outdated;
I'll fix that next.


Regards,
Roger

-- 
  .''`.  Roger Leigh
 : :' :  Debian GNU/Linux             http://people.debian.org/~rleigh/
 `. `'   Printing on GNU/Linux?       http://gutenprint.sourceforge.net/
   `-    GPG Public Key: 0x25BFB848   Please GPG sign your mail.
From a709296e8c7f8514e53f3792a6993a6da994ba61 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 |  110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 94 insertions(+), 16 deletions(-)

diff --git a/dh b/dh
index 50e0f14..e7b6721 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, 'rules:build-arch', 'rules:build-indep'];
+$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'} = ['rules:build', @i, 'rules:install-arch', 'rules:install-indep'];
+$sequences{'install-indep'} = ['rules:build-indep', @i];
+$sequences{'install-arch'} = ['rules:build-arch', @i];
 my @ba=qw{
 	dh_strip
 	dh_makeshlibs
@@ -390,9 +411,9 @@ 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} = ['rules:install', @ba, @b, 'rules:binary-arch', 'rules:binary-indep'];
+$sequences{'binary-indep'} = ['rules:install-indep', @b];
+$sequences{'binary-arch'} = ['rules:install-arch', @ba, @b];
 
 # Additional command options
 my %command_opts;
@@ -641,20 +662,71 @@ 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;
+
+	if ($command =~ '^rules:(.*)') {
+		my $target = $1;
+		$command = 'debian/rules';
+		@options = ($target);
+	}
+
+	# 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 ($command ne 'debian/rules' && 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) {
+				local %ENV=%ENV;
+				if ($command eq 'debian/rules') {
+					# The dh options are not passed in the
+					# environment, to ensure that the behaviour
+					# is the same if invoked directly.
+					delete $ENV{DH_INTERNAL_OPTIONS};
+					delete $ENV{DH_INTERNAL_OVERRIDE};
+				}
+				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 +748,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 +760,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 6bb492660bb8e78e3b9ed47b55d10eafcb01da93 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 |   67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 67 insertions(+), 0 deletions(-)

diff --git a/dh b/dh
index e7b6721..a0ff637 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.
@@ -707,6 +753,27 @@ sub run {
 			}
 		}
 	}
+
+	if ($command ne 'debian/rules') {
+	    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

Attachment: signature.asc
Description: Digital signature

Reply via email to