Having had some difficulties to gather coherent info on how to build a proper debian source package, here is a guide wrapping it up. It will be useful to anyone wanting to start a new package and host it on a PPA on Launchpad, especially if the project is built on Qt.

EZWebGallery, my pet-project to be packaged, is built upon two main components:

  • /src contains the sources and binary files required to build the gallery generator. The project is built on Qt4, implying that the makefile will be generated by qmake-qt4 from Thus there is no configure.
  • /web contains the javascript and css files forming the engine of the online gallery. They will be minimized and placed in the /deployment/common/data directory prior to the actual building of the generator.

Note: The data contained in /web and /skins are architecture independent and should ideally be placed in a separated repository. This is not the case here.

Setting up the environment

  • Download the necessary tools via apt-get:
sudo apt-get install build-essential devscripts ubuntu-dev-tools
debhelper dh-make patch gnupg fakeroot lintian cdbs
  • Pbuilder lets you build in a clean, chroot environment, ensuring all dependencies are present. Create a file named .pbuilderrc in your home, then fill it with the distribution you want base your environment on. In this case: raring
nano ~/.pbuilderrc

Then construct the base environment (note: it can take a long time)

sudo pbuilder create -debootstrapopts -variant=buildd

Preparing your project


The building process will need to run make release, make install and make distclean. The task at this point is to write your Qt Project (extension .pro) in order to properly generate these targets.


  • The binary generated by release will have to be placed in /usr/bin/
  • All data required for the binary to run will have to be placed in /usr/share/<package-name>
  • A <package-name>.desktop file will have to be placed in /usr/share/applications for a proper integration with a standard desktop environment.
[Desktop Entry]
GenericName= EZWebGallery
Comment=Generate html5 web photo galleries in a few clicks.
  • Optionally, you can place the man page of the program in /usr/share/man/man1/<package-name>.1.gz, a gzip-9 compressed file.


Be sure to remove any file generated during the compilation.

Configuring the /debian files


As your package does not come from an upstream, you have to provide the <package-name>-<version>.orig.tar.gz file.

Compress your source folder, excluding the debian directory, to <package-name>-<version>.tar.gz and place it in the parent folder. Make a copy and rename it to <package-name>-<version>.orig.tar.gz.

Then, in your package’s folder, which also must be named <package-name>-<version>_:

dh_make -e [email protected]

This will generate the debian directory and fill it with the files you are required to fill along with various examples. You can delete them.

  cd debian
  rm *.ex *.EX


It contains information about all versions of the package since it was created. The build tools only process the top entry, which is used to determine the package version, urgency (which is only of relevance to Debian itself), and bugs in the distribution that this release fixes.

<package-name> (1.0-0ubuntu1) distribution; urgency=low

* Change details.
* More change details.

- Your full name <your full email>  Thu, 28 Oct 2010 11:03:40 +0300

Use dch to add new entries to the changelog or modify existing ones.


Contains information about the source package and all binary packages it builds. This is an important step: any error can make the building process to fail.

Source: <package-name>
Section: utils
Priority: optional
Maintainer Your full name <your full email>
XSBC-Original-Maintainer: Your full name <your full email>
Build-Depends: cdbs, qt4-qmake, libqt4-dev, libmagick++-dev, debhelper (>= 8) # AND ANY OTHER DEPENDENCIES REQUESTED TO BUILD
Standards-Version: 3.9.4 # PUT THE LATEST VERSION
Homepage: project’s homepage

Package: <package-name>
Architecture: any # (or a list of supported launchpad target, ie i386…)
Depends: # ANY DEPENDENCIES REQUIRED TO RUN. Exemple: sed (>=4.2.1), grep (>=2.6.3), mpg321, imagemagick, libnotify-bin, \${shlibs:Depends}, \${misc:Depends}
Description: Short description.
Full description that can
Span on many lines!


It must be an executable makefile, and has to contain the package-specific recipes for compiling the package and building binary package(s) from the source.
It must start with the line #!/usr/bin/make -f, so that it can be invoked by saying its name rather than invoking make explicitly. That is, invoking either of make -f debian/rules args… or ./debian/rules args… must result in identical behavior.

For convenience, it will rely on CDBS, which provide snippets that can be included in a Makefile. These snippets implement actions that originally would usually have been directly included in the rules file. One of them will be in charge to make a proper use of the “qmake build system”.

Thus, the rules file will be the following one:

#!/usr/bin/make -f

include /usr/share/cdbs/1/rules/
include /usr/share/cdbs/1/class/

The other files in the debian directory are not mandatory.

Building the source

Before building, you need to have a GPG key in order to sign your package. Refer to this page for instructions:

Remove from your source code any files that are not really useful for compiling the source (DO remove the Makefile, DO NOT remove the .pro file! You MUST remove any possible .o files, the executable, and the .pro.user file).

debuild -S -sa

The -S flag asks debuild to build a source package using another script, dpkg-buildpackage, together with fakeroot, which grants us fake root privileges while making the package. It will take the .orig.tar.gz file and produce a .diff.gz (the difference between the original tarball from the author and the directory we have created, debian/ and its contents) and a .dsc file that has the description and md5sums for the source package. The .dsc and *_source.changes (used for uploading the source package) files are then signed using your GPG key.

The –sa flag indicates to upload the .orig.tar.gz file along with the changes to the repository.

If you do not have a gpg key set up, you will get an error from debuild. You can either set up a gpg key or use the -us -uc options from debuild to turn off signing. However, you will not be able to have your packages uploaded to an Ubuntu repository or ppa without signing them.

To make sure debuild finds the right gpg key you should set the DEBFULLNAME and DEBEMAIL environment variables (in your ~/.bashrc for instance) to the name and email address you used for your gpg key and in the debian/changelog. Some people have reported that they were unable to get debuild to find their gpg key properly, even after setting the above environment variables. To get around this you can give debuild the -k flag where is your gpg key ID.

With the source package now built, we can now use its .dsc file to build the corresponding binary package in a clean pbuilder environment:

 sudo pbuilder build ../*.dsc

Using pbuilder to build the binary packages is very important. It ensures that the build dependencies are correct, because pbuilder provides only a minimal environment, so all the build-time dependencies are determined by the control file.
We can check the source package for common mistakes using lintian:

 cd .. & lintian -Ivi *.dsc

Once lintian does not report any more error, you can optionally build the .deb binary package if you need one:



  • fakeroot runs a command in an environment wherein it  appears  to  have root  privileges  for  file  manipulation. This is useful for allowing users to create archives (tar, ar, .deb etc.) with files in them with root permissions/ownership.
    Without  fakeroot one would need to have  root privileges to create the constituent files of  the  archives  with the  correct  permissions and ownership, and then pack them up, or one would have to  construct  the  archives  directly,  without  using  the archiver.
  • pbuilder maintains a minimal working systems in chroot, installs only the necessary build dependencies listed in debian/control, and remove them when the build is finished.
    Therefore, using pbuilder, a package maintainer can detect if some build dependencies were not specified in debian/control.
    Also, pbuilder makes it possible to test-build for distributions other than the one the maintainer is running: for example, for the development version, while actually running the stable version.
  • It is not necessary to build a .deb binary package if you intend to upload your sources to your personnal PPA: the build farm will do the job!

Uploading to Launchpad


Now you have a source package that you can upload to your PPA. Before that, you have to check that the GPG key used to sign the package is known to Launchpad. If not the upload may appear to succeed, but will eventually silently fail.

When ready:

dput ppa:your-lp-id/ppa

If the upload succeeded, you will be noticed on the email address provided in the maintainer field of debian/control. Your package will now be queued to be processed by the build farm.

Optional: Writing and using recipes


The “manual“ method described above requires uploading one version of the software for each Ubuntu revision still supported by Canonical. The only differences would be the distribution in debian/changelog and, as they can evolve from one Ubuntu revision to another, the required libraries in debian/control to build and run the package.

As this is fastidious and error prone, the solution is to write a recipe, which is a description of the steps needed to construct a package from a set of Bazaar branches. Thus, you have to publish your source code on a Bazaar branch hosted on launchpad.
A recipe will allow you to build your software for any supported version of Ubuntu, daily or manually.

The recipe used to build EZWebGallery is quite simple:

 # bzr-builder format 0.3 deb-version {debupstream}-1~{revno} lp:ezwebgallery

The only hurdle is that the version of libmagick++ often changes from one version of Ubuntu to the next, so a little bit of flexibility had to be introduced in debian/control in order for the package to be successfully built on all targets.

Depends: libmagick++4 | libmagick++5, \${shlibs:Depends}, \${misc:Depends}