X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=dh;h=50e0f14dbd90895295b82c98d08627da0aba349b;hb=5e13cc10b6c899fa143b76d4b312b7cdb2e39d08;hp=81160b8437d2ea7e5b4d878ece36ff4260617b81;hpb=bf969c1ca026433477c3578123b28e9829ba4e25;p=debhelper.git diff --git a/dh b/dh index 81160b8..50e0f14 100755 --- a/dh +++ b/dh @@ -11,47 +11,47 @@ use Debian::Debhelper::Dh_Lib; =head1 SYNOPSIS -B sequence [B<--with> I] [B<--until> I] [B<--before> I] [B<--after> I] [B<--remaining>] [S>] +B I [B<--with> I[B<,>I ...]] [B<--list>] [B<--until> I] [B<--before> I] [B<--after> I] [B<--remaining>] [S>] =head1 DESCRIPTION -dh runs a sequence of debhelper commands. The supported sequences -correspond to the targets of a debian/rules file: "build", "clean", -"install", "binary-arch", "binary-indep", and "binary". +B runs a sequence of debhelper commands. The supported Is +correspond to the targets of a F file: B, +B, B, B, B, B, +B, B, B, and B. -Commands in the binary-indep sequence are passed the "-i" option to ensure -they only work on binary independent packages, and commands in the -binary-arch sequences are passed the "-a" option to ensure they only work -on architecture dependent packages. +Commands in the B, B and B +sequences are passed the B<-i> option to ensure they only work on +architecture independent packages, and commands in the B, +B and B sequences are passed the B<-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", -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.) +If F contains a target with a name like BI, +then when it would normally run I, B 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 =over 4 -=item B<--with> I +=item B<--with> I[B<,>I ...] Add the debhelper commands specified by the given addon to appropriate places in the sequence of commands that is run. This option can be repeated more -than once, and is used when there is a third-party package that provides -debhelper commands. See "SEQUENCE ADDONS" below for documentation about what -such packages should do to be supported by --with. +than once, or multiple addons can be listed, separated by commas. +This is used when there is a third-party package that provides +debhelper commands. See the F file for documentation about +the sequence addon interface. + +=item B<--without> I + +The inverse of B<--with>, disables using the given addon. + +=item B<--list>, B<-l> + +List all available addons. =item B<--until> I @@ -69,40 +69,20 @@ Run commands in the sequence that come after I. Run all commands in the sequence that have yet to be run. -=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. +=item B<--no-act> -=head1 COMMAND SPECIFICATION +Prints commands that would run for a given sequence, but does not run them. -I 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. - -=head1 SEQUENCE ADDONS - -When B<--with> I is used, dh loads the perl module -Debian::Debhelper::Sequence::I. Two functions are provided to let -the module add its commands to sequences: - -=over 4 - -=item Debian::Debhelper::Dh_Lib::insert_before(existing_command, new_command) - -Insert I in sequences before I. - -=item Debian::Debhelper::Dh_Lib::insert_after(existing_command, new_command) - -Insert I in sequences after I. - -=item Debian::Debhelper::Dh_Lib::remove_command(existing_command) +=back -Remove I from the list of commands to run. +All other options passed to B 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. -=back +In the above options, I 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 @@ -157,9 +137,9 @@ easy way to do with is by adding an override target for that command. 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 and L +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 %: @@ -182,30 +162,163 @@ after a particular debhelper command is run. dh_fixperms chmod 4755 debian/foo/usr/bin/foo -If your package is a python package, dh will use dh_pysupport by -default. This is how to use dh_pycentral instead. +If your package is a Python package, B will use B by +default. This is how to use B instead. + + #!/usr/bin/make -f + %: + dh $@ --with python-central + +If your package uses autotools and you want to freshen F and +F with newer versions from the B package +at build time, you can use some commands provided in B +that automate it, like this. + + #!/usr/bin/make -f + %: + dh $@ --with autotools_dev + +Here is how to force use of Perl's B 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 B to use quilt's B +sequence addons like this: + + #!/usr/bin/make -f + %: + dh $@ --with quilt + +Here is an example of overriding where the BI<*> commands find +the package's source, for a package where the source is located in a +subdirectory. + + #!/usr/bin/make -f + %: + dh $@ --sourcedirectory=src + +And here is an example of how to tell the BI<*> commands to build +in a subdirectory, which will be removed on B. + + #!/usr/bin/make -f + %: + dh $@ --builddirectory=build + +If your package can be built in parallel, you can support parallel building +as follows. Then B will work. + + #!/usr/bin/make -f + %: + dh $@ --parallel + +Here is a way to prevent B 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 $@ + + # 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 to test what is being built. For example: + + #!/usr/bin/make -f + %: + dh $@ + + override_dh_fixperms: + dh_fixperms + ifneq (,$(filter 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 B. You can also explicitly define the regular +rules file targets when it makes sense to do so. A common reason to do this +is if your package needs different B and B targets. +For example, a package with a long document build process can put it in +B. #!/usr/bin/make -f %: - dh --with python-central $@ + dh $@ + + binary: binary-arch binary-indep ; + binary-arch:: build-arch + binary-indep:: build-indep + build: build-arch build-indep ; + build-indep: + $(MAKE) docs + build-arch: + $(MAKE) bins + +=head1 INTERNALS + +If you're curious about B's internals, here's how it works under the hood. + +Each debhelper command will record when it's successfully run in +F. (Which B deletes.) So B can tell +which commands have already been run, for which packages, and skip running +those commands again. + +Each time B 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. + +B uses the B 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 # 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"; + 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}},$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, }, -}); + # 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{ @@ -214,12 +327,14 @@ $sequences{build} = [qw{ dh_auto_build dh_auto_test }], +$sequences{'build-indep'} = [@{$sequences{build}}]; +$sequences{'build-arch'} = [@{$sequences{build}}]; $sequences{clean} = [qw{ dh_testdir dh_auto_clean dh_clean }]; -$sequences{install} = [@{$sequences{build}}, qw{ +my @i = qw{ dh_testroot dh_prep dh_installdirs @@ -234,7 +349,6 @@ $sequences{install} = [@{$sequences{build}}, qw{ dh_installcatalogs dh_installcron dh_installdebconf - dh_installcatalogs dh_installemacsen dh_installifupdown dh_installinfo @@ -249,34 +363,39 @@ $sequences{install} = [@{$sequences{build}}, qw{ dh_installudev dh_installwm dh_installxfonts + dh_installgsettings + dh_bugfiles + dh_ucf dh_lintian - dh_desktop dh_gconf dh_icons dh_perl - dh_scrollkeeper dh_usrlocal dh_link dh_compress dh_fixperms -}]; +}; +$sequences{'install'} = [@{$sequences{build}}, @i]; +$sequences{'install-indep'} = [@{$sequences{'build-indep'}}, @i]; +$sequences{'install-arch'} = [@{$sequences{'build-arch'}}, @i]; +my @ba=qw{ + dh_strip + dh_makeshlibs + dh_shlibdeps +}; my @b=qw{ dh_installdeb dh_gencontrol dh_md5sums dh_builddeb }; -$sequences{'binary-indep'} = [@{$sequences{install}}, @b]; -$sequences{binary} = [@{$sequences{install}}, qw{ - dh_strip - dh_makeshlibs - dh_shlibdeps -}, @b]; -$sequences{'binary-arch'} = [@{$sequences{binary}}]; +$sequences{binary} = [@{$sequences{install}}, @ba, @b]; +$sequences{'binary-indep'} = [@{$sequences{'install-indep'}}, @b]; +$sequences{'binary-arch'} = [@{$sequences{'install-arch'}}, @ba, @b]; -# --with python-support is enabled by default, at least for now -unshift @{$dh{WITH}}, "python-support"; +# Additional command options +my %command_opts; # sequence addon interface sub _insert { @@ -313,26 +432,89 @@ sub remove_command { } } +sub add_command { + my $command=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}; + } +} + +sub list_addons { + my %addons; + + for my $inc (@INC) { + eval q{use File::Spec}; + my $path = File::Spec->catdir($inc, "Debian/Debhelper/Sequence"); + if (-d $path) { + for my $module_path (glob "$path/*.pm") { + my $name = basename($module_path); + $name =~ s/\.pm$//; + $name =~ s/_/-/g; + $addons{$name} = 1; + } + } + } + + for my $name (sort keys %addons) { + print "$name\n"; + } + + exit 0; +} + foreach my $addon (@{$dh{WITH}}) { my $mod="Debian::Debhelper::Sequence::$addon"; $mod=~s/-/_/g; eval "use $mod"; if ($@) { - error("--with $addon not supported or failed to load module $mod"); + error("unable to load addon $addon: $@"); } } -# 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).")"; @@ -345,14 +527,18 @@ my @packages=@{$dh{DOPACKAGES}}; # Get the options to pass to commands in the sequence. # Filter out options intended only for this program. my @options; -if ($sequence eq 'binary-arch') { +if ($sequence eq 'build-arch' || + $sequence eq 'install-arch' || + $sequence eq 'binary-arch') { push @options, "-a"; # as an optimisation, remove from the list any packages # that are not arch dependent my %arch_packages = map { $_ => 1 } getpackages("arch"); @packages = grep { $arch_packages{$_} } @packages; } -elsif ($sequence eq 'binary-indep') { +elsif ($sequence eq 'build-indep' || + $sequence eq 'install-indep' || + $sequence eq 'binary-indep') { push @options, "-i"; # ditto optimisation for arch indep my %indep_packages = map { $_ => 1 } getpackages("indep"); @@ -360,22 +546,31 @@ elsif ($sequence eq 'binary-indep') { } while (@ARGV_orig) { my $opt=shift @ARGV_orig; - next if $opt eq $sequence; - if ($opt =~ /^--?(after|until|before|with)$/) { + if ($opt =~ /^--?(after|until|before|with|without)$/) { shift @ARGV_orig; next; } - elsif ($opt =~ /^--?(no-act|remaining|(after|until|before|with)=)/) { + 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. my %logged; my %startpoint; foreach my $package (@packages) { - my @log=loadlog($package); + my @log=load_log($package, \%logged); if ($dh{AFTER}) { # Run commands in the sequence that come after the # specified command. @@ -385,7 +580,7 @@ foreach my $package (@packages) { # no commands remain to run after it, communicating to # future dh instances that the specified command should not # be run again. - writelog($sequence[$startpoint{$package}-1], $package); + write_log($sequence[$startpoint{$package}-1], $package); } elsif ($dh{REMAINING}) { # Start at the beginning so all remaining commands will get @@ -442,99 +637,123 @@ sub run { 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; - 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(" ", @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); + $ENV{DH_INTERNAL_OVERRIDE}=$command; + $command="debian/rules"; + @options="override_".$override_command; + } + else { + $command = undef; + } } else { - # If some packages are excluded, add flags - # to prevent them from being acted on. - push @options, map { "-N$_" } @exclude; + # 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) { + # 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); + } + delete $ENV{DH_INTERNAL_OPTIONS}; - # Need to handle logging for overriden commands here, - # because the actual debhelper command may not have - # been run by the rules file target. - my %packages=map { $_ => 1 } @packages; - map { delete $packages{$_} } @exclude; - writelog($override_command, keys %packages); + delete $ENV{DH_INTERNAL_OVERRIDE}; } } } -sub loadlog { - my $package=shift; - my $ext=pkgext($package); - - my @log; - open(LOG, "<", "debian/${ext}debhelper.log") || return; - while () { - chomp; - push @log, $_; - $logged{$package}{$_}=1; - } - close LOG; - return @log; -} - -sub writelog { - Debian::Debhelper::Dh_Lib::write_log(@_); -} - { my %targets; my $rules_parsed; 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; - open(MAKE, "make -Rrnpsf debian/rules debhelper-fail-me 2>/dev/null |"); + my $current_target; + open(MAKE, "LC_ALL=C make -Rrnpsf debian/rules debhelper-fail-me 2>/dev/null |"); while () { if ($processing_targets) { if (/^# Not a target:/) { $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; } } @@ -542,7 +761,7 @@ sub rules_explicit_target { $rules_parsed = 1; } - return exists $targets{$target}; + return $targets{$target}; } }