секвенсор команд debhelper (debhelper command sequencer)
OVERRIDE AND HOOK TARGETS
A debian/rules file using dh
can override the command that is run
at any step in a sequence, by defining an override target. It is
also possible to inject a command before or after any step
without affecting the step itself.
Injecting commands before or after a step
Note: This feature requires debhelper 12.8 or later plus the
package must use compatibility mode 10 or later.
To inject commands before dh_command, add a target named
execute_before_
dh_command to the rules files. Similarly, if you
want to inject commands after dh_command, add the target
execute_after_
dh_command. Both targets can be used for the same
dh_command and also even if the command is overridden (as
described in "Overriding a command" below).
When these targets are defined, dh
will call the targets
respectively before or after it would invoke dh_command (or its
override target).
Overriding a command
To override dh_command, add a target named override_
dh_command to
the rules file. When it would normally run 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.
Architecture dependent/independent override and hook targets
The override and hook targets can also be defined to run only
when building architecture dependent or architecture independent
packages. Use targets with names like override_
dh_command-arch
and execute_after
dh_command-indep
.
This feature is available since debhelper 8.9.7 (for override
targets) and 12.8 (for hook targets).
Completely empty targets
As a special optimization, dh
will skip a target if it is
completely empty. This is mostly useful for override targets,
where the command will simply be skipped without the overhead of
invoking a dummy target.
Note that the target has to be completely empty for this to work:
# Skip dh_bar - the good and optimized way
# Some rationale for skipping dh_bar goes here
override_dh_bar:
# Skip dh_foo - the slow way
override_dh_foo:
# Some rationale for skipping dh_foo goes here
# (these comments causes a dummy target to be run)
Verifying targets are picked up by dh
If you want to confirm that dh
has seen an override or a hook
target, you can use the following command as an example:
$ dh binary --no-act | grep dh_install | head -n5
dh_installdirs
dh_install
debian/rules execute_after_dh_install
dh_installdocs
dh_installchangelogs
The debian/rules execute_after_dh_install
in the output, which
signals that dh
registered a execute_after_dh_install
target and
would run it directly after dh_install(1).
Note that "Completely empty targets" will be omitted in the
listing above. This makes it a bit harder to spot as you are
looking for the omission of a command name. But otherwise, the
principle remains the same.
Caveats with hook targets and makefile conditionals
If you choose to wrap a hook target in makefile conditionals,
please be aware that dh
computes all the hook targets a head of
time and caches the result for that run. Furthermore, the
conditionals will be invoked again when dh
calls the hook target
later and will assume the answer did not change.
The parsing and caching often happens before dh
knows whether it
will build arch:any (-a) or/and arch:all (-i) packages, which can
produce confusing results - especially when dh_listpackages(1) is
part of the conditional.
Most of the problems can be avoided by making the hook target
unconditional and then have the "body" be partially or completely
conditional. As an example:
# SIMPLE: It is well-defined what happens. The hook target
# is always considered. The "maybe run this" bit is
# conditional but dh_foo is definitely skipped.
#
# Note: The conditional is evaluated "twice" where its
# influences what happens. Once when dh check which hook
# targets exist and once when the override_dh_foo hook target
# is run. If *either* times return false, "maybe run this"
# is skipped.
override_dh_foo:
ifneq (...)
maybe run this
endif
# SIMPLE: This is also well-defined. The hook target is always
# run and dh_bar is skipped. The "maybe run this" bit is
# conditional as one might expect.
#
# Note: The conditional is still evaluated multiple times (in
# different process each time). However, only the evaluation
# that happens when the hook target is run influences what
# happens.
override_dh_bar:
: # Dummy command to force the target to always be run
ifneq (...)
maybe run this
endif
# COMPLICATED: This case can be non-trivial and have sharp edges.
# Use at your own peril if dh_listpackages in the conditional.
#
# Here, either dh_baz is run normally OR "maybe run this" is run
# instead.
#
# And it gets even more complicated to reason about if dh needs to
# recurse into debian/rules because you have an "explicit"
# standard target (e.g. a "build-arch:" target separate from "%:").
ifneq (...)
override_dh_baz:
maybe run this
endif
These recipes are also relevant for conditional dependency
targets, which are often seen in a variant of the following
example:
COND_TASKS =
ifneq (...)
COND_TASKS += maybe-run-this
endif
...
maybe-run-this:
...
# SIMPLE: It is well-defined what happens. Either the
# $(COND_TASKS) are skipped or run.
#
# Note: The conditional is evaluated "twice" where its
# influences what happens. Once when dh check which hook
# targets exist and once when the override_dh_foo hook target
# is run. If *either* times return false, $(COND_TASKS)
# is skipped.
override_dh_foo: $(COND_TASKS)
# SIMPLE: This is also well-defined. The hook target is always
# run and dh_bar is skipped. The $(COND_TASKS) bit is
# conditional as one might expect.
#
# Note: The conditional is still evaluated multiple times (in
# different process each time). However, only the evaluation
# that happens when the hook target is run influences what
# happens.
override_dh_bar: $(COND_TASKS)
: # Dummy command to force the target to always be run
# COMPLICATED: This case can be non-trivial and have sharp edges.
# Use at your own peril if dh_listpackages in the conditional.
#
ifneq (...)
override_dh_baz: $(COND_TASKS)
endif
When in doubt, pick the relevant SIMPLE
case in the examples
above that match your need.