Thursday, June 23, 2011

Bootstrapping Debian packages

I read something about dh_make again a while ago, which made me wonder, besides dh_make, how do people generally bootstrap new Debian packages. I don't think I've ever actually used dh_make for anything but experimenting. For the longest time, copying over the packaging files from some similar package worked pretty well.

Recently, however, I have applied a completely new strategy: I start with nothing, call debuild, fix the error, retry, until it works. This might sound pretty bizarre, but it works pretty well and enhances your understanding of how the packaging tools work.

Here is about how it works:

Start with nothing, call debuild, it complains:
cannot find readable debian/changelog anywhere!
Call dch --create, which says:
Cannot find debian directory!
OK, mkdir debian, call dch --create again, fill in the template. Call debuild again, now it says:
but there's no debian/rules there!
Create a debian/rules, that's easy to do by heart nowadays, at least as a start:
#!/usr/bin/make -f

        dh $@
Call debuild again, now dpkg-buildpackage actually starts, but stops with:
dpkg-source: error: cannot read mypackage/debian/control: No such file or directory
At this point I'm too lazy to figure out what is necessary to put into debian/control, so let's just keep it simple and touch debian/control. At this point dpkg-source gets into a bit of trouble:
Use of uninitialized value $sourcepackage in sprintf at /usr/bin/dpkg-source line 290.
So let's put that in and also follow the subsequent advice to add debian/source/format and the Maintainer and Standards-Version fields. So far we have:
Source: mypackage
Maintainer: Peter Eisentraut <>
Standards-Version: 3.9.2
The next hint of a message is:
dh: No packages to build.
This means we need a binary package stanza, so I'll just add
Package: mypackage
Architecture: any
Now debhelper complains:
dh: Compatibility levels before 5 are deprecated.
Not sure why it didn't complain about that earlier. Let's stick 8 in there.

At this point I had to do actual work and mess around with debian/rules a bit to get the package to actually build, but a few minutes later I had a functioning provisional package.

The next step is to clean up the warnings from the various dpkg-* workers:
dpkg-gencontrol: warning: missing information for output field Description
dpkg-gencontrol: warning: package mypackage: unused substitution variable ${shlibs:Depends}
dpkg-deb: warning: parsing file 'debian/mypackage/DEBIAN/control' near line 6 package 'mypackage': missing description
dpkg-genchanges: warning: missing Section for binary package mypackage; using '-'
dpkg-genchanges: warning: missing Priority for binary package mypackage; using '-'
dpkg-genchanges: warning: missing Section for source files
dpkg-genchanges: warning: missing Priority for source files
So we add Description, Depends, Section, and Priority.

And finally we have a list of complaints from Lintian to address:
W: mypackage source: debhelper-but-no-misc-depends mypackage
E: mypackage source: package-uses-debhelper-but-lacks-build-depends
W: mypackage source: package-needs-versioned-debhelper-build-depends 8
W: mypackage source: debhelper-overrides-need-versioned-build-depends (>= 7.0.50~)
E: mypackage source: temporary-debhelper-file debhelper.log
E: mypackage: no-copyright-file
The only things I added manually after that were Vcs-*, Homepage, and Enhances.

Now the only things left to do are running the thing through cowbuilder a few times and putting in all the necessary build dependencies, and writing a nice changelog entry.

Note, this method does not replace putting in some thought. But it's an interesting way to get a relatively clean package.


  1. wow, this is one of those things that make you think why you never thought of that yourself - it makes you really understand better how everything works together. thank you for the idea :D

  2. Awesome. That's a great way to simplify (even if just for experimentation), and it's nice to see the error messages are all quite helpful!

  3. I just fill in everything from memory and then build to see what I forgot and take it from there.

  4. I actually used dh-make, then copied the package that worked all the time I needed to make another (except for one dh-make-perl which worked nicely, and a dh-make-pecl that failed but that was due to upstream). Copying works very well for me, now that I have understood packaging and processes and so on. (I’ve even got a few “3.0 (quilt)” packages now, but every once in a while someone raises an eyebrow on my packages. Well, they can be easily backported to etch or, with a bit more effort, even sarge/dapper – yes, there are use cases – and often build unmodified from lenny onwards. They are fully sid conformant, though. And having backported the latest-of-the-crop packages, I like my advances.)

    But nowadays, I see debhelper pulling in more and more and more and more and even more junk, especially since I’m the one doing builds for m68k right now. I’ve seen packages that go without debhelper, such as grml-archive-keyring, or without any build dependencies at all (debianutils). One of my own has begun using a shell script for compile logic, because it’s too dynamic to try and express it in GNU make, and the build/install targets just call that. Then there’s the situation with build-arch/binary-arch… I’m honestly considering going AWAY FROM DEBHELPER (5 is the compat level I’ll be using for the foreseeable future anyway) and TOWARDS NO HELPER AT ALL. (dh-style doesn’t suit me and is slower than dh_command-style, and cdbs is an abomination… and manoj’s build system takes up even more time on the m68k build“d” than the others.) Comments?

  5. I like this. I tend to try and do things manually, but I haven't applied such a "test-driven" approach, which does help to highlight what bits require what, etc.

    @mirabilos: I rebuilt the doom-wad-shareware package without any helper (no dh, etc.). It was an interesting experiment, and d-w-s is one of the simplest possible packages (install one binary to one location), but even then I managed to miss something (the md5sum file). I think for the vast majority of cases, a helper like dh is essential.

  6. Jon: right, but lintian would warn about the md5sums file, right?

    I usually use 「lintian -vIiE --pedantic *.changes」 after building (drop --pedantic and -E if lenny or etch) to check if everything’s alright, ignore some of the pedantic warnings (like no upstream changelog when none exists) and put in overrides for everything else.

    But I will look at that package for a guide. Another idea I recently got was to see _what_ debhelper does (using its verbose mode) as a guide for helper-less packaging.

    On the other hand… debhelper takes much work away from a packager if they want to target multiple distros (and I regularily build for Debian etch/lenny/sid – no squeeze yet – and Kubuntu hardy) since they do differ.

    I don’t think I will drop debhelper entirely, but in some cases, it may help. We’ll see.