3 min read, 500 words

Packaging Nightmares

As a follow-up to the previous Debian packaging article, here is a second go at documenting for future me a couple more obscure concepts around building custom packages.

Virtual Packages

So today I learned how to create virtual packages. For those unaware, Debian has a way for packages to state that they satisfy more than just a single package name. In the canonical example, there are dozens of packages that can fill the generic dependency of www-browser, such as firefox, chromium-browser, or konquoror. When a package doesn’t particularly care which specific browser is used, just that there is one, they can specify a dependency on www-browser and allow the user to pick the browser of their choice. The actual browser package has a section in the config file that lists the virtual packages that it provides, in this case firefox provides: www-browser iceweasel gnome-www-browser. You can easily view what virtual packages a package provides using apt-cache showpkg:

$ apt-cache showpkg firefox
Package: firefox
Versions:
52.0.2+build1-0ubuntu0.12.04.1 
[...]
Provides:
52.0.2+build1-0ubuntu0.12.04.1 - www-browser iceweasel gnome-www-browser

You can get a list of packages that provide a virtual package, shown in the Reverse Provides section, in the same way:

$ apt-cache showpkg www-browser
Package: www-browser
[...]
Reverse Provides:
w3m 0.5.3-5ubuntu1.2
chromium-browser 18.0.1025.151~r130497-0ubuntu1
konqueror 4:4.8.2-0ubuntu2
firefox 11.0+build1-0ubuntu4
[...]

Virtual packages are quite a powerful concept and allow for a significant amount of flexibility in building packages, a single package can supersede a handful of individual packages, without breaking backwards compatibility with older dependant projects.

Epoch Versions

I also had the pleasure of having to actually understand what the hell the strings that pass for Debian package version numbers mean. Debian deb-version goes into the full details, but a quick overview wouldn’t hurt. The part of the version string that burned me this time was the epoch segment.

Take the version string from the Ubuntu 14.04 package for python-numpy: 1:1.6.1-6ubuntu1. This breaks down into epoch; upstream-version; debian-revision or 1; 1.6.1; 6ubuntu1. Epoch is this fun modifier that allows the maintainer to basically reset the version numbers, by ignoring anything of a lower epoch. Epoch defaults to 0 when not provided, so version numbers are evaluated as expected.

If there is a major mishap in releases and the version numbers are beyond recovery, the maintainer can increment the epoch version and essentially start over– 1:1.0 evaluates as newer than 3.1.4 (implied 0 epoch so 0:3.1.4). At a glance, without domain specific knowledge, this can lead to quite interesting results when trying to figure out what version should be installed.

All in all, I feel like I have a better grasp of packaging as a whole from this experience, not just with Debian, but also the details that plague anyone attempting to maintain a consistent experience for downstream consumers.


Once again fucked by the intricacies of Debian packaging Logging and capturing messages from libraries and nested modules


comments powered by Disqus