16.2. Debian packaging#

This chapter describes how software for Univention Corporate Server is packaged in the Debian format. It allows proper dependency handling and guarantees proper tracking of file ownership. Customers can package their own internal software or use the package mechanism to distribute configuration files consistently to different machines.

Software is packaged as a source package, from which one or more binary packages can be created. This is useful to create different packages from the same source package. For example the Samba source package creates multiple binary packages:

  • one containing the file server

  • one containing the client commands to access the server

  • and several other packages containing documentation, libraries, and common files shared between those packages

The directory should be named package_name-version.

16.2.1. Prerequisites and preparation#

Some packages are required for creating and building packages.

build-essential

This meta package depends on several other packages like compilers and tools to extract and build source packages. Packages must not declare an explicit dependency on this and its dependent packages.

devscripts

This package contains additional scripts to modify source package files like for example debian/changelog.

dh-make

This program helps to create an initial debian/ directory, which can be used as a starting point for packaging new software.

These packages must be installed on the development system. If not, missing packages can be installed on the command line using univention-install or through UMC, which is described in the Univention Corporate Server - Manual for users and administrators [2].

16.2.2. dh_make#

dh_make is a tool, which helps creating the initial debian/ directory. It is interactive by default and asks several questions about the package to be created.

Type of package: single binary, indep binary, multiple binary, library, kernel module, kernel patch?
[s/i/m/l/k/n]
s, single binary

A single architecture specific binary package is created from the source package. This is for software which needs to be compiled individually for different CPU architectures like i386 and amd64.

i, indep binary

A single architecture-independent binary package is created from the source package. This is for software which runs unmodified on all CPU architectures.

m, multiple binary

Multiple binary packages are created from the source package, which can be both architecture independent and dependent.

l, library

Two or more binary packages are created for a compiled library package. The runtime package consists of the shared object file, which is required for running programs using that library. The development package contains the header files and other files, which are only needed when compiling and linking programs on a development system.

k, kernel module

A single kernel-dependent binary package is created from the source package. Kernel modules need to be compiled for each kernel flavor. dkms should probably be used instead. This type of packages is not described in this manual.

n, kernel patch

A single kernel-independent package is created from the source package, which contains a patch to be applied against an unpacked Linux kernel source tree. dkms should probably be used instead. This type of packages is not described in this manual.

In Debian, a package normally consists of an upstream software archive, which is provided by a third party like the Samba team. This collection is extended by a Debian specific second TAR archive or a patch file, which adds the debian/ directory and might also modify upstream files for better integration into a Debian system.

When a source package is built, dpkg-source.1 separates the files belonging to the packaging process from files belonging to the upstream package. For this to work, dpkg-source needs the original source either provided as a TAR archive or a separate directory containing the unpacked source. If neither of these is found and --native is not given, dh_make prints the following warning:

Could not find my-package_1.0.orig.tar.gz
Either specify an alternate file to use with -f,
or add --createorig to create one.

The warning from dh_make states that no pristine upstream archive was found, which prohibits the creation of the Debian specific patch, since the Debian packaging tools have no way to separate upstream files from files specific to Debian packaging. The option --createorig can be passed to dh_make to create a .orig.tar.gz archive before creating the debian/ directory, if such separation is required.

16.2.3. Debian control files#

The control files in the debian/ directory control the package creation process. The following sections provide a short description of these files. A more detailed description is available in the The Debian GNU/Linux FAQ - Basics of the Debian package management system [4].

Several files will have the .ex suffix, which mark them as examples. To activate these files, they must be renamed by stripping this suffix. Otherwise, the files should be deleted to not clutter up the directory by unused files. In case a file was deleted and needs to be restored, the original templates can be found in the /usr/share/debhelper/dh_make/debian/ directory.

The debian/ directory contains some global configuration files, which can be put into two categories: The files changelog, control, copyright, rules are required and control the build process of all binary packages. Most other files are optional and only affect a single binary package. Their filename is prefixed with the name of the binary package. If only a single binary package is build from the source package, this prefix can be skipped, but it is good practice to always use the prefix.

The following files are required:

changelog

Changes related to packaging, not the upstream package. See debian/changelog below for more information.

compat

The Debhelper tools support different compatibility levels. For UCS-3.x the file must contain a single line with the value 7. See debhelper.7 for more details.

control

Contains control information about the source and all its binary packages. This mostly includes package name and dependency information. See debian/control below for more information.

copyright

This file contains the copyright and license information for all files contained in the package. See debian/copyright below for more information.

rules

This is a Makefile style file, which controls the package build process. See debian/rules below for more information.

source/format

This file configures how dpkg-source.1 separates the files belonging to the packaging process from files belonging to the upstream package. Historically, the Debian source format 1.0 shipped packages as a TAR file containing the upstream source plus one patch file, which contained all files of the debian/ sub-directory in addition to all changes to upstream files.

The new format 3.0 (quilt) replaces the patch file with a second TAR archive containing the debian/ directory. Changes to upstream files are no longer applied as one giant patch, but split into logical changes and applied using a built-in quilt.1.

For simple packages, where there is no distinction between upstream and the packaging entity, the 3.0 (native) format can be used instead, were all files including the debian/ directory are contained in a single TAR file.

The following files are optional and should be deleted if unused, which helps other developers to concentrate on only the files relevant to the packaging process:

README.Debian

Notes regarding package specific changes and differences to default options, for example compiler options. Will be installed into /usr/share/doc/package_name/README.Debian.

package.cron.d

Cron tab entries to be installed. See dh_installcron.1 for more details.

package.dirs

List of extra directories to be created. See dh_installdirs.1 for more details. May other dh_ tools automatically create directories themselves, so in most cases this file is unneeded.

package.install

List of files and directories to be copied into the package. This is normally used to partition all files to be installed into separate packages, but can also be used to install arbitrary files into packages. See dh_install.1 for more details.

package.docs

List of documentation files to be installed in /usr/share/doc/package/. See dh_installdocs.1 for more details.

package.emacsen-install; package.emacsen-remove; package.emacsen-startup

Emacs specific files to be installed below /usr/share/emacs-common/package/. See dh_installemacsen.1 for more details.

package.doc-base*

Control files to install and register extended HTML and PDF documentation. See dh_installdocs.1 for more details.

package.init.d; package.default

Start-/stop script to manage a system daemon or service. See dh_installinit.1 for more details.

package.manpage.1; package.manpage.sgml

Manual page for programs, library functions or file formats, either directly in troff or SGML. See dh_installman.1 for more details.

package.menu

Control file to register programs with the Debian menu system. See dh_installmenu.1 for more details.

watch

Control file to specify the download location of this upstream package. This can be used to check for new software versions. See uscan.1 for more details.

package.preinst; package.postinst; package.prerm; package.postrm

Scripts to be executed before and after package installation and removal. See debian/preinst, debian/prerm, debian/postinst, debian/postrm below for more information.

package.maintscript

Control file to simplify the handling of configuration files. See dpkg-maintscript-helper.1 and dh_installdeb.1 for more information.

Other debhelper programs use additional files, which are described in the respective manual pages.

16.2.3.1. debian/control#

The control file contains information about the packages and their dependencies, which are needed by dpkg. The initial control file created by dh_make looks like this:

Source: testdeb
Section: unknown
Priority: optional
Maintainer: John Doe <user@example.com>
Build-Depends: debhelper (>= 5.0.0)
Standards-Version: 3.7.2

Package: testdeb
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: <insert up to 60 chars description>
<insert long description, indented with spaces>

The first block beginning with Source describes the source package:

Source

The name of the source package. Must be consistent with the directory name of the package and the information in the changelog file.

Section

A category name, which is used to group packages. There are many predefined categories like libs, editors, mail, but any other string can be used to define a custom group.

Priority

Defines the priority of the package. This information is only used by some tools to create installation DVD. More important packages are put on earlier CD, while less important packages are put on later CD.

essential

Packages are installed by default and dpkg prevents the user from easily removing it.

required

Packages which are necessary for the proper functioning of the system. The package is part of the base installation.

important

Important programs, including those which one would expect to find on any Unix-like system. The package is part of the base installation.

standard

These packages provide a reasonably small but not too limited character-mode system.

optional

Package is not installed by default. This level is recommended for most packages.

extra

This contains all packages that conflict with some other packages.

Maintainer

The name and email address of a person or group responsible for the packaging.

Build-Depends; Build-Depends-Indep

A list of packages which are required for building the package.

Standards-version

Specifies the Debian Packaging Standards version, which this package is conforming to. This is not used by UCS, but required by Debian.

All further blocks beginning with Package describes a binary package. For each binary package one block is required.

Package

The name of the binary package. The name must only consist of lower case letters, digits and dashes. If only a single binary package is built from a source package, the name is usually the same as the source package name.

Architecture

Basically there are two types of packages:

  • Architecture dependent packages must be build for each architecture like i386 and amd64, since binaries created on one architecture do not run on other architectures. A list of architectures can be explicitly given, or any can be used, which is then automatically replaced by the architecture of the system where the package is built.

  • Architecture independent packages only need to be built once, but can be installed on all architectures. Examples are documentation, scripts and graphics files. They are declared using all in the architecture field.

Description

The first line should contain a short description of up to 60 characters, which should describe the purpose of the package sufficiently. A longer description can be given after that, where each line is indented by a single space. An empty line can be inserted by putting a single dot after the leading space.

Most packages are not self-contained but need other packages for proper function. Debian supports different kinds of dependencies.

Depends

A essential dependency on some other packages, which must be already installed and configured before this package is configured.

Recommends

A strong dependency on some other packages, which should normally be co-installed with this package, but can be removed. This is useful for additional software like plug-ins, which extends the functionality of this package, but is not strictly required.

Suggests

A soft dependency on some other packages, which are not installed by default. This is useful for additional software like large add-on packages and documentation, which extends the functionality of this package, but is not strictly required.

Pre-Depends

A strong dependency on some other package, which must be fully operational even before this package is unpacked. This kind of dependency should be used very sparsely. It’s mostly only required for software called from the .preinst script.

Conflicts

A negative dependency, which prevents the package to be installed while the other package is already installed. This should be used for packages, which contain the same files or use the same resources, for example TCP port numbers.

Provides

This package declares, that it provides the functionality of some other package and can be considered as a replacement for that package.

Replaces

A declaration, that this package overwrites the files contained in some other package. This deactivates the check normally done by dpkg to prevent packages from overwriting files belonging to some other package.

Breaks

A negative dependency, which requests the other package to be upgraded before this package can be installed. This is a lesser form of Conflicts. Breaks is almost always used with a version specification in the form Breaks: package (<< version): This forces package to be upgraded to a version greater than version before this package is installed.

In addition to literal package names, debhelper supports a substitution mechanism: Several helper scripts are capable of automatically detecting dependencies, which are stored in variables.

${shlibs:Depends}

dh_shlibdeps automatically determines the shared library used by the programs and libraries of the package and stores the package names providing them in this variable.

${python3:Depends}

dh_python detects similar dependencies for Python modules.

${misc:Depends}

Several Debhelper commands automatically add additional dependencies, which are stored in this variable.

In addition to specifying a single package as a dependency, multiple packages can be separated by using the pipe symbol (|). At least one of those packages must be installed to satisfy the dependency. If none of them is installed, the first package is chosen as the default.

A package name can be followed by a version constraint enclosed in parenthesis. The following operators are valid:

<<

is less than

<=

is less than or equal to

=

is equal to

>=

is greater than or equal to

>>

is greater than

For example:

Depends: libexample1 (>= ${binary:Version}),
 exim4 | mail-transport-agent,
 ${shlibs:Depends}, ${misc:Depends}
Conflicts: libgg0, libggi1
Recommends: libncurses5 (>> 5.3)
Suggests: libgii0-target-x (= 1:0.8.5-2)
Replaces: vim-python (<< 6.0), vim-tcl (<= 6.0)
Provides: www-browser, news-reader

16.2.3.3. debian/changelog#

The changelog file documents the changes applied to this Debian package. The initial file created by dh_make only contains a single entry and looks like this:

testdeb (0.1-1) unstable; urgency=low

  * Initial Release.

 -- John Doe <user@example.com>  Mon, 21 Mar 2013 13:46:39 +0100

For each new package release a new entry must be prepended before all previous entries. The version number needs to be incremented and a descriptive text should be added to describe the change.

The command debchange from the devscripts package can be used for editing the changelog file. For example the following command adds a new version:

dch -i

After that the changelog file should look like this:

testdeb (0.1-2) unstable; urgency=low

  * Add more details.

 -- John Doe <user@example.com>  Mon, 21 Mar 2013 17:55:47 +0100

testdeb (0.1-1) unstable; urgency=low

  * Initial Release.

 -- John Doe <user@example.com>  Mon, 21 Mar 2013 13:46:39 +0100

The date and timestamp must follow the format described in RFC 2822. debchange automatically inserts and updates the current date. Alternatively date -R can be used on the command line to create the correct format.

For UCS it is best practice to mention the bug ID of the UCS bug tracker (see Bug reporting) to reference additional details of the bug fixed. Other parties are encouraged to devise similar comments, for example URLs to other bug tracking systems.

16.2.3.4. debian/rules#

The file rules describes the commands needed to build the package. It must use the Make syntax The GNU Make manual [5]. It consists of several rules, which have the following structure:

target: dependencies
    command
    ...

Each rule starts with the target name, which can be a filename or symbolic name. Debian requires the following targets:

clean

This rule must remove all temporary files created during package build and must return the state of all files back to the same state as when the package is freshly extracted.

build; build-arch; build-indep

These rules should configure the package and build either all, all architecture dependent or all architecture independent files.

These rules are called without root permissions.

binary; binary-arch; binary-indep

These rules should install the package into a temporary staging area. By default this is the directory debian/tmp/ below the source package root directory. From there files are distributed to individual packages, which are created as the result of these rules.

These rules are called with root permissions.

Each command line must be indented with one tabulator character. Each command is executed in a separate shell, but long command lines can be split over consecutive lines by terminating each line with a backslash (\).

Each rule describes a dependency between the target and its dependencies. make considers a target to be out-of-date, when a file with that name target does not exists or when the file is older than one of the files it depends on. In that case make invokes the given commands to re-create the target.

In addition to filenames also any other word can be used for target names and in dependencies. This is most often used to define phony targets, which can be given on the command line invocation to trigger some tasks. The above mentioned clean, build and binary targets are examples for that kind of targets.

dh_make only creates a template for the rules file. The initial content looks like this:

#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.

# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1

%:
    dh $@

Since UCS-3.0 the debian/rules file is greatly simplified by using the dh sequencer. It is a wrapper around all the different debhelper tools, which are automatically called in the right order.

Tip

To exactly see which commands are executed when dpkg-buildpackage builds a package, invoke dh target --no-act by hand, for example dh binary --no-act lists all commands to configure, build, install and create the package.

In most cases it’s sufficient to just provide additional configuration files for the individual debhelper commands as described in Debian control files. If this is not sufficient, any debhelper command can be individually overridden by adding an override target to the rules file.

For example the following snippet disables the automatic detection of the build system used to build the package and passes additional options:

override_dh_auto_configure:
    ./setup --prefix=/usr --with-option-foo

Without that explicit override dh_auto_configure would be called, which normally automatically detects several build systems like cmake, setup.py, autoconf and others. For these dh also passes the right options to configure the default prefix /usr and use the right compiler flags.

After configuration the package is built and installed to the temporary staging area in debian/tmp/. From there dh_install partitions individual files and directories to binary packages. This is controlled through the debian/package.install files.

This file can also be used for simple packages, where no build system is used. If a path given in the debian/package.install file is not found below debian/tmp/, the path is interpreted as relative to the source package root directory. This mechanism is sufficient to install simple files, but fails when files must be renamed or file permissions must be modified.

16.2.3.5. debian/preinst, debian/prerm, debian/postinst, debian/postrm#

In addition to distributing only files, packages can also be used to run arbitrary commands on installation, upgrades or removal. This is handled by the four Maintainer scripts, which are called before and after files are unpacked or removed:

debian/package.preinst

called before files are unpacked.

debian/package.postinst

called after files are unpacked. Mostly used to (re-)start services after package installation or upgrades.

debian/package.prerm

called before files are removed. Mostly used to stop services before a package is removed or upgraded.

debian/package.postrm

called after files have been removed.

The scripts themselves must be shell scripts, which should contain a #DEBHELPER# marker, where the shell script fragments created by the dh_ programs are inserted. Each script is invoked with several parameters, from which the script can determine, if the package is freshly installed, upgraded from a previous version, or removed. The exact arguments are described in the template files generated by dh_make.

The maintainer scripts can be called multiple times, especially when errors occur. Because of that the scripts should be idempotent, that is they should be written to achieve a consistent state instead of blindly doing the same sequence of commands again and again.

A bad example would be to append some lines to a file on each invocation. The right approach would be to add a check, if that line was already added and only do it otherwise.

Warning

Make sure to handle package upgrades and removal correctly: Both tasks will invoke any existing scripts prerm and postrm, but with different parameters remove and upgrade only.

It is important that all these scripts handle error conditions properly: Maintainer scripts should exit with exit 0 on success and exit 1 on fail, if things go catastrophically wrong.

On the other hand, an exit code unequal to zero usually aborts any package installation, upgrade or removal process. This prevents any automatic package maintenance and usually requires manual intervention of a human administrator. Therefore, it is essential that maintainer scripts handle error conditions properly and are able to recover an inconsistent state.

16.2.4. Building#

Before the first build is started, remove all unused files from the debian/ directory. This simplifies maintenance of the package and helps other maintainers to concentrate on only the relevant differences from standard packages.

The build process is started by invoking the following command:

$ dpkg-buildpackage -us -uc

The options -us and -uc disable the PGP signing process of the source and changes files. This is only needed for Debian packages, were all files must be cryptographically signed to be uploaded to the Debian infrastructure.

Additionally, the option -b can be added to restrict the build process to only build the binary packages. Otherwise a source package will also be created.

16.2.5. Further reading#

  • The Debian GNU/Linux FAQ - Basics of the Debian package management system [4]

  • Debian New Maintainers' Guide [6]

  • Debian Policy Manual [7]

  • Debian Developer's Reference [8]