Creating debian packages for Ubuntu

A few weeks ago, I announced that Ubuntu packages are available for the Pothos SDR environment and I intended to make a blog entry to document the effort. So, without further adieu...

Working with Ubuntu PPAs

A PPA (personal package archive) hosts debian installer packages for open source software. The developer (thats me) uploads the source code along with special packaging and building instructions. The PPA server then builds the packages and hosts the resulting debian installers on a remote server. Users can access and install packages from the PPA using the standard mechanisms (apt-get, etc).

Basically, what this means to me is that I don't have to build or even host anything, and users will be able to download and install the entire Pothos SDR environment with a few commands. However, there is a lot of upfront work on my part to setup the PPA and to learn about the debian control files (thats the special packaging and building instructions).

Dependencies and versions

There are a lot of dependencies that need to go into building the Pothos SDR environment. Most dependencies are already packaged in Ubuntu's mainline software repositories, like Qt, CMake, Python, and Boost -- which is really great!

However, other dependencies are not available or severely out-of-date: For example, the available version of Poco is years behind and missing JSON libraries, most Ubuntu versions are missing a Qwt built agains Qt5, and SDR hardware drivers are almost always stale. Its not anyone's fault, its just that drivers tend to gain features over the years, but OS releases version lock with whatever was available at the time of release.

So what's getting packaged?

As it stands at the time of writing, we are going to package:

Which drags in additional dependencies:

And for hardware support:

Managing debian files

The debian directory contains a slew of carefully formated files, that says everything the build server needs to know to build and install packages. Also including: licensing, installation hooks, multi-arch, multiple packages...

The debian files may look complicated, but they are well structured and well documented, with plenty of examples on the web. Honestly, making the debian files was the easiest part. It was building and testing them which took the most effort.

When possible, I checked the entire debian directory into the git repository to host it along with the source:

Uploading source packages

From the source directory, do a complete test build using git buildpackage:

gbp buildpackage --git-ignore-new --git-ignore-branch --git-export=WC \
    --git-upstream-tree=HEAD --git-export-dir=build-area

Build the source package, this will be uploaded to the PPA:

gbp buildpackage --git-ignore-new --git-ignore-branch --git-export=WC \
    --git-upstream-tree=HEAD --git-export-dir=build-area -S

Now upload the actual source package to the PPA with dput:

dput ppa:your_username/your_ppa_name build-area/package_name_version_source.changes

Snapshots and multiple series

The changelog file is dangerously more powerful than its name implies. The first line of the changelog specifies the package name, version, series (OS version), and how we handle development snapshots.

The first line of the changelog takes the following format:

package_name (incrementing_version-extra_info~trusty) trusty; urgency=low
  • The first part of the version string must always increment when the source changes, or the build server will reject updates to the source package. However, the second part can be incremented when the debian files change.
  • Its important that the same package for multiple OS versions can coexist. The recommended convention is to append series_name to the version string.
  • Development snapshots must use a version that is less than the actual release version, but greater than the version of the previous release. Convention recommends previous_version+1SNAPSHOTtimestamp.
  • Read more from

Multi-arch and LIB_SUFFIX

Multi-arch support means that libraries for multiple CPU architectures can coexist on the same file-system. Typically this means 32-bit and 64-bit for x86 (64-bit libraries install to /usr/lib/x86_64-linux-gnu). A multi-arch aware build involves configuring and installing runtime libraries to the correct library prefix.

For years I have been adding LIB_SUFFIX to my CMakeLists.txt files; mostly used to install libraries into the lib64 directory (this is multi-arch for redhat style systems). I thought it was neat that LIB_SUFFIX can just as easily be used to support multi-arch on debian style systems (example configure option to cmake -DLIB_SUFFIX="/x86_64-linux-gnu").

Back-porting is easy

Suppose that Ubuntu now hosts a package on a recent OS release and you want to make it available for previous OS releases. If you already have a PPA setup, then backporting is the easiest thing that you can possibly do. This command will find the most recent official copy of <package_name>, modify it for the specified series (-d trusty in this case), and upload it to the specified PPA. I used this technique to back-port Qwt for QT5 from vidid to utopic and trusty releases.

backportpackage -d trusty -u ppa:your_username/your_ppa_name package_name

Assuming that the source package does not require changes, thats it, you are done! Read more from

Last edited: Sun, Jun 7 2015 - 10:29PM