simple case

Imagine a very simple debian/rules, that should work for most packages w/o modification:

#!/usr/bin/make -f
build:
    dh build

clean:
    dh clean

binary-arch:
    dh binary-arch

binary-indep:
    dh binary-indep

binary: build binary-arch binary-indep

absurdly simple case

AKA debian/rules zen guru level.

#!/usr/bin/make -f
%:
    dh $@

the complex cases

Often you'll want to handle configuring by hand. (And maybe, run automake too.)

build:
    dh build --before configure
    #aclocal
    #autoheader
    #automake --add-missing
    #autoconf
    ./configure --kitchen-sink=yes
    dh build --after configure

Here's how to skip two steps in a row (configure and build):

build:
    dh build --before configure
    ./mondoconfig
    make universe-explode-in-delight GROOVINESS=420
    dh build --after build

Another common case is wanting to run some code manually after a particular debhelper command is run.

binary: build
    dh binary --until dh_fixperms
    # dh_fixperms has run, now override it for one program
    chmod 4755 debian/foo/usr/bin/foo
    # and continue
    dh binary

Suppose you hate dh_strip, and just don't want it to run. (This might be a contrived example; if people frequently don't want to run a few commands in a set, it may be better to have -X exclude them.)

binary: build
    dh binary --before dh_strip
    dh binary --after dh_strip

Maybe you want to run a command out of order. This should be no problem:

binary: build
    dh binary --until dh_fixperms
    dh_install foo usr/bin
    dh binary --after dh_fixperms

A separate install target can be added if you like. And maybe you want to run make install by hand in it. (This is tricky because dh binary needs to avoid running dh_auto_install which was skipped over in the install target.)

install: build
    dh install --before install
    $(MAKE) install PREFIX=debian/tmp
    dh install --after install

binary: install
    dh binary

Once you have an install target, you can do this to run some commands manually after the install target runs, and before the remaining steps are run to build a binary.

binary: install
    dh_strip -X foo
    dh_fixperms -X bar
    dh binary --remaining

If the --remaining was left off, dh binary would only run commands in its list after dh_fixperms. With --remaining, it runs commands that haven't run before, avoiding running dh_strip and dh_fixperms again.

A more elaborate way to do the same thing, without needing a separate install target is this.

binary: build
    dh binary --before dh_strip
    dh_strip -X foo
    dh binary --after dh_strip --before dh_fixperms
    dh_fixperms -X bar
    dh binary --after dh_fixperms

the dh_auto_* commands

dh_auto_* are thin wrappers, with enough intelligence to handle 90% of cases (autofoo, perl/python packages, etc) automatically. These will rarely be run by hand, instead if they don't do what is needed, they can just be skipped.

  • dh_auto_configure: Figures out how to run autofoo, ./configure, Makefile.PL, or whatever.
  • dh_auto_build: runs make
  • dh_auto_test: runs make test or the like (may have a config file specifying if test failures should fail the build).
  • dh_auto_clean: runs "make clean" etc
  • dh_auto_install: runs "make install" or similar

the dh command

dh runs a set of other debhelper commands in order (and prints their names as it does so). The set that it runs is determined by its parameter.

The sets of commands are:

  • build: dh_auto_configure, dh_auto_build, dh_auto_test
  • clean: dh_testdir, dh_testroot(?), dh_auto_clean, and finally dh_clean.
  • install: Everything in the build list, plus dh_installdirs, dh_install, dh_auto_install (and probably dh_install* too)
  • binary: Everything in the install list, and all debhelper commands used in binary targets.
  • binary-arch: Like binary, but runs commands with -s.
  • binary-indep: Like binary, but does not run dh_strip or dh_shlibdeps or dh_makeshlibs, and runs commands with -i.

Possibly dh does smart optimisations to avoid running lesser-used commands if they will do nothing. (Or not.)

Each debhelper command will record when it's successfully run in debian/package.log.debhelper. (Which dh_clean deletes.) So dh can tell which commands have already been run, for which packages, and skip those.

Options passed to dh are passed on to each command it runs, which is useful for common options like -v, -X, and the like. For that matter, you can use it for uncommon options as well, since commands will ignore options that don't apply to them.

dh has a few options of its own:

  • --until cmd: Run commands until and including cmd, then stop.
  • --before cmd: Run commands before cmd, then stop.
  • --after cmd: Run commands that are listed after cmd.
  • --remaining: Run all listed commands that have yet to be run.

cmd can be a full name of a debhelper command, or a substring. It'll first search for a command exactly matching the name, to avoid any ambiguity. For example, "--before dh_installdeb" does not refer to dh_installdebconf. Otoh, "--before build" is much easier to type, and clearer, than "--before dh_auto_build". If there are multiple substring matches, the last in the command list is taken. So "--before install" stops before dh_auto_install, and not before the earlier dh_install.

Each time dh is run, it examines the log, and finds the last logged command that is in its list of commands to run. It then continues with the following command in its list. (Or the one after --after, if that was specified. Or if --remaining was specified, start at the first command in the list that is not in the log.)

So...

If you run debian/rules build twice, and it just has "dh build" in it, the second run will be a no-op. The same as if the build target touched a build-stamp. This is generally considered a feature, so I'll consider it a feature in dh too. (To force a rebuild, run dh_clean to remove the log.)

If you run debian/rules binary, and a build hasn't happened yet, it will run the build steps first. Even if the rules file is a bit lame (or over-golfed), and doesn't have the binary target explicitly depend on the build target. Ditto for the install target.

If a rules file runs a command out of order, it'll need to use --after to get dh back on track.

If you manually run a debhelper command at the command line, running debian/rules binary will skip forward until after that command. Similarly, if debian/rules binary is interrupted (or fails), running it again will resume after the last debhelper command run. This is a bit of a behavior change, and could be considered a bug, but is easy enough to work around by running debian/rules clean binary. (Or by manually deleting the log.)