Table of Contents
The rewrite of this tutorial document with updated contents and more practical examples is available as Guide for Debian Maintainers. Please use this new tutorial as the primary tutorial document.
Please note that there isn't space here to go into all the details of fixing upstream sources, but here are some basic steps and problems people often run across.
The program quilt offers a basic method for recording
modifications to the upstream source for Debian packaging. It's
useful to have a slightly customized default, so let's create an alias
dquilt for Debian packaging by adding the following
lines to ~/.bashrc
. The second line provides the same
shell completion feature of the quilt command to the
dquilt command:
alias dquilt="quilt --quiltrc=${HOME}/.quiltrc-dpkg" . /usr/share/bash-completion/completions/quilt complete -F _quilt_completion -o filenames dquilt
Then let's create ~/.quiltrc-dpkg
as follows:
d=. ; while [ ! -d $d/debian -a $(readlink -e $d) != / ]; do d=$d/..; done if [ -d $d/debian ] && [ -z $QUILT_PATCHES ]; then # if in Debian packaging tree with unset $QUILT_PATCHES QUILT_PATCHES="debian/patches" QUILT_PATCH_OPTS="--reject-format=unified" QUILT_DIFF_ARGS="-p ab --no-timestamps --no-index --color=auto" QUILT_REFRESH_ARGS="-p ab --no-timestamps --no-index" QUILT_COLORS="diff_hdr=1;32:diff_add=1;34:diff_rem=1;31:diff_hunk=1;33:diff_ctx=35:diff_cctx=33" if ! [ -d $d/debian/patches ]; then mkdir $d/debian/patches; fi fi
See quilt(1) and
/usr/share/doc/quilt/quilt.pdf.gz
on how to use
quilt.
Let's assume you find an error in the upstream Makefile
as follows, where install: gentoo
should have been
install: gentoo-target
.
install: gentoo install ./gentoo $(BIN) install icons/* $(ICONS) install gentoorc-example $(HOME)/.gentoorc
Let's fix this and record it with the dquilt command as
fix-gentoo-target.patch
: [22]
$ mkdir debian/patches $ dquilt new fix-gentoo-target.patch $ dquilt add Makefile
You change the Makefile
file as follows:
install: gentoo-target install ./gentoo $(BIN) install icons/* $(ICONS) install gentoorc-example $(HOME)/.gentoorc
Ask dquilt to generate the patch to create
debian/patches/fix-gentoo-target.patch
and add its
description following DEP-3: Patch Tagging Guidelines:
$ dquilt refresh $ dquilt header -e ... describe patch
Most third-party software installs itself in the /usr/local
directory hierarchy. On Debian this is reserved for private use
by the system administrator, so packages must not use directories such
as /usr/local/bin
but should instead use system
directories such as /usr/bin
, obeying the
Filesystem Hierarchy Standard (FHS).
Normally, make(1) is used to automate building the
program, and executing make install
installs programs
directly to the desired destination (following the
install
target in the
Makefile
). In order for Debian to provide
pre-built installable packages, it modifies the build system to install
programs into a file tree image created under a temporary directory
instead of the actual destination.
These two differences between normal program installation on one hand and the
Debian packaging system on the other can be transparently addressed by the
debhelper
package through the
dh_auto_configure and dh_auto_install
commands if the following conditions are met:
The Makefile
must follow GNU conventions and
support the $(DESTDIR)
variable.
[23]
The source must follow the Filesystem Hierarchy Standard (FHS).
Programs that use GNU autoconf follow the GNU conventions
automatically, so they can be trivial to package. On the basis of
this and other heuristics, it is estimated that the
debhelper
package will work for
about 90% of packages without making any intrusive changes to their
build system. So packaging is not as complicated as it may seem.
If you need to make changes in the Makefile
, you
should be careful to support the $(DESTDIR)
variable. Although it is unset by default, the $(DESTDIR)
variable is prepended to each file path used for the program
installation. The packaging script will set
$(DESTDIR)
to the temporary directory.
For a source package generating a single binary package, the temporary directory used
by the dh_auto_install command will be set to
debian/
.
[24] Everything that is contained in the temporary directory
will be installed on users' systems when they install your package; the only
difference is that dpkg will be installing the
files to paths relative to the root directory rather than your working
directory.
package
Bear in mind that even though your program installs in
debian/
, it still needs
to behave correctly when installed from the package
.deb
package under the root directory. So you must not allow the build
system to hardcode strings like
/home/me/deb/
into files in the package.
package
-version
/usr/share/package
Here's the relevant part of gentoo
's
Makefile
[25]:
# Where to put executable commands on 'make install'? BIN = /usr/local/bin # Where to put icons on 'make install'? ICONS = /usr/local/share/gentoo
We see that the files are set to install under /usr/local
.
As explained above, that directory hierarchy is reserved for local use on
Debian, so change those paths as follows:
# Where to put executable commands on 'make install'? BIN = $(DESTDIR)/usr/bin # Where to put icons on 'make install'? ICONS = $(DESTDIR)/usr/share/gentoo
The exact locations that should be used for binaries, icons, documentation, etc. are specified in the Filesystem Hierarchy Standard (FHS). You should browse through it and read the sections relevant to your package.
So, we should install executable commands in /usr/bin
instead of
/usr/local/bin
, the manual page in
/usr/share/man/man1
instead of
/usr/local/man/man1
, and so on. Notice how there's no manual
page mentioned in gentoo
's
Makefile
, but since Debian Policy requires that every
program has one, we'll make one later and install it in
/usr/share/man/man1
.
Some programs don't use Makefile
variables to define paths
such as these. This means you might have to edit some real C sources in order
to fix them to use the right locations. But where to search, and exactly what
for? You can find this out by issuing:
$ grep -nr --include='*.[c|h]' -e 'usr/local/lib' .
grep will run recursively through the source tree and tell you the filename and the line number for all matches.
Edit those files and in those lines replace usr/local/lib
with usr/lib
. This can be done automatically as follows:
$ sed -i -e 's#usr/local/lib#usr/lib#g' \ $(find . -type f -name '*.[c|h]')
If you want to confirm each substitution instead, this can be done interactively as follows:
$ vim '+argdo %s#usr/local/lib#usr/lib#gce|update' +q \ $(find . -type f -name '*.[c|h]')
Next you should find the install
target (searching
for the line that starts with install:
will usually
work) and rename all references to directories other than ones defined
at the top of the Makefile
.
Originally, gentoo
's
install
target said:
install: gentoo-target install ./gentoo $(BIN) install icons/* $(ICONS) install gentoorc-example $(HOME)/.gentoorc
Let's fix this upstream bug and record it with the dquilt command as
debian/patches/install.patch
.
$ dquilt new install.patch $ dquilt add Makefile
In your editor, change this for the Debian package as follows:
install: gentoo-target install -d $(BIN) $(ICONS) $(DESTDIR)/etc install ./gentoo $(BIN) install -m644 icons/* $(ICONS) install -m644 gentoorc-example $(DESTDIR)/etc/gentoorc
You'll have noticed that there's now an install -d
command
before the other commands in the rule. The original
Makefile
didn't have it because usually
/usr/local/bin
and other directories already exist on the
system where you are running make install
. However, since we will
be installing into a newly created private directory tree, we will have to
create each and every one of those directories.
We can also add in other things at the end of the rule, like the installation of additional documentation that the upstream authors sometimes omit:
install -d $(DESTDIR)/usr/share/doc/gentoo/html cp -a docs/* $(DESTDIR)/usr/share/doc/gentoo/html
Check carefully, and if everything is okay, ask dquilt to
generate the patch to create debian/patches/install.patch
and add its description:
$ dquilt refresh $ dquilt header -e ... describe patch
Now you have a series of patches.
Upstream bug fix: debian/patches/fix-gentoo-target.patch
Debian specific packaging modification:
debian/patches/install.patch
Whenever you make changes that are not specific to the Debian package
such as debian/patches/fix-gentoo-target.patch
, be sure to
send them to the upstream maintainer so they can be included in the next
version of the program and be useful to everyone else. Also remember
to avoid making your fixes specific to Debian or Linux — or even Unix!
Make them portable. This will make your fixes much easier to apply.
Note that you don't have to send the debian/*
files
upstream.
There is one other common problem: libraries are often different from platform
to platform. For example, a Makefile
can contain a
reference to a library that doesn't exist on the Debian system. In that case, we
need to change it to a library that does exist in Debian, and serves the same
purpose.
Let's assume a line in your program's Makefile
(or
Makefile.in
) as the following.
LIBS = -lfoo -lbar
If your program doesn't compile since the foo
library
doesn't exist and its equivalent is provided by the foo2
library on the Debian system, you can fix this build problem as
debian/patches/foo2.patch
by changing
foo
into foo2
:[26]
$ dquilt new foo2.patch $ dquilt add Makefile $ sed -i -e 's/-lfoo/-lfoo2/g' Makefile $ dquilt refresh $ dquilt header -e ... describe patch
[22] The
debian/patches
directory should exist now if you ran
dh_make as described before. This example operation creates
it just in case you are updating an existing package.
[24] For a source package generating multiple binary packages, the
dh_auto_install command uses debian/tmp
as the temporary directory while the dh_install command with
the help of
debian/
and
package-1
.installdebian/
files
will split the contents of package-2
.installdebian/tmp
into
debian/
and
package-1
debian/
temporary
directories, to create
package-2
and
package-1
_*.deb
binary
packages.
package-2
_*.deb
[25] This is just an example to
show what a Makefile
should look like. If the
Makefile
is created by the
./configure command, the correct way to fix this kind of
Makefile
is to execute ./configure
from the dh_auto_configure command with default
options including --prefix=/usr
.
[26] If there
are API changes from the foo
library to the
foo2
library, required changes to the source code need to be
made to match the new API.