Skip to content

Latest commit

 

History

History
 
 

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

Tutorial 5: the debhelper pipeline and customizing debhelper steps

Let's say you have an application that must be compiled in manner that debhelper doesn't support out-of-the-box. It could be a C application with a custom build system, or it could be an application written in an new programming language. What do you do? Do you fall back to not using debhelper as much, like you did in tutorial 3? But if you do that then you have to figure out which individual dh_* tools to call, which is a pain.

There is a better way: you can override parts of debhelper while still allowing it to everything else.

Table of contents


The debhelper pipeline system

Think of debhelper as a pipeline system. There are three pipelines: clean, build and binary, which correspond to the three rules makefile targets. Each pipeline calls a number of steps serially, with each step usually being a command invocation.

You can see the steps in the dh output. But for your convenience, here is a listing.

The clean pipeline

The clean pipeline consists of these steps:

Step Goal Behavior
dh_testdir Sanity checks the current working directory Aborts if debian/control does not exist
dh_auto_clean Remove compilation products generated by the app's build system Runs make clean or a similar command if the build system is supported
dh_clean Removes build products generated by a previous debhelper run Removes the package root directory, amongst others

The build pipeline

The build pipeline consists of these steps:

Step Goal Behavior
dh_testdir Sanity checks the current working directory Aborts if debian/control does not exist
dh_auto_configure Configures the source code Runs ./configure, cmake or a similar command if the build system is supported
dh_auto_build Compiles the source code Runs make, setup.py or a similar build command if the build system is supported
dh_auto_test Runs the source code's test suite Runs make test, make check or a similar command if the build system is supported

The binary pipeline

The binary pipeline consists of these steps:

Step Goal Behavior
dh_testroot Checks whether the rules makefile is run as root[1] Aborts if it isn't
dh_prep Performs some preparation cleanups Removes the package root directory, amongst others
dh_auto_install Installs the compiled application into the package root directory Runs make install DESTDIR=... or a similar command if the build system is detected
dh_installdocs Installs documentation such as man pages into the package root directory
dh_installchangelogs Installs the debian/changelog file into the package root directory
dh_perl Do Perl stuff Calculates Perl dependencies and cleans up after MakeMaker
dh_link Creating necessary symlinks in the package root directory
dh_compress Compresses files and fix symlinks in package root directory
dh_fixperms Fix various file permissions in the package root directory
dh_strip Strips binaries Automatically finds binaries in the package root and invokes strip on them
dh_makeshlibs Creates shlibs files using dpkg-gensymbols
dh_shlibdeps Finds out which binaries depend on which shared libraries Invokes dpkg-shlibdeps
dh_installdeb Installs key files in the debian/ directory into <package root>/DEBIAN
dh_gencontrol Creates <package root>/DEBIAN/control Invokes dpkg-gencontrol
dh_md5sums Creates <package root>/DEBIAN/md5sums Automatically scans all files in the package root
dh_builddeb Creates the .deb file(s) Invokes dpkg-deb

Notes

Footnote 1: Debian packages are supposed to be built as root, for reasons that I also do not totally comprehend. But wait, we ran tutorials 1-4 without root, so why didn't it abort? It turns out that dpkg-buildpackage automatically runs the rules makefile through fakeroot. So I think that the dh_testroot step is unnecessary nowadays.

Note: the exact steps differ between different versions of debhelper. For example debhelper 10 (introduced in Debian 9) has more steps. When targeting a specific distribution version, be sure to look at the.

Tip: the debhelper man page has documentation on each of the step described above.

Tip 2: I've highlighted the especially interesting steps: dh_auto_clean, dh_auto_build and dh_auto_install. We are going to override these steps in the rest of this tutorial.

Our application and its custom build system

The application that we use in this tutorial is the same hello world application from tutorial 4, but with a custom build system and with the version number bumped 5.0.0. The commands make, make clean and make install DESTDIR=... are replaced by ./build.sh, ./clean.sh and env DESTDIR=... ./install.sh.

Let's prepare our application and its files:

mkdir tutorial-5
cd tutorial-5
editor hello.c

editor build.sh
editor clean.sh
editor install.sh
chmod +x build.sh
chmod +x clean.sh
chmod +x install.sh

mkdir debian
editor debian/control
echo 9 > debian/compat
editor debian/changelog

hello.c

hello.c must contain:

#include <stdio.h>

int
main() {
	printf("hello 5.0.0\n");
	return 0;
}

build.sh

build.sh must contain:

#!/bin/sh
set -ex
gcc -Wall -g hello.c -o hello

clean.sh

clean.sh must contain:

#!/bin/sh
set -ex
rm -f hello

install.sh

install.sh must contain:

#!/bin/bash
set -ex
mkdir -p "$DESTDIR/usr/bin"
cp hello "$DESTDIR/usr/bin/hello"

debian/control

The control file remains the same compared to tutorial 4:

Source: hello
Section: devel
Priority: optional
Maintainer: John Doe <[email protected]>
Build-Depends: build-essential, debhelper (>= 9)

Package: hello
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: John's hello package
 John's package is written in C
 and prints a greeting.
 .
 It is awesome.

debian/compat

The compatibility level remains the same compared to tutorial 3:

echo 9 > debian/compat

debian/changelog

We add a new changelog entry to the beginning of the file. The beginning of the file looks like this:

hello (5.0.0-1) stretch; urgency=medium

  * Support custom build system.

 -- John Doe <[email protected]>  Tue, 11 Jul 2017 16:34:17 +0000

Overriding debhelper steps

From the above pipeline description, it becomes clear that if we want to support our custom build system, we need to override the dh_auto_clean, dh_auto_build and dh_auto_install steps. We can do that by defining targets in the rules file according to this naming scheme:

override_<STEP NAME>

Inside this target you can then do whatever you want. This target will be invoked by debhelper in place of the corresponding dh_* command invocation.

So here is what our rules file should look like:

#!/usr/bin/make -f

%:
	dh $@

override_dh_auto_clean:
	./clean.sh

override_dh_auto_build:
	./build.sh

override_dh_auto_install:
	env DESTDIR=debian/hello ./install.sh

Verifying that it works

Build the package:

dpkg-buildpackage -b

Then:

$ sudo gdebi -n ../hello_5.0.0-1_<ARCH>.deb
$ hello
5.0.0

Extending debhelper steps

What if you don't want to completely override a step? What if you want to extend a step, e.g. by running custom commands right before or right after that step? For example what if the dh_strip step fails to find your binary (because your binary is gzipped for example), and you want to run your own commands to strip that file.

Inside an override target you can call the original command. Here is how you can override the above hypothetical gzip-strip situation:

override_dh_strip:
	dh_strip
	gunzip debian/hello/usr/lib/helper-binary.gz
	strip --strip-all debian/hello/usr/lib/helper-binary
	gzip debian/hello/usr/lib/helper-binary

Conclusion

Congratulations, this concludes the beginner tutorials! You have learned that debhelper is a pipeline system and how you can override or extend specific pipeline steps.