Preface

Caution
This manual is still not finished and quite rough.

The debmake command is a helper script to generate Debian packaging files.

The debmake command is intended to replace functions offered historically by deb-make
[This new debmake package starts its version from 4.0 to avoid version overlaps with its predecessor provided the deb-make command.]
and dh_make commands. Its features include:

  • keep pre-existing Debian package configuration files untouched

  • use of dh syntax under the new debhelper (> 9.0) package

    • extensive check of copyright for DEP-5 (with licensecheck(1) and more)

    • substvar supports for binary packages

    • support of compiler hardening options

  • easy packaging command line UI supporting

    • non-stop execution with clean results

    • direct operation on the tarball archive

    • direct operation on the source tree from VCS

    • the multiarch Debian package

    • the multi binary Debian package

    • the non-native Debian packages from the VCS snapshot

    • seamless work with debuild, pdebuild, etc.

Note
I wrote this debmake command because there was no easy command like "python setup.py bdist_deb" to create the Debian binary package. Now "debmake -d -s -b":python" -i debuild" does the job for me.

I will describe the following to get you started with the debmake command.

  • Quick guide for the debmake command

    • This should be enough for you to get started with the debmake command, if you already know the similar dh_make command.

    • Just browse this section first and come back later, if you are new to the Debian packaging.

  • Top down view of the Debian packaging

    • A rewrite in progress of the “Debian New Maintainers' Guide” for the debmake command.

  • Bottom up tutorial for the Debian packaging

    • Step-by-step examples of various packaging cases using simple model packages.

    • The examples.tar.xz tarball has the sources of these and more.

  • Appendix: the debmake(1) manpage

Caution
This document only explains how to make a working set of installable Debian binary packages from the upstream source. Much more details need to be addressed before uploading the package to the Debian archive.

Please read the basic Debian documentations together with this manual to generate perfect Debian packages.

Tip
There is an old Latin saying: “fabricando fit faber” (“practice makes perfect”). It is highly recommended to practice and experiment with all the steps of Debian packaging with simple packages while reading this tutorial.

Quick guide

A quick guide for the debmake command is presented here for simple use cases.

This should be enough for you to get started with the debmake command, if you already know the similar dh_make command.

If you are new to the Debian packaging, do not worry about the details and get the big picture instead. The more detailed tutorial follows this section. There is also the debmake manpage which explains all the command options and included here in the appendix.

Note
The debmake command only provides good template files. You need to manually edit them to the perfection.

The basics

The debmake command produces files required for generating the Debian package using the debuild command. (The debmake command can be used in the same way as the dh_make command.)

 $ tar -xvzf upstreampackage-1.0.tar.gz
 $ cd upstreampackage-1.0
 $ debmake
 $ debuild
Tip
The debmake command provides good default values and requires less input than its predecessors.
Tip
The debuild command used to make Debian binary packages from the source package in examples may be substituted by the equivalent commands such as pdebuild run with the cowbuilder backend.

The extras

Open the upstream tarball

The debmake command can open the upstream tarball before its normal operation when used with the -a option.

 $ debmake -a upstreampackage-1.0.tar.gz
 $ cd upstreampackage-1.0
 $ debuild
Tip
URL such as "http://www.example.org/DL/package-1.0.tar.gz" may be used for the -a option.

Build the binary package

The debmake command can build the source tree after its normal operation when used with the "-i debuild" option.

 $ debmake -a upstreampackage-1.0.tar.gz -i debuild
Tip
The functioning single binary package may be generated automatically without manual modifications to the upstream source.

Make the upstream tarball

The debmake command can generate the upstream tarball with the "make dist" equivalent before its normal operation when used with the -d option. This can be used to produce the upstream tarball snapshot from the upstream source tree in VCS.

 $ cd /path/to/upstream-vcs
 $ debmake -d
 $ cd ../upstreampackage-1.0
 $ debuild

Alternatively, the debmake command can generate the upstream tarball with the tar command before its normal operation when used with the -t option. This can be used to produce the upstream tarball snapshot from the upstream source tree in VCS.

 $ cd /path/to/upstream-vcs
 $ debmake -t
 $ debuild

The -d and -t options combined with the -i option also ease making of non-native Debian packages from the VCS snapshot by allowing to have the debian/ directory contents in the same VCS branch as the upstream development one.

 $ cd /path/to/upstream-vcs
 $ vim
   ... hack upstream source
 $ dch
   ... update debian/changelog
 $ git commit -a
 $ debmake -t -i debuild

I call this Debian non-native binary package building scheme using the "debmake -t -i debuild" command as the quasi-native Debain package scheme since it looks like the Debian native binary package building scheme by the debuild command without the upstream tarball.

Use of the non-native Debain package helps to ease communication with the downstream distros such as Ubuntu for bug fixes etc.

The the debmake command can make a summary report of the copyright and license for the entire source tree using the licensecheck command.

 $ tar -xvzf upstreampackage-1.0.tar.gz
 $ cd upstreampackage-1.0
 $ debmake -c | less

The binary package

The -b option of the debmake command provides intuitive and flexible methods to customize packaging parameters for each binary package. It has no equivalence in dh_make.

The -b optiopn syntax

Let’s quote the pertinent part from the manpage here.

-b "binarypackage,…", --binaryspec "binarypackage,…"

set binary package specs as comma separated list of binarypackage:'type' pairs, e.g., in full form "foo:bin,foo-doc:doc,libfoo1:lib,libfoo1-dbg:dbg,libfoo-dev:dev" or in short form ",-doc,libfoo1,libfoo1-dbg, libfoo-dev".

Here, binarypackage is the binary package name; and optional type is chosen from the following type values:

  • bin: C/C++ compiled ELF binary code package (any, foreign) (default, alias: "", i.e., null-string)

  • data: Data (fonts, graphics, …) package (all, foreign) (alias: da)

  • dbg: Debug symbol package (any, same) (alias: db)

  • dev: Library development package (any, same) (alias: de)

  • doc: Documentation package (all, foreign) (alias: do)

  • lib: Library package (any, same) (alias: l)

  • perl: Perl script package (all, foreign) (alias: pl)

  • python: Python script package (all, foreign) (alias: py)

  • python3: Python3 script package (all, foreign) (alias: py3)

  • ruby: Ruby script package (all, foreign) (alias: rb)

  • script: Shell script package (all, foreign) (alias: sh)

The pair values in the parentheses, such as (any, foreign), are the Architecture and Multi-Arch stanza values set in the debian/control file.

In many cases, the debmake command makes good guess for type from binarypackage. If type is not obvious, type is set to bin. For example, libfoo sets type to lib, and font-bar sets type to data, …

If the source tree contents does not match settings for type, debmake warns you.

The default type is the bin type which means the compiled ELF binary executables. This is why above examples do not specify -b option.

For programs written in other compiler languages, you may need to add its run-time library package as the dependency of the resulting binary package by adjusting debian/control.

Python package example

You can generate a single binary Debian package directly from the Python module package offered as a tarball. The package type python needs to be specified with the -b option.

 $ debmake -b":python" -s -a upstreampackage-1.0.tar.gz -i debuild

For programs written in other interpreter languages, specify script as the package type instead of the default bin and add the interpreter package as the dependency of the resulting binary package by adjusting debian/control.

The -s option makes the debmake command to copy the package description from the upstream Python package to the generated Debian package.

Multi binary package example

Let’s make a following set of binary packages from the upstream tarball foo-1.0.tar.gz.

  • foo: compiled ELF executable binaries from the C program

  • foo-doc: accompanying documentations for foo

  • foo-dbg: accompanying debug symbols for foo

  • perl-foo: accompanying perl programs for foo

 $ debmake -j -b",-doc,-dbg,perl-foo" -a foo-1.0.tar.gz
 $ less foo.build-dep.log
 $ less foo.install.log
 $ rm -rf foo-1.0
 $ debmake -b",-doc,-dbg,perl-foo" -a foo-1.0.tar.gz
 $ cd foo-1.0
 $ vim debian/foo.install
 $ vim debian/foo-doc.install
 $ vim debian/perl-foo.install
 $ vim debian/control
 $ debuild
Tip
See dh_install(1) for how to write debian/binarypackage.install files.

The first invocation of "debmake" is used to identify install paths of files and build dependencies.

The second invocation of "debmake" provides us with the clean build tree.

Tip
The binary package name starting with a "-" (hyphen) is treated as the abbreviated name and the real binary package name is generated by attaching it to the source package name.

Top down tutorial

Debian packaging work flow

The Debian packaging work flow to create the Debian binary package involves generating several specifically named files as defined in the “Debian Policy Manual”.

It can be summarized in 5 steps as follows.

  1. The upstream tarball is downloaded as the package-version.tar.gz file.

  2. The upstream tarball is untared to create many files under the package-version/ directory.

  3. The upstream tarball is copied (or symlinked) to the particular filename packagename_version.orig.tar.gz.

    • the character separating package and version is changed from - (hyphen) to _ (underscore)

    • .orig is added in the file extension.

  4. The Debian package specification files are added to the upstream source under the package-version/debian/ directory.

    • The debmake command invoked in the package-version/ directory helps this by providing template files.

    • debian/rules (This is makefile. Use of dh and debhelper(8) is the current best practice.)

    • debian/control (This defines the binary package names and package dependency.)

    • debian/changelog (This is required.)

    • debian/copyright (This is required.)

    • … (edit these files manually to their perfection according toy the “Debian Policy Manual”)

  5. The dpkg-buildpackage command (usually from its wrapper debuild or pdebuild) is invoked in the package-version/ directory to make the Debian source and binary package by invoking the debian/rules script.

    • Create the Debian source package in "3.0 (quilt)" format using dpkg-source(1)

      • package_version.orig.tar.gz (copy or symlink of package-version.tar.gz)

      • package_version-revision.debian.tar.xz (tarball of package-version/debian/*)

      • package_version-revision.dsc

    • Build the source using "debian/rules build" into $(DESTDIR)

      • DESTDIR=debian/binarypackage/ (single binary package)

      • DESTDIR=debian/tmp/ (multi binary package)

    • Create the Debian binary package using dpkg-deb(1), and dpkg-genchanges(1).

      • binarypackage_version-revision_arch.deb

      • … (There may be multiple Debian binary package files.)

      • package_version-revision_arch.changes

Here, please replace each part of the filename as:

  • the package part with the Debian source package name

  • the binarypackage part with the Debian binary package name

  • the version part with the upstream version

  • the revision part with the Debian revision

  • the arch part with the package architecture

The debmake command

The debmake command is the helper script
[I am prejudiced.]
for the Debian packaging.

  • It makes template files for the step 4 just as dh_make does.

  • It always sets most of the obvious option states and values to reasonable defaults.

  • It delegates most of the heavy lifting to its back-end packages: debhelper, dpkg-dev, devscripts, etc.

  • It always prepares to build the source for the multiarch package, unless -m option is explicitly specified.

  • It always prepares to build the non-native Debian package with the "3.0 (quilt)" format, unless -n option is explicitly specified.

  • It can function as a wrapper script integrating all the steps 1-5.

  • It has the -a option to make it work directly with the tarball.

  • It has the -t and -d options to make it work well with the source files in VCS. These options also allow to make the non-native Debian package from the VCS source tree with the package-version/debian/ directory. Please note, the non-native Debian package is the normal Debian package.

A functional single binary package can be generated automatically without touching files in the package-version/debian/ directory generated by the debmake command. Such a package can be used locally.

  • To comply with the strict quality requirements of the Debian archive, these template files must be manually adjusted to their perfection before the upload.

  • For example, you can get a Python module packaged by the Python distutils and make its Debian binary package by simply running "debmake -d -i debuild" in its untared source tree.

The functional multi binary package always requires some extra manual works. These works are done as follows:

  • Invoke debmake with the -b"package1:type1, …" and -j options in the package-version/ directory.

  • Check the last lines of package.build-dep.log to judge build dependencies for Build-Depends. (You do not need to list packages used by debhelper, perl, or fakeroot explicitly in Build-Depends.)

  • Check the contents of package.install.log to identify file paths in debian/tmp.

  • Update debian/control and debian/binarypackage.install files using the above information.

  • Update other debian/* files as needed.

  • Build binary packages with debuild, pdebuild, etc.

  • Files installed into debian/tmp are split by debian/binarypackage.install into each binarypackage_version-revision_arch.deb.

Tip
Make sure to protect the arguments of the -b, -f, -n, and -w options from the shell interference by quoting them properly.

Package name and version

If the upstream source comes as hello-0.9.12.tar.gz, you can take hello as the upstream source package name and 0.9.12 as the upstream version.

There are some limitations for what characters may be used as a part of the Debian package. The most notable limitation is the prohibition of uppercase letters in the package name. Here is the summary in the regular expression.

  • Upstream package name (-p): [-+.a-z0-9]{2,}

  • Binary package name (-b): [-+.a-z0-9]{2,}

  • Upstream version (-u): [0-9][-+.:~a-z0-9A-Z]*

  • Debian revision (-r): [0-9][+.~a-z0-9A-Z]*

See the exact definition in “5.6.1 Source”, “5.6.7 Package”, and “5.6.12 Version” of “Debian Policy Manual”. (http://www.debian.org/doc/debian-policy/ch-controlfields.html)

You must adjust the package name and upstream version accordingly for the Debian packaging.

If upstream does not use a normal versioning scheme such as 2.30.32 but uses some kind of date such as 11Apr29, a random codename string, or a VCS hash value as part of the version, make sure to remove them from the upstream version. Such information can be recorded in the debian/changelog file. If you need to invent a version string, use the YYYYMMDD format such as 20110429 as upstream version. This ensures that dpkg interprets later versions correctly as upgrades. If you need to ensure smooth transition to the normal version scheme such as 0.1 in future, use the 0~YYMMDD format such as 0~110429 as upstream version, instead.

Version strings can be compared using dpkg(1) as follows.

$ dpkg --compare-versions ver1 op ver2

The version comparison rule can be summarized as:

  • Strings are compared from the head to the tail.

  • Letters are larger than digits.

  • Numbers are compared as integers.

  • Letters are compared in ASCII code order.

There are special rules for period (.), plus (+), and tilde (~) characters, as follows.

0.0 < 0.5 < 0.10 < 0.99 < 1 < 1.0~rc1 < 1.0 < 1.0+b1 < 1.0+nmu1 < 1.1 < 2.0

One tricky case occurs when upstream releases hello-0.9.12-ReleaseCandidate-99.tar.gz as the pre-release of hello-0.9.12.tar.gz. You need to make sure that the upgrade works properly by renaming the upstream source to hello-0.9.12~rc99.tar.gz.

Debian packaging script

The Debian packaging script re-targets the build systems to install files in the $(DESTDIR) and creates the archive file of the generated files as the deb file. This deb file is used for the binary distribution and installed to the system using the dpkg command.

  • $(DESTDIR)=debian/binarypackage : when building a single binary package, binarypackage.

  • $(DESTDIR)=debian/tmp : when building multiple binary packages.

The dh command

The dh command from the debhelper package with the help from its associated packages functions as the wrapper to the typical build systems and offers us with the uniform access to them by supporting all the Debian policy stipulated targets of the debian/rules file.

  • dh clean : clean files in the source tree.

  • dh build : build the source tree

  • dh build-arch : build the source tree for architecture dependent packages

  • dh build-indep : build the source tree for architecture independent packages

  • dh install : install the binary files to $(DESTDIR)

  • dh install-arch : install the binary files to $(DESTDIR) for architecture dependent packages

  • dh install-indep : install the binary files to $(DESTDIR) for architecture independent packages

  • dh binary : generate the deb file

  • dh binary-arch : generate the deb file for architecture dependent packages

  • dh binary-indep : generate the deb file for architecture independent packages

Thanks to this abstraction of the dh command
[This simplicity is available since the debhelper version 7. This document assumes that the debhelper version 9 or newer is used.]
, the Debian policy compliant debian/rules file supporting all the required targets can be written as simple as:

Simple debian/rules:
%:
        dh $@

Essentially, this dh command calls all required dh_* commands at the right moment.

The debmake command takes full advantage of this simple package building process enabled by the debhelper package for normal cases.

You still need to know how underlying build systems well for fixing bugs and making workarounds.

Package customization

There are some upstream sources which does not behave well and you may need to add customization to the build system of those upstream sources.

You have two approaches to customize the build system here:

  • Apply modifications to the upstream source before building it.

    • Set up debian/patches/* with -p1 patches and specify their sequence in debian/series

  • Add customization to the Debian package build system.

    • Set up "debian/rules" with appropriate override_dh_* targets.

      • Whenever some special operation is required for a certain dh_foo command, any automatic execution of it can be overridden by adding the makefile target override_dh_foo in the debian/rules file.

    • Add configuration files for the debhelper package in the debian/ directory.

      • debian/binarypackage.install, debian/binarypackage.link, debian/binarypackage.manpages, debian/binarypackage.docs, …

Splitting the package

Sometimes, it is better to split the generated binary package into small ones. This can be easily realized:

  • by creating binary package entries for all binary packages in the debian/control file, and

  • by listing all file paths (relative to debian/tmp) in the debian/binarypackage.install files.

See dh_install(1).

Upstream build systems

upstream build systems go through several steps to install generated binary files to the system from the source distribution.

Autotools

Autotools (autoconf + automake) has 4 steps.

  1. setup the build system ("vim configure.ac Makefile.am" and "autoreconf -ivf")

  2. configure the build system ("./configure")

  3. build the source tree ("make")

  4. install the binary files ("make install")

The upstream usually performs the step 1 and builds the upstream tarball for distribution using the "make dist" command.

The package maintainer needs to take care step 2 to 4 at least. This is realized by the "dh $@ --with autotools-dev" command used in the debian/rules file.

The package maintainer wishes to take care step 1 to 4. This is realized by the "dh $@ --with autoreconf" command used in the debian/rules file. This rebuilds all auto-generated files to the latest version and provides better porting supports.

Python distutils

Python distutils has 3 steps.

  1. setup and configure the build system ("vim setup.py")

  2. build the source tree ("python setup.py build")

  3. install the binary files ("python setup.py install")

The upstream usually performs the step 1 and builds the upstream tarball for distribution using the "python setup.py sdist" command.

The package maintainer needs to take care step 2. This is realized simply by the "dh $@" command used in the debian/rules file, after jessie.

Shared library

Basics of the shared library

Before packaging shared libraries, you should read the following primary references in detail.

  • “Debian Policy Manual, 8 Shared libraries”

  • “Debian Policy Manual, 9.1.1 File System Structure”

  • “Debian Policy Manual, 10.2 Libraries”

Here are some oversimplified hints for you to get started.

  • Shared libraries are ELF object files containing compiled code.

  • Shared libraries are distributed as *.so files. (Neither *.a files nor *.la files)

  • Shared libraries are mainly used to share common codes among multiple executables with the ld mechanism.

  • Shared libraries are sometimes used to provide multiple plugins to an executable with the dlopen mechanism.

  • Shared libraries export symbols which represent compiled objects such as variables, functions, and classes; and enables access to them from the linked executables.

  • The SONAME of a shared library libfoo.so.i1: "objdump -p libfoo.so.1 | grep SONAME"

  • The SONAME of a shared library usually matches the library file name (but not always).

  • The SONAME of shared libraries linked to /usr/bin/foo: "objdump -p /usr/bin/foo | grep NEEDED"

  • libfoo1: the library package for the shared library libfoo.so.1 with the SONAME ABI version 1.

  • The package maintainer scripts of the library package must call ldconfig under the specific circumstances to create the necessary symbolic links for the SONAME.

  • libfoo1-dbg: the debugging symbols package which contains the debugging symbols for the shared library package libfoo1.

  • libfoo-dev: the development package which contains the header files etc. for the shared library libfoo.so.1.

  • Debian package should not contain *.la Libtool archive files in general.

  • Debian package should not use RPATH in general.

Note
The "readelf -d" command may be used in place for the "objdump -p" command.

Although it is somewhat outdated and is only a secondary reference, “Debian Library Packaging Guide” may still be useful.

Shared library example

When packaging the shared library package, one needs to be careful to accommodate the future major library upgrades. Its corresponding debug package may contain the major library version as a part of the package name while other corresponding packages should not contain them. For example:

  • libfoo-1.0.tar.gz : the upstream source package tarball

  • libfoo : the upstream source package name

  • libfoo1 : the library binary package name

  • libfoo1-dbg : the debug symbol binary package name

  • libfoo-dev : the development binary package

  • libfoo-doc : the documentation binary package

  • libfoo-utils : the executable binary package

debian/package.symbols

When you package a shared library libfoo1, you should create debian/libfoo1.symbols file to manage the minimal version associated to each symbol for backward-compatible ABI changes under the same SONAME of the library for the same shared library package name. You should read the following primary references in detail.

  • “Debian Policy Manual, 8.6.3 The symbols system”

  • dh_makeshlibs(1)

  • dpkg-gensymbols(1)

  • dpkg-shlibdeps(1)

  • deb-symbols(5)

Tip
For C++ libraries and other cases where tracking individual symbols is too difficult, follow the “Debian Policy Manual, 8.6.4 The shlibs system”, instead.

Here is a rough example to create the libfoo1 package to the upstream version 1.3 with the proper debian/libfoo1.symbols file.

Prepare the skeleton debianized source tree using the upstream ‘libfoo-1.3’.tar.gz file.

If this is the first packaging of the libfoo1 package, create the debian/libfoo1.symbols file with empty content.

If the previous upstream version 1.2 was packaged as the libfoo1 package with the proper debian/libfoo1.symbols in its source package, use it again.

If the previous upstream version 1.2 was not packaged with the debian/libfoo1.symbols, create it as the symbols file from all available binary packages of the same shared library package name containing the same SONAME of the library, for example, versions 1.1-1 and 1.2-1.
[All previous versions of Debian packages are available at http://snapshot.debian.org/. The Debian revision is dropped from the version to make it easier to backport the package: 1.1 << 1.1-1~bpo70+1 << 1.1-1 and 1.2 << 1.2-1~bpo70+1 << 1.2-1]

 $ dpkg-deb -x libfoo1_1.1-1.deb libfoo1_1.1-1
 $ dpkg-deb -x libfoo1_1.2-1.deb libfoo1_1.2-1
 $ : > symbols
 $ dpkg-gensymbols -v1.1 -plibfoo1 -Plibfoo1_1.1-1 -Osymbols
 $ dpkg-gensymbols -v1.2 -plibfoo1 -Plibfoo1_1.2-1 -Osymbols

Make trial builds of the source tree with tools such as debuild and pdebuild. (If this fails due to missing symbols etc., there were some backward-incompatible ABI changes which require you to bump the shared library package name to something like libfoo2 and you should start over again.)

 $ cd libfoo-1.3
 $ debuild
 ...
dpkg-gensymbols: warning: some new symbols appeared in the symbols file: ...
 see diff output below
--- debian/libfoo1.symbols (libfoo1_1.3-1_amd64)
+++ dpkg-gensymbolsFE5gzx        2012-11-11 02:24:53.609667389 +0900
@@ -127,6 +127,7 @@
  foo_get_name@Base 1.1
  foo_get_longname@Base 1.2
  foo_get_type@Base 1.1
+ foo_get_longtype@Base 1.3-1
  foo_get_symbol@Base 1.1
  foo_get_rank@Base 1.1
  foo_new@Base 1.1
...

If you see the diff printed by the dpkg-gensymbols as above, extract the updated proper symbols file from the generated binary package of the shared library. Here, the Debian revision is dropped from the version to make it easier to backport the package: 1.3 << 1.3-1~bpo70+1 << 1.3-1

$ cd ..
$ dpkg-deb -R  libfoo1_1.3_amd64.deb libfoo1-tmp
$ sed -e 's/1\.3-1/1\.3/' libfoo1-tmp/DEBIAN/symbols \
        >libfoo-1.3/debian/libfoo1.symbols

Build release packages with tools such as debuild and pdebuild.

$ cd libfoo-1.3
$ debuild clean
$ debuild
...

In addition to the above examples, we need to check the ABI compatibility further and bump versions for some symbols manually as needed.

Although it is only a secondary reference, Debian wiki UsingSymbolsFiles and its linked web pages may be useful.

Multiarch

The multiarch feature introduced to Debian wheezy integrates support for cross-architecture installation of binary packages (particularly i386<->amd64, but also other combinations) in dpkg and apt. You should read the following references in detail.

  • Ubuntu wiki MultiarchSpec (upstream)

  • Debian wiki Multiarch/Implementation (Debian situation)

It uses the triplet such as i386-linux-gnu and x86_64-linux-gnu for the install path of shared libraries. The actual triplet path is dynamically set into $(DEB_HOST_MULTIARCH) value by dpkg-architecture for each build. For example, the path to install multiarch libraries are changed as follows. (Old special purpose library paths such as /lib32/ and /lib64/ are not used any more.)

Old path

i386 multiarch path

amd64 multiarch path

/lib/

/lib/i386-linux-gnu/

/lib/x86_64-linux-gnu/

/usr/lib/

/usr/lib/i386-linux-gnu/

/usr/lib/x86_64-linux-gnu/

Here are some typical multiarch package split scenario examples for the followings:

  • a library source libfoo-1.tar.gz

  • a tool source bar-1.tar.gz written in a compiled language

  • a tool source baz-1.tar.gz written in an interpreted language

Package

Architecture:

Multi-Arch:

Package content

libfoo1

any

same

the shared library, co-installable

libfoo1-dbg

any

same

the shared library debug symbols, co-installable

libfoo-dev

any

same

the shared library header files etc., co-installable

libfoo-tools

any

foreign

the run-time support programs, not co-installable

libfoo-doc

all

foreign

the shared library documentation files

bar

any

foreign

the compiled program files, not co-installable

bar-doc

all

foreign

the documentation files for the program

baz

all

foreign

the interpreted program files

Please note that the development package should contain a symlink for the associated shared library without a version number. E.g.: /usr/lib/x86_64-linux-gnu/libfoo.solibfoo.so.1

Building a shared library package

You can build a Debian library package enabling the multiarch support using dh as follows.

  • Update debian/control.

    • Add "Build-Depends: debhelper (>=9)" for the source package section.

    • Add "Pre-Depends: ${misc:Pre-Depends}" for each shared library binary package.

    • Add Multi-Arch: stanza for each binary package section.

  • Set debian/compat to "9".

  • Adjust the path from the normal /usr/lib/ to the multiarch /usr/lib/$(DEB_HOST_MULTIARCH)/ for all packaging scripts.

    • Call "DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)" in debian/rules to set DEB_HOST_MULTIARCH variable, first.

    • Replace /usr/lib/ with /usr/lib/$(DEB_HOST_MULTIARCH)/ in debian/rules.

    • If ./configure is used in the part of override_dh_auto_configure target in debian/rules, make sure to replace it with "dh_auto_configure --" .

  • Replace all occurrences of /usr/lib/ with /usr/lib/\/* in debian/foo.install files.

  • Generate files like debian/foo.links from debian/foo.links.in dynamically by adding a script to override_dh_auto_configure target in debian/rules.

override_dh_auto_configure:
        dh_auto_configure
        sed 's/@DEB_HOST_MULTIARCH@/$(DEB_HOST_MULTIARCH)/g' \
                debian/foo.links.in > debian/foo.links

Please make sure to verify that the shared library package contains only the expected files, and that your -dev package still works.

All files installed simultaneously as the multiarch package to the same file path should have exactly the same file content. You must be careful on differences generated by the data byte order and by the compression algorithm.

Note
As fot ./configure, you can add --libdir={prefix}/lib/$(DEB_HOST_MULTIARCH) arguments to ./configure. Please note that --libexecdir specifies the default path to install executable programs run by other programs rather than by users. Its Autotools default is /usr/libexec/ but its Debian default is /usr/lib/.

Debian package building reminders

Here are some reminders for the Debian package building.

  • The debmake command aims to address typical packaging situation only.

  • The Debian package generated by the above package building work flow is in the non-native package format.

  • The Debian source package means the set of input files used to build the Debian binary package building and is not a single file.

  • A single Debian source package may generate multiple Debian binary packages defined in the debian/control file.

  • The debian/rules file is a makefile.

    • The debian/rules file may be crafted primarily by a single "dh $@" command while using dh_* commands as its back-end. (recommended approach by this author)

    • The debian/rules file can be customized by optional "override_dh_:*" targets.

    • Both dh and dh_* commands are a part of the debhelper package (see debhelper(8)).

    • The debhelper package works best if the build system of the upstream tarball is made to support the $(DESTDIR) feature (a part of GNU coding standard).

    • The $(DESTDIR) feature is supported by many build systems such as Autotools, CMake, Python Distutils, etc.

  • The dpkg-buildpackage(1) command is usually invoked by a wrapper script which sets up the proper build environments.

    • debuild(1)

    • pdebuild(1) (optionally with cowbuilder(8))

    • gbp-buildpackage(1) (use git-pbuilder(1) and cowbuilder(8) as a part of its back-end)

  • The debmake(1) command helps to generate packaging template files and automating the sequence of associated routine tasks.

    • Use script type and customize the debian/control file if any other interpreter is used.

    • Use bin type and customize the debian/control file if any other compiler is used.

    • The debmake command is designed to make the multiarch package as default.

      • The -m option needs to be specified to make the non-multiarch package.

    • Fancy multiarch "allowed" packages etc. need to be manually set in the debian/control file.

  • Some people promote to package even programs which have been written especially for Debian in the non-native package format with the above workflow while generating the required tarball without debian/* files by oneself in advance. They claim that the use of non-native package format eases communication with the downstream distributions.

Bottom up tutorial

Basic tool setups

Although these are not nessasary the requirement, basic tool setups are described as below for us to share the common baseline working environment.

Setting up bash

Various Debian maintenance tools offered by the devscripts package and debmake recognize your email address and name to use by the shell environment variables $DEBEMAIL and $DEBFULLNAME.

Let’s set up these by adding the following lines to /.bashrc foornote[This assumes you are using Bash as your login shell. If you use some other login shell such as Z shell, use their corresponding configuration files instead of /.bashrc.].

DEBEMAIL="your.email.address@example.org"
DEBFULLNAME="Firstname Lastname"
export DEBEMAIL DEBFULLNAME

Setting up quilt

The program quilt offers a basic method for recording modifications to the upstream source for the Debian packaging. It’s useful to have a slightly customized default suitable for the Debian packaging to avoid changing the behavior of the quilt command itself.

Let’s create an alias dquilt for the Debian packaging by adding the following lines to the ~/.bashrc file. The second line provides the same shell completion feature of the quilt command to the dquilt command.

alias dquilt="quilt --quiltrc=${HOME}/.quiltrc-dpkg"
complete -F _quilt_completion $_quilt_complete_opt 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 the quilt command.

Setting up devscripts

The debuild command runs the dpkg-buildpackage and lintian commands under the current build environment with the sanitized environment variables to create all the files necessary for uploading a Debian package.

Let’s create ~/.devscripts as follows.

DEBSIGN_KEYID='Your_GPG_keyID'
DEBUILD_LINTIAN_OPTS=-i -I --show-overrides

With these, packages are signed by your specified GPG key ID (good for sponsoring packages) and checked in detail by the lintian command.

Setting up pbuilder + cowbuilder

The pbuilder package provides the clean room (chroot) build environment. The cowbuilder package boosts its processing speed. Let’s customize these packages to make the pdebuild command to run with the cowbuilder and *lintian commands.

Let’s create ~/.pbuilderrc as follows.

AUTO_DEBSIGN=${AUTO_DEBSIGN:-no}
HOOKDIR=/var/cache/pbuilder/hooks
PDEBUILD_PBUILDER=cowbuilder
BUILDRESULT=../

Let’s create a hook script /var/cache/pbuilder/hooks/B90lintian as follows.

#!/bin/sh
set -e
apt-get -y --force-yes install lintian
echo "+++ lintian output +++"
su -c "lintian -i -I --show-overrides /tmp/buildd/*.changes; :" -l pbuilder
echo "+++ end of lintian output +++"

Setting up git

You may wish to set several global configuration in ~/.gitconfig such as your name and email address used by Git by the following.

$ git config --global user.name "Name Surname"
$ git config --global user.email yourname@example.com

If you are too used to CVS or Subversion commands, you may wish to set several command aliases by the following.

$ git config --global alias.ci "commit -a"
$ git config --global alias.co checkout

You can check your global configuration by the following.

$ git config --global --list
Tip
It is essential to use the gitk command for Git repository.

Setting up git-buildpackage

You may wish to set several global configuration in ~/.gbp.conf

# Configuration file for "gbp <command>"

[DEFAULT]
# the default build command:
builder = git-pbuilder -i -I -us -uc
# use pristine-tar:
pristine-tar = True
# Use color when on a terminal, alternatives: on/true, off/false or auto
color = auto

Basic single binary package

For the case of creating a single binary Debian package from the $(DESTDIR) and Filesystem Hierarchy Standard (FHS) supporting source, the packaging process can be practically automatic if you only wish to make it for your local use and do not worry about details of the Debian Policy.

Let’s assume you have a simple upstream source tarball hello-c-1.0.tar.gz.

 $ wget http://www.example.org/download/hello-c-1.0.tar.gz
 ...

Let’s untar it.

 $ tar -xvzmf hello-c-1.0.tar.gz
hello-c-1.0/
hello-c-1.0/Makefile
hello-c-1.0/hello.c

Let’s inspect files.

 $ tree
.
|-- hello-c-1.0
|   |-- hello.c
|   `-- Makefile
`-- hello-c-1.0.tar.gz

1 directory, 3 files

Makefile supports $(DESTDIR).

 $ cat hello-c-1.0/Makefile
all: hello

hello: hello.c
        gcc -Wall -o hello hello.c

install: hello
        install -D hello $(DESTDIR)/usr/bin/hello

clean:
        -rm -f hello

distclean: clean

.PHONY: all install clean distclean

The C source hello.c is a very simple one.

 $ cat hello-c-1.0/hello.c
#include <stdio.h>
int
main()
{
        printf("Hello, Debian packager!\n");
        return 0;
}

You create a non-native Debian package source tree from this upstream example using the debmake command.

 $ cd hello-c-1.0
 $ debmake
I: set parameters
I: sanity check of parameters
I: pkg="hello-c", ver="1.0", rev="1"
I: *** start packaging in "hello-c-1.0". ***
I: provide hello-c_1.0.orig.tar.gz for non-native Debian package
I: pwd = "/path/to"
I: $ ln -sf hello-c-1.0.tar.gz hello-c_1.0.orig.tar.gz
I: pwd = "/path/to/hello-c-1.0"
I: parse binary package settings:
I: binary package=hello-c Type=bin / Arch=any M-A=foreign
I: analyze the source tree
I: build_type = make
I: 100 %, ext = c
I: make debian/* template files
I: single binary package
I: debmake -x "1" ...
I: creating => debian/control
I: creating => debian/copyright
I: creating => debian/changelog
I: creating => debian/rules
I: creating => debian/compat
I: creating => debian/watch
I: creating => debian/README.Debian
I: creating => debian/source/format
I: creating => debian/source/local-options
I: creating => debian/patches/series
I: run "debmake -x2" to get more template files
I: $ wrap-and-sort

Let’s inspect generated template files.

debian/rules:
 $ cat debian/rules
#!/usr/bin/make -f
# See debhelper(7) (uncomment to enable)
# output every command that modifies files on the build system.
#DH_VERBOSE = 1

# harden via compile options
# see FEATURE AREAS in dpkg-buildflags(1))
#export DEB_BUILD_MAINT_OPTIONS = hardening=+all
# see ENVIRONMENT in dpkg-buildflags(1))
# package maintainers to append CFLAGS
#export DEB_CFLAGS_MAINT_APPEND  = -Wall -pedantic
# package maintainers to append LDFLAGS
#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed

# main packaging script based on dh7 syntax
%:
        dh $@

# debmake generated override targets
# Set required multiarch library install path.
# See dpkg-architecture(1)
#DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
#
# This is example for Cmake (See http://bugs.debian.org/641051 )
#override_dh_auto_configure:
#       dh_auto_configure -- \
#       -DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH)

This is essentialy the standard debian/rules file with the dh command. (There are some commented out contens for you to customize it.)

Tip
Configuration files used by the debhelper command usually treat # as the start of the comment line.
debian/control:
 $ cat debian/control
Source: hello-c
Section: unknown
Priority: extra
Maintainer: "Firstname Lastname" <email.address@example.org>
Build-Depends: debhelper (>=9)
Standards-Version: 3.9.5
Homepage: <insert the upstream URL, if relevant>

Package: hello-c
Architecture: any
Multi-Arch: foreign
Depends: ${misc:Depends}, ${shlibs:Depends}
Description: auto-generated package by debmake
 This Debian binary package was auto-generated by the
 debmake(1) command provided by the debmake package.
 .
 ===== This comes from the unmodified template file =====
 .
 Please edit this template file (debian/control) and other package files...
 (debian/*) to make them meet all the requirements of the Debian Policy
 before uploading this package to the Debian archive.
 .
 See
  * http://www.debian.org/doc/manuals/maint-guide/dreq.en.html#control
  * http://www.debian.org/doc/manuals/developers-reference/best-pkging-p...
 .
 The synopsis description at the top should be about 60 characters and
 written as a phrase.  No extra capital letters or a final period.  No
 articles — "a", "an", or "the".
 .
 The package description for general-purpose applications should be
 written for a less technical user.  This means that we should avoid
 jargon.  GNOME or KDE is fine but GTK+ is probably not.
 .
 Use the canonical forms of words:
  * Use X Window System, X11, or X; not X Windows, X-Windows, or X Windo...
  * Use GTK+, not GTK or gtk.
  * Use GNOME, not Gnome.
  * Use PostScript, not Postscript or postscript.

Please note that the debmake command is run with the -x21 option as the default for the new single binary package.

Since this is the ELF binary executable package (type=bin), it is set to "Architecture: any" and "Multi-Arch: foreign". Also, required substvar parameters are set as "Depends: ${shlibs:Depends}, ${misc:Depends}" by the debmake command.

Note
Please note this debian/control file uses the RFC-822 style as documented in the “Debian Policy Manual: 5.2 Source package control files — debian/control”. The use of the empty line and the leading space are significant.

There are several other template files under the debian/ directory.

The source tree after the basic debmake execution.
 $ cd ..
 $ tree
.
|-- hello-c-1.0
|   |-- debian
|   |   |-- changelog
|   |   |-- compat
|   |   |-- control
|   |   |-- copyright
|   |   |-- patches
|   |   |   `-- series
|   |   |-- README.Debian
|   |   |-- rules
|   |   |-- source
|   |   |   |-- format
|   |   |   `-- local-options
|   |   `-- watch
|   |-- hello.c
|   `-- Makefile
|-- hello-c_1.0.orig.tar.gz -> hello-c-1.0.tar.gz
`-- hello-c-1.0.tar.gz

4 directories, 14 files

For the proper packaging, you are required to make further modification here.

For learning purpose, let’s leave such details and move on. You can create a non-native Debian package using the debuild command (or its equivalents) in this source tree.

 $ cd hello-c-1.0
 $ debuild
 dpkg-buildpackage -rfakeroot -D -us -uc -I -i
 ...
 fakeroot debian/rules clean
dh clean
 ...
 debian/rules build
dh build
 ...
 fakeroot debian/rules binary
dh binary
 ...
Finished running lintian.

Let’s inspect the result.

The generated files of version 1.0 by the debuild command:
 $ cd ..
 $ tree -L 1
.
|-- hello-c-1.0
|-- hello-c_1.0-1_amd64.build
|-- hello-c_1.0-1_amd64.changes
|-- hello-c_1.0-1_amd64.deb
|-- hello-c_1.0-1.debian.tar.xz
|-- hello-c_1.0-1.dsc
|-- hello-c_1.0.orig.tar.gz -> hello-c-1.0.tar.gz
`-- hello-c-1.0.tar.gz

1 directory, 7 files
The source package contents of version 1.0:
 $ tar -tJf hello-c_1.0-1.debian.tar.xz
debian/
debian/compat
debian/changelog
debian/watch
debian/control
debian/copyright
debian/README.Debian
debian/rules
debian/source/
debian/source/format
debian/patches/
debian/patches/series
 $ tar -tzf hello-c-1.0.tar.gz
hello-c-1.0/
hello-c-1.0/Makefile
hello-c-1.0/hello.c
The binary package contents of version 1.0:
 $ dpkg -c hello-c_1.0-1_amd64.deb
drwxr-xr-x root/root ...  ./
drwxr-xr-x root/root ...  ./usr/
drwxr-xr-x root/root ...  ./usr/bin/
-rwxr-xr-x root/root ...  ./usr/bin/hello
drwxr-xr-x root/root ...  ./usr/share/
drwxr-xr-x root/root ...  ./usr/share/doc/
drwxr-xr-x root/root ...  ./usr/share/doc/hello-c/
-rw-r--r-- root/root ...  ./usr/share/doc/hello-c/copyright
-rw-r--r-- root/root ...  ./usr/share/doc/hello-c/README.Debian
-rw-r--r-- root/root ...  ./usr/share/doc/hello-c/changelog.Debian.gz

Modifications to the upstream

Let’s assume we have an older upstream source tarball hello-c-0.9.tar.gz. The Makefile of version 0.9 installs its binary to the fixed location /usr/local/bin/hello and does not support $(DESTDIR) like the one in the upstream source tarball hello-c-1.0.tar.gz.

There are several methods to prepare the -p1 patch needed for applying modifications to this 0.9 upstream source.

  • The diff command

  • The dquilt command (alias of the quilt command)

  • The git comamnd with the --format-paches option.

  • The git-dpm comamnd.

Here we show the method with the dquilt command.

The packaging procedure is the same as that of version 1.0 up to running the debmake command.

 $ cd hello-c-0.9
 $ debmake
I: set parameters
I: sanity check of parameters
I: pkg="hello-c", ver="0.9", rev="1"
 ...
 ... (snip)
 ...
I: run "debmake -x2" to get more template files
I: $ wrap-and-sort

The "dquilt new …" command sets the name of the patch.

The "dquilt add …" command sets the files to be modified.

 $ dquilt new 0001-destdir.patch
Patch 0001-destdir.patch is now on top
 $ dquilt add Makefile
File Makefile added to patch 0001-destdir.patch
 $ cat Makefile
all: hello

hello: hello.c
        gcc -Wall -o hello hello.c

install: hello
        install -D hello /usr/local/bin/hello

clean:
        -rm -f hello

distclean: clean

.PHONY: all install clean distclean

The vim command edits the Makefile to be modified to support $(DESTDIR)..

The "dquilt refresh …" command records the modification as the -p1 patch in the debian/patches/ directory.

 $ vim Makefile
 ...
 $ cat Makefile
all: hello

hello: hello.c
        gcc -Wall -o hello hello.c

install: hello
        install -D hello $(DESTDIR)/usr/bin/hello

clean:
        -rm -f hello

distclean: clean

.PHONY: all install clean distclean
 $ dquilt refresh
Refreshed patch 0001-destdir.patch
 $ cat debian/patches/0001-destdir.patch
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@
        gcc -Wall -o hello hello.c

 install: hello
-       install -D hello /usr/local/bin/hello
+       install -D hello $(DESTDIR)/usr/bin/hello

 clean:
        -rm -f hello

The "dquilt header -e …" command adds the DEP-3: Patch Tagging Guidelines compatible patch header.

The "dquilt pop -a" command removes all applied patches from the source.

 $ dquilt header -e
 ...
 $ cat debian/patches/0001-destdir.patch
From: Foo Bar <foo@example.org>
Description: make Makefile to support GNU coding standard
 $DESTDIR: debian/hello-c
 $prefix:  /usr/local -> /usr

--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@
        gcc -Wall -o hello hello.c

 install: hello
-       install -D hello /usr/local/bin/hello
+       install -D hello $(DESTDIR)/usr/bin/hello

 clean:
        -rm -f hello
 $ dquilt pop -a
Removing patch 0001-destdir.patch
Restoring Makefile

No patches applied
 $ cat debian/patches/series
# The patch files of the -p1 format included in the debian/patches direc...
# are applied to the upstream source in the order listed below.
# This is manually managed by users with dquilt (quilt(1) wrapper) etc.
# See http://www.debian.org/doc/manuals/maint-guide/modify.en.html#quilt...
# Also this may be updated by dpkg-source(1) when making a package.
0001-destdir.patch

For the proper packaging, you are required to make further modification here.

For learning purpose, let’s leave such details and move on. You can create a non-native Debian package using the debuild command (or its equivalents) in this source tree.

 $ cd hello-c-0.9
 $ debuild
 dpkg-buildpackage -rfakeroot -D -us -uc -I -i
 ...
dpkg-source: info: applying 0001-destdir.patch
 fakeroot debian/rules clean
dh clean
 ...
 debian/rules build
dh build
 ...
 fakeroot debian/rules binary
dh binary
 ...
Finished running lintian.

Let’s inspect files.

The generated files of version 0.9 by the debuild command:
 $ cd ..
 $ tree -L 1
.
|-- hello-c-0.9
|-- hello-c_0.9-1_amd64.build
|-- hello-c_0.9-1_amd64.changes
|-- hello-c_0.9-1_amd64.deb
|-- hello-c_0.9-1.debian.tar.xz
|-- hello-c_0.9-1.dsc
|-- hello-c_0.9.orig.tar.gz -> hello-c-0.9.tar.gz
`-- hello-c-0.9.tar.gz

1 directory, 7 files
The source package contents of version 0.9:
 $ dpkg -c hello-c_0.9-1_amd64.deb
drwxr-xr-x root/root ...  ./
drwxr-xr-x root/root ...  ./usr/
drwxr-xr-x root/root ...  ./usr/bin/
-rwxr-xr-x root/root ...  ./usr/bin/hello
drwxr-xr-x root/root ...  ./usr/share/
drwxr-xr-x root/root ...  ./usr/share/doc/
drwxr-xr-x root/root ...  ./usr/share/doc/hello-c/
-rw-r--r-- root/root ...  ./usr/share/doc/hello-c/copyright
-rw-r--r-- root/root ...  ./usr/share/doc/hello-c/README.Debian
-rw-r--r-- root/root ...  ./usr/share/doc/hello-c/changelog.Debian.gz
The binary package contents of version 0.9:
 $ tar -tJf hello-c_0.9-1.debian.tar.xz
debian/
debian/compat
debian/changelog
debian/watch
debian/control
debian/copyright
debian/README.Debian
debian/rules
debian/source/
debian/source/format
debian/patches/
debian/patches/0001-destdir.patch
debian/patches/series
 $ tar -tzf hello-c-0.9.tar.gz
hello-c-0.9/
hello-c-0.9/Makefile
hello-c-0.9/hello.c

Basic multi binary package

Let’s consider an upstream package hello-1.1.tar.gz and untar it to inspect files.

 $ tree
.
|-- hello-1.1
|   |-- hello.c
|   |-- hello.data
|   |-- hello-sh
|   `-- Makefile
`-- hello-1.1.tar.gz

1 directory, 5 files

This is similar to the previously shown hello-c-1.0.tar.gz but with a few additional files and changes.

The C source hello.c is the same one.

Makefile is updated to support $(DESTDIR) for all files.

 $ cat hello-1.1/Makefile
all: hello

hello: hello.c
        gcc -Wall -o hello hello.c

install: hello hello.data
        install -D hello $(DESTDIR)/usr/bin/hello
        install -D hello-sh $(DESTDIR)/usr/bin/hello-sh
        install -D hello.data $(DESTDIR)/usr/share/hello/hello.data

clean:
        -rm -f hello

distclean: clean

.PHONY: all install clean distclean

There is an additional simple shell script hello-sh.

 $ cat hello-1.1/hello-sh
#!/bin/sh
echo "Hello from the shell!"

The hello.data file is a dummy data for this training.

Let’s create a set of the following non-native binary Debian packages.

  • hello-c : type=bin, This package contains an ELF executable hello file compiled the source file hello.c.

  • hello-c-dbg : type=dbg, This package contains debug symbols data of the ELF executable file hello.

  • hello-sh : type=script, This contains the shell script hello-sh.

  • hello-data : type=data, This contains the data file hello.data.

Since we are splitting the generated files into multiple packages, we package this in two steps. The first step is the "debmake -j …" command.

The debmake execution (1st stage)
 $ cd hello-1.1
 ...
 ... (snip)
 ...
I: $ fakeroot dpkg-depcheck -b -f -catch-alternatives debian/rules insta...
I: $ find debian/tmp -type f 2>&1 | sed -e "s/^debian\/tmp\///" >../hell...
I: upon return to the shell, current directory becomes /path/to/hello-1....
I: please execute "cd /path/to/hello-1.1" before building the binary pac...
I: with dpkg-buildpackage (or debuild, pdebuild, sbuild, ...).
The parent directory after the "debmake -j …" execution.
 $ cd ..
 $ tree -L 1
.
|-- hello-1.1
|-- hello_1.1.orig.tar.gz -> hello-1.1.tar.gz
|-- hello-1.1.tar.gz
|-- hello.build-dep.log
`-- hello.install.log

1 directory, 4 files

There are 2 log files in the parent directory.

hello.build-dep.log generated by the dpkg-depcheck command
 $ cat hello.build-dep.log
 ...
 ... (snip)
 ...
Packages needed:
  perl-modules
  libgdbm3:amd64
  libfakeroot:amd64
  perl
  locales-all
  liblocale-gettext-perl
  dpkg-dev
  libtimedate-perl
  man-db
  libdpkg-perl
  debhelper
  libpipeline1:amd64
  locales

Since the buiid dependency to the debhelper package is always implemented by the debamke command and other packages are installed by the dependencies of the build-essential package, there is no additional package required be listed as the build dependency.

hello.install.log listing files under the debian/tmp directory
 $ cat hello.install.log
usr/bin/hello
usr/bin/hello-sh
usr/share/hello/hello.data

Now we know what files are generated in the debian/tmp directory.

Let’s start with the fresh source tree and build package from there.

The debmake execution (2nd stage)
 $ rm -rf hello-1.1
 $ debmake -b'-c,-c-dbg,-data:data,-sh:script' -a hello-1.1.tar.gz
I: set parameters
I: sanity check of parameters
I: pkg="hello", ver="1.1", rev="1"
 ...
I: parse binary package settings: -c,-c-dbg,-data:data,-sh:script
I: binary package=hello-c Type=bin / Arch=any M-A=foreign
I: binary package=hello-c-dbg Type=dbg / Arch=any M-A=same
I: binary package=hello-data Type=data / Arch=all M-A=foreign
I: binary package=hello-sh Type=script / Arch=all M-A=foreign
 ...
I: debmake -x "2" ...
 ...
I: $ wrap-and-sort
I: upon return to the shell, current directory becomes /path/to
I: please execute "cd /path/to/hello-1.1" before building the binary pac...
I: with dpkg-buildpackage (or debuild, pdebuild, sbuild, ...).

Please note that the debmake command is run with the -x2 option as the default for the new multi binary packages.

 $ cd hello-1.1
 $ tree
.
|-- debian
|   |-- changelog
|   |-- clean
|   |-- compat
|   |-- control
|   |-- copyright
|   |-- hello-c-dbg.install
|   |-- hello-c.doc-base
|   |-- hello-c.docs
|   |-- hello-c.examples
|   |-- hello-c.info
|   |-- hello-c.install
|   |-- hello-c.links
|   |-- hello-c.manpages
|   |-- hello-c.menu
|   |-- hello-c.postinst
|   |-- hello-c.postrm
|   |-- hello-c.preinst
|   |-- hello-c.prerm
|   |-- hello-data.install
|   |-- hello-sh.install
|   |-- patches
|   |   `-- series
|   |-- README.Debian
|   |-- rules
|   |-- source
|   |   |-- format
|   |   `-- local-options
|   `-- watch
|-- hello.c
|-- hello.data
|-- hello-sh
`-- Makefile

3 directories, 30 files

Let’s inspect generated template files.

debian/rules:
 $ cat debian/rules
#!/usr/bin/make -f
# See debhelper(7) (uncomment to enable)
# output every command that modifies files on the build system.
#DH_VERBOSE = 1

# harden via compile options
# see FEATURE AREAS in dpkg-buildflags(1))
#export DEB_BUILD_MAINT_OPTIONS = hardening=+all
# see ENVIRONMENT in dpkg-buildflags(1))
# package maintainers to append CFLAGS
#export DEB_CFLAGS_MAINT_APPEND  = -Wall -pedantic
# package maintainers to append LDFLAGS
#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed

# main packaging script based on dh7 syntax
%:
        dh $@

# debmake generated override targets
# save debug symbols to a single -dbg package
override_dh_strip:
        dh_strip --dbg-package=hello-c-dbg

This is essentialy the standard debian/rules file with the dh command with override_dh_strip to create a debug package. (There are some commented out contents for you to customize it.)

debian/control:
 $ cat debian/control
Source: hello
Section: unknown
Priority: extra
Maintainer: "Firstname Lastname" <email.address@example.org>
Build-Depends: debhelper (>=9)
Standards-Version: 3.9.5
Homepage: <insert the upstream URL, if relevant>

Package: hello-c
Architecture: any
Multi-Arch: foreign
Depends: ${misc:Depends}, ${shlibs:Depends}
Description: auto-generated package by debmake: bin
 This package contains the compiled binary executable.
 ...
 ... (snip)
 ...

Package: hello-c-dbg
Architecture: any
Multi-Arch: same
Depends: ${misc:Depends}
Description: auto-generated package by debmake: dbg
 This package contains the debugging symbols.

Package: hello-data
Architecture: all
Multi-Arch: foreign
Depends: ${misc:Depends}
Description: auto-generated package by debmake: data
 This package contains the architecture independent data.

Package: hello-sh
Architecture: all
Multi-Arch: foreign
Depends: ${misc:Depends}
Description: auto-generated package by debmake: script
 This package contains the script program.

Nice to see thse templates are generated with reasonable contents.

There are several template files under the debian/ directory. Let’s customize them and erase unnecessary ones. (Here, we are skipping details required by the best practice.)

Manual adjustments of debian/*
 $ cd ./debian
 $ rm -f *.do* *.examples *.info *.links *.m*  *.p*
 $ rm hello-c-dbg.install
 $ echo usr/bin/hello > hello-c.install
 $ echo usr/share/hello/hello.data > hello-data.install
 $ echo usr/bin/hello-sh > hello-sh.install

You can create a non-native Debian package using the debuild command (or its equivalents) in this source tree.

 $ cd ..
 $ debuild
 dpkg-buildpackage -rfakeroot -D -us -uc -I -i
 ...
dpkg-buildpackage: host architecture amd64
 fakeroot debian/rules clean
dh clean
 ...
 debian/rules build
dh build
 ...
 fakeroot debian/rules binary
dh binary
 ...
Finished running lintian.

Let’s inspect the result.

The generated files of version 1.0 by the debuild command:
 $ cd ..
 $ tree -L 1
.
|-- hello-1.1
|-- hello_1.1-1_amd64.build
|-- hello_1.1-1_amd64.changes
|-- hello_1.1-1.debian.tar.xz
|-- hello_1.1-1.dsc
|-- hello_1.1.orig.tar.gz -> hello-1.1.tar.gz
|-- hello-1.1.tar.gz
|-- hello.build-dep.log
|-- hello-c_1.1-1_amd64.deb
|-- hello-c-dbg_1.1-1_amd64.deb
|-- hello-data_1.1-1_all.deb
|-- hello.install.log
`-- hello-sh_1.1-1_all.deb

1 directory, 12 files
The source package contents of version 1.0:
 $ tar -tJf hello_1.1-1.debian.tar.xz
debian/
debian/compat
debian/clean
debian/changelog
debian/watch
debian/hello-sh.install
debian/hello-c.install
debian/control
debian/copyright
debian/README.Debian
debian/rules
debian/source/
debian/source/format
debian/patches/
debian/patches/series
debian/hello-data.install
 $ tar -tzf hello-1.1.tar.gz
hello-1.1/
hello-1.1/Makefile
hello-1.1/hello.data
hello-1.1/hello-sh
hello-1.1/hello.c
The binary package contents of version 1.0:
 $ dpkg -c hello-c_1.1-1_amd64.deb
drwxr-xr-x root/root ...  ./
drwxr-xr-x root/root ...  ./usr/
drwxr-xr-x root/root ...  ./usr/bin/
-rwxr-xr-x root/root ...  ./usr/bin/hello
drwxr-xr-x root/root ...  ./usr/share/
drwxr-xr-x root/root ...  ./usr/share/doc/
drwxr-xr-x root/root ...  ./usr/share/doc/hello-c/
-rw-r--r-- root/root ...  ./usr/share/doc/hello-c/copyright
-rw-r--r-- root/root ...  ./usr/share/doc/hello-c/README.Debian
-rw-r--r-- root/root ...  ./usr/share/doc/hello-c/changelog.Debian.gz
 $ dpkg -c hello-c-dbg_1.1-1_amd64.deb
drwxr-xr-x root/root ...  ./
drwxr-xr-x root/root ...  ./usr/
drwxr-xr-x root/root ...  ./usr/lib/
drwxr-xr-x root/root ...  ./usr/lib/debug/
drwxr-xr-x root/root ...  ./usr/lib/debug/.build-id/
drwxr-xr-x root/root ...  ./usr/lib/debug/.build-id/de/
-rw-r--r-- root/root ...  ./usr/lib/debug/.build-id/de/316ffc70f35adbe1d...
drwxr-xr-x root/root ...  ./usr/share/
drwxr-xr-x root/root ...  ./usr/share/doc/
drwxr-xr-x root/root ...  ./usr/share/doc/hello-c-dbg/
-rw-r--r-- root/root ...  ./usr/share/doc/hello-c-dbg/copyright
-rw-r--r-- root/root ...  ./usr/share/doc/hello-c-dbg/changelog.Debian.g...
 $ dpkg -c hello-data_1.1-1_all.deb
drwxr-xr-x root/root ...  ./
drwxr-xr-x root/root ...  ./usr/
drwxr-xr-x root/root ...  ./usr/share/
drwxr-xr-x root/root ...  ./usr/share/doc/
drwxr-xr-x root/root ...  ./usr/share/doc/hello-data/
-rw-r--r-- root/root ...  ./usr/share/doc/hello-data/copyright
-rw-r--r-- root/root ...  ./usr/share/doc/hello-data/changelog.Debian.gz...
drwxr-xr-x root/root ...  ./usr/share/hello/
-rwxr-xr-x root/root ...  ./usr/share/hello/hello.data
 $ dpkg -c hello-sh_1.1-1_all.deb
drwxr-xr-x root/root ...  ./
drwxr-xr-x root/root ...  ./usr/
drwxr-xr-x root/root ...  ./usr/bin/
-rwxr-xr-x root/root ...  ./usr/bin/hello-sh
drwxr-xr-x root/root ...  ./usr/share/
drwxr-xr-x root/root ...  ./usr/share/doc/
drwxr-xr-x root/root ...  ./usr/share/doc/hello-sh/
-rw-r--r-- root/root ...  ./usr/share/doc/hello-sh/copyright
-rw-r--r-- root/root ...  ./usr/share/doc/hello-sh/changelog.Debian.gz

Snapshot from VCS (1)

Let’s consider an upstream source in the VCS and make a snapshot package from it.

Let’s make this more fun to use the Autotools (=Autoconf + Automake) its build system. where the upstream VCS does not contain auto-generated files while the distributed tarball has many auto-generated files.

Let’s inspect files.

VCS source tree
 $ tree
.
`-- vcsdir
    |-- configure.ac
    |-- hello.c
    `-- Makefile.am

1 directory, 3 files

There are minimalistic configuration files for Autotools.

configure.ac:
 $ cat vcsdir/configure.ac
#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT([hello-c], [1.5], [foo@example.org])
AC_CONFIG_SRCDIR([hello.c])
AC_CONFIG_HEADERS([config.h])
# Manually added
AM_INIT_AUTOMAKE([foreign])
# Checks for programs.
AC_PROG_CC
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
Makefile.am:
 $ cat vcsdir/Makefile.am
bin_PROGRAMS = hello
hello_SOURCES = hello.c

The C source hello.c is the same one as before.

You create a non-native Debian package source tree from the above upstream example using the debmake(1) command.

git and debmake
 $ cd vcsdir
 $ git init
Initialized empty Git repository in /path/to/vcsdir/.git/
 $ git add .
 $ git commit -m "initial commit"
[master (root-commit) 455cd85] initial commit
 3 files changed, 21 insertions(+)
 create mode 100644 Makefile.am
 create mode 100644 configure.ac
 create mode 100644 hello.c
 $ git branch devel
 $ git branch upstream
 $ git branch
  devel
* master
  upstream
 $ debmake -p hello-c -u 1.5 -d
I: set parameters
I: sanity check of parameters
W: -p "hello-c" != auto set value ""
W: -u "1.5" != auto set value ""
I: pkg="hello-c", ver="1.5", rev="1"
I: make the upstream tarball with "make dist" equivalents
I: pwd = "/path/to/vcsdir"
I: $ autoreconf -ivf && ./configure --prefix "/usr" && make distcheck
 ...
I: debmake -x "1" ...
 ...
I: run "debmake -x2" to get more template files
I: $ wrap-and-sort
I: upon return to the shell, current directory becomes /path/to/vcsdir
I: please execute "cd /path/to/hello-c-1.5" before building the binary p...
I: with dpkg-buildpackage (or debuild, pdebuild, sbuild, ...).

Let’s clean vcsdir/ since it has so many Autotools generated files.

 $ git clean -d -f
Removing .deps/
Removing Makefile
Removing Makefile.in
Removing aclocal.m4
Removing autom4te.cache/
Removing compile
Removing config.h
Removing config.h.in
Removing config.log
Removing config.status
Removing configure
Removing depcomp
Removing hello-c-1.5.tar.gz
Removing install-sh
Removing missing
Removing stamp-h1

Let’s inspect files.

 $ cd ..
 $ tree
.
|-- hello-c-1.5
|   |-- aclocal.m4
|   |-- compile
|   |-- config.h.in
|   |-- configure
|   |-- configure.ac
|   |-- debian
|   |   |-- changelog
|   |   |-- compat
|   |   |-- control
|   |   |-- copyright
|   |   |-- patches
|   |   |   `-- series
|   |   |-- README.Debian
|   |   |-- rules
|   |   |-- source
|   |   |   |-- format
|   |   |   `-- local-options
|   |   `-- watch
|   |-- depcomp
|   |-- hello.c
|   |-- install-sh
|   |-- Makefile.am
|   |-- Makefile.in
|   `-- missing
|-- hello-c_1.5.orig.tar.gz -> hello-c-1.5.tar.gz
|-- hello-c-1.5.tar.gz
`-- vcsdir
    |-- configure.ac
    |-- hello.c
    `-- Makefile.am

5 directories, 26 files

There are many files:

  • the snapshot upstream tarball: hello-1.5.tar.gz (hello-c_1.5.orig.tar.gz)

  • the snapshot upstream source tree with template files generated by the debmake command: hello-c-1.5/*

  • the cleaned VCS directory: vcsdir/*

For the proper packaging, you are required to make further modification using these auto-generated template files in the hello-c-1.5/debian directory. For learning purpose, let’s leave such details and move on. You can create a non-native Debian package using the debuild command (or its equivalent) in this source tree.

 $ cd hello-c-1.5
 $ debuild
 dpkg-buildpackage -rfakeroot -D -us -uc -I -i
 ...
 fakeroot debian/rules clean
dh clean --with "autotools-dev"
 ...
 debian/rules build
dh build --with "autotools-dev"
 ...
 fakeroot debian/rules binary
dh binary --with "autotools-dev"
 ...
Finished running lintian.

Let’s inspect the result.

 $ cd ..
 $ tree -L 1
.
|-- hello-c-1.5
|-- hello-c_1.5-1_amd64.build
|-- hello-c_1.5-1_amd64.changes
|-- hello-c_1.5-1_amd64.deb
|-- hello-c_1.5-1.debian.tar.xz
|-- hello-c_1.5-1.dsc
|-- hello-c_1.5.orig.tar.gz -> hello-c-1.5.tar.gz
|-- hello-c-1.5.tar.gz
`-- vcsdir

2 directories, 7 files
 $ dpkg -c hello-c_1.5-1_amd64.deb
drwxr-xr-x root/root ...  ./
drwxr-xr-x root/root ...  ./usr/
drwxr-xr-x root/root ...  ./usr/bin/
-rwxr-xr-x root/root ...  ./usr/bin/hello
drwxr-xr-x root/root ...  ./usr/share/
drwxr-xr-x root/root ...  ./usr/share/doc/
drwxr-xr-x root/root ...  ./usr/share/doc/hello-c/
-rw-r--r-- root/root ...  ./usr/share/doc/hello-c/copyright
-rw-r--r-- root/root ...  ./usr/share/doc/hello-c/README.Debian
-rw-r--r-- root/root ...  ./usr/share/doc/hello-c/changelog.Debian.gz
 $ tar -tJf hello-c_1.5-1.debian.tar.xz
debian/
debian/compat
debian/changelog
debian/watch
debian/control
debian/copyright
debian/README.Debian
debian/rules
debian/source/
debian/source/format
debian/patches/
debian/patches/series
 $ tar -tzf hello-c-1.5.tar.gz
hello-c-1.5/
hello-c-1.5/install-sh
hello-c-1.5/aclocal.m4
hello-c-1.5/Makefile.am
hello-c-1.5/depcomp
hello-c-1.5/configure.ac
hello-c-1.5/config.h.in
hello-c-1.5/compile
hello-c-1.5/Makefile.in
hello-c-1.5/missing
hello-c-1.5/configure
hello-c-1.5/hello.c

Your development branch holding the real upstream source tree is the devel branch.

The following will import generated Debian packages to master, upstream, and pristine-tar branches.

 $ cd vcsdir
 $ git-import-dsc --color=no --pristine-tar ../hello-c_1.5-1.dsc
gbp:info: Tag upstream/1.5 not found, importing Upstream tarball
pristine-tar: committed hello-c_1.5.orig.tar.gz.delta to branch pristine...
gbp:info: Version '1.5-1' imported under 'hello-c'
 $ git branch
  devel
* master
  pristine-tar
  upstream
 $ gitk --all

See the history.

Snapshot from VCS (2)

Let’s consider another upstream source in the VCS and make a snapshot package from it. Let’s assume this is a Python3 source package in distutils.

Let’s inspect files.

 $ tree
.
`-- vcsdir
    |-- hello-py
    |   `-- __init__.py
    |-- MANIFEST
    |-- MANIFEST.in
    |-- PKG-INFO
    |-- scripts
    |   `-- hello
    `-- setup.py

3 directories, 6 files

There are minimalistic configuration files for Autotools.

setup.py:

 $ cat vcsdir/setup.py
#!/usr/bin/python3
# vi:se ts=4 sts=4 et ai:
from distutils.core import setup

setup(name='hello-py',
    version='1.0',
    description='Hello Python',
    long_description='Hello Python program.',
    author='Osamu Aoki',
    author_email='user@debian.org',
    url='http://people.debian.org/~user/',
    packages=['hello-py'],
    package_dir={'hello-py': 'hello-py'},
    scripts=['scripts/hello'],
    classifiers = ['Development Status :: 3 - Alpha',
        'Environment :: Console',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: MIT License',
        'Natural Language :: English',
        'Operating System :: POSIX :: Linux',
        'Programming Language :: Python :: 3',
        'Topic :: Utilities',
    ],
    platforms   = 'POSIX',
    license     = 'MIT License'
)

The Python program code is as follows.

 $ cat vcsdir/scripts/hello
#!/usr/bin/python3
# vim:se tw=0 sts=4 ts=4 et si:
"""
Copyright © 2014 Osamu Aoki

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"...
to deal in the Software without restriction, including without limitatio...
the rights to use, copy, modify, merge, publish, distribute, sublicense,...
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""

import hello-py

if __name__ == '__main__':
    hello.main()

 $ cat vcsdir/hello-py/__init__.py
#!/usr/bin/python3
# vim:se tw=0 sts=4 ts=4 et ai:

def main():
    print('Hello Python3!')
    return

if __name__ == '__main__':
    main()

You create a non-native Debian package source tree from the above upstream example using the debmake(1) command. Here package description is copied from the upstream setup.py content by the -s option.

 $ cd vcsdir
 $ git init
Initialized empty Git repository in /path/to/vcsdir/.git/
 $ git add .
 $ git commit -m "initial commit"
[master (root-commit) 525e40b] initial commit
 6 files changed, 93 insertions(+)
 create mode 100644 MANIFEST
 create mode 100644 MANIFEST.in
 create mode 100644 PKG-INFO
 create mode 100755 hello-py/__init__.py
 create mode 100755 scripts/hello
 create mode 100755 setup.py
 $ git branch devel
 $ git branch upstream
 $ git branch
  devel
* master
  upstream
 $ debmake -s -b':python3' -p hello-py -u 1.0 -d -i debuild
 ...
I: debmake -x "1" ...
 ...
Finished running lintian.
I: upon return to the shell, current directory becomes /path/to/vcsdir
I: please execute "cd .." and inspect the build results.
 $ git clean -d -f
Removing dist/

Let’s inspect the result.

 $ cd ..
 $ tree -L 1
.
|-- hello-py-1.0
|-- hello-py_1.0-1_all.deb
|-- hello-py_1.0-1_amd64.build
|-- hello-py_1.0-1_amd64.changes
|-- hello-py_1.0-1.debian.tar.xz
|-- hello-py_1.0-1.dsc
|-- hello-py_1.0.orig.tar.gz -> hello-py-1.0.tar.gz
|-- hello-py-1.0.tar.gz
`-- vcsdir

2 directories, 7 files
 $ dpkg -c hello-py_1.0-1_all.deb
drwxr-xr-x root/root ...  ./
drwxr-xr-x root/root ...  ./usr/
drwxr-xr-x root/root ...  ./usr/lib/
drwxr-xr-x root/root ...  ./usr/lib/python3/
drwxr-xr-x root/root ...  ./usr/lib/python3/dist-packages/
-rw-r--r-- root/root ...  ./usr/lib/python3/dist-packages/hello_py-1.0.e...
drwxr-xr-x root/root ...  ./usr/lib/python3/dist-packages/hello-py/
-rw-r--r-- root/root ...  ./usr/lib/python3/dist-packages/hello-py/__ini...
drwxr-xr-x root/root ...  ./usr/bin/
-rwxr-xr-x root/root ...  ./usr/bin/hello
drwxr-xr-x root/root ...  ./usr/share/
drwxr-xr-x root/root ...  ./usr/share/doc/
drwxr-xr-x root/root ...  ./usr/share/doc/hello-py/
-rw-r--r-- root/root ...  ./usr/share/doc/hello-py/copyright
-rw-r--r-- root/root ...  ./usr/share/doc/hello-py/README.Debian
-rw-r--r-- root/root ...  ./usr/share/doc/hello-py/changelog.Debian.gz
 $ tar -tJf hello-py_1.0-1.debian.tar.xz
debian/
debian/compat
debian/changelog
debian/watch
debian/control
debian/copyright
debian/README.Debian
debian/rules
debian/source/
debian/source/format
debian/patches/
debian/patches/series
 $ tar -tzf hello-py-1.0.tar.gz
hello-py-1.0/
hello-py-1.0/hello-py/
hello-py-1.0/hello-py/__init__.py
hello-py-1.0/scripts/
hello-py-1.0/scripts/hello
hello-py-1.0/MANIFEST.in
hello-py-1.0/PKG-INFO
hello-py-1.0/setup.py
hello-py-1.0/MANIFEST

Let’s check the generated control file content.

 $ dpkg -e hello-py_1.0-1_all.deb
 $ tree DEBIAN
DEBIAN
|-- control
|-- md5sums
|-- postinst
`-- prerm

0 directories, 4 files

Let’s compare how packaging deals with substvar etc.

debian/control in the source package
 $ cat hello-py-1.0/debian/control
Source: hello-py
Section: unknown
Priority: extra
Maintainer: "Firstname Lastname" <email.address@example.org>
Build-Depends: debhelper (>=9), python3-all
Standards-Version: 3.9.5
Homepage: <insert the upstream URL, if relevant>
X-Python3-Version: >= 3.2

Package: hello-py
Architecture: all
Multi-Arch: foreign
Depends: python3, ${misc:Depends}, ${python3:Depends}
Description: Hello Python
 Hello Python program.
DEBIAN/control in the binary package
 $ cat DEBIAN/control
Package: hello-py
Version: 1.0-1
Architecture: all
Maintainer: "Firstname Lastname" <email.address@example.org>
Installed-Size: 50
Depends: python3, python3:any (>= 3.3.2-2~)
Section: unknown
Priority: extra
Multi-Arch: foreign
Homepage: <insert the upstream URL, if relevant>
Description: Hello Python
 Hello Python program.

Appendix

The debmake(1) manpage

NAME

debmake - program to make the Debian source package

SYNOPSIS

debmake [-h] [-c] [-n | -a package-version.orig.tar.gz | -d | -t ] [-p package] [-u version] [-r revision] [-z extension] [-b "binarypackage, …]" [-e foo@example.org] [-f "firstname lastname"] [-i "buildtool" | -j] [-l license_file] [-m] [-o file] [-q] [-s] [-v] [-w "addon, …"] [-x [01234]] [-y]

DESCRIPTION

debmake helps to build the Debian package from the upstream source. Normally, this is done as follows:

  • The upstream tarball is downloaded as the package-version.tar.gz file.

  • It is untared to create many files under the package-version/ directory.

  • debmake is invoked in the package-version/ directory possibly without any arguments.

  • Files in the package-version/debian/ directory are manually adjusted.

  • dpkg-buildpackage (usually from its wrapper debuild or pdebuild) is invoked in the package-version/ directory to make debian packages.

Make sure to protect the arguments of the -b, -f, -n, and -w options from the shell interference by quoting them properly.

optional arguments:
-h, --help

show this help message and exit.

-c, --copyright

scan source for copyright+license text and exit.

-n, --native

make a native Debian source package without .orig.tar.gz. This makes the "3.0 (native)" format package.

If you are thinking to package a Debian specific source tree with debian/* in it into a native Debian package, please think otherwise. You can use "debmake -d -i debuild" or "debmake -t -i debuild" to make the "3.0 (quilt)" format non-native Debian package. The only difference is that the debian/changelog file must use the non-native version scheme: version-revision. The non-native package is more friendly to the downstream distributions.

-a package-version.tar.gz, --archive package-version.tar.gz

use the upstream source tarball directly. (-p, -u, -z: overridden)

The upstream tarball may be specified as package_version.orig.tar.gz and tar.gz for all cases may be tar.bz2, or tar.xz.

If the specified upstream tarball name contains uppercase letters, the Debian package name is generated by converting them to lowercase letters.

If the specified argument is the URL (http://, https://, or ftp://) to the upstream tarball, the upstream tarball is downloaded from the URL using wget or curl.

-d, --dist

run "make dist" equivalent first to generate upstream tarball and use it.

"debmake -d" is designed to run in the package/ directory hosting the upstream VCS with the build system supporting "make dist" equivalents. (automake/autoconf, Python distutils, …)

-t, --tar

run "tar" to generate upstream tarball and use it

"debmake -t" is designed to run in the package/ directory hosting the upstream VCS. Unless there is the debian/changelog file, you need to provide the upstream version with the -u option. The generated tarball excludes the debian/ directory. (It also excludes typical VCS directories: .git/ .hg/ .svn/ .CVS/)

-p package, --package package

set the Debian package name.

-u version, --upstreamversion version

set the upstream package version.

-r revision, --revision revision

set the Debian package revision.

-z extension, --targz extension

set the tarball type, extension=(tar.gz|tar.bz2|tar.xz) (alias: z, b, x)

-b "binarypackage,…", --binaryspec "binarypackage,…"

set binary package specs as comma separated list of binarypackage:'type' pairs, e.g., in full form "foo:bin,foo-doc:doc,libfoo1:lib,libfoo1-dbg:dbg,libfoo-dev:dev" or in short form ",-doc,libfoo1,libfoo1-dbg, libfoo-dev".

Here, binarypackage is the binary package name; and optional type is chosen from the following type values:

  • bin: C/C++ compiled ELF binary code package (any, foreign) (default, alias: "", i.e., null-string)

  • data: Data (fonts, graphics, …) package (all, foreign) (alias: da)

  • dbg: Debug symbol package (any, same) (alias: db)

  • dev: Library development package (any, same) (alias: de)

  • doc: Documentation package (all, foreign) (alias: do)

  • lib: Library package (any, same) (alias: l)

  • perl: Perl script package (all, foreign) (alias: pl)

  • python: Python script package (all, foreign) (alias: py)

  • python3: Python3 script package (all, foreign) (alias: py3)

  • ruby: Ruby script package (all, foreign) (alias: rb)

  • script: Shell script package (all, foreign) (alias: sh)

The pair values in the parentheses, such as (any, foreign), are the Architecture and Multi-Arch stanza values set in the debian/control file.

In many cases, the debmake command makes good guess for type from binarypackage. If type is not obvious, type is set to bin. For example, libfoo sets type to lib, and font-bar sets type to data, …

If the source tree contents does not match settings for type, debmake warns you.

-e foo@example.org, --email foo@example.org

set e-mail address.

The default is taken from the value of the environment variable $DEBEMAIL.

-f "firstname lastname", --fullname "firstname lastname"

set the fullname.

The default is taken from the value of the environment variable $DEBFULLNAME.

-i "buildtool", --invoke "buildtool"

invoke "buildtool" at the end of execution. "buildtool" may be "dpkg-buildpackage", "debuild", "pdebuild", "pdebuild --pbuilder cowbuilder", etc..

The default is not to execute any program.

-j, --judge

run dpkg-depcheck to judge build dependencies and identify file paths. Log files are in the parent directory.

  • package.build-dep.log: Log file for dpkg-depcheck.

  • package.install.log: Log file recording files in the debian/tmp directory.

-l license_file,…, --license license_file,…

add formatted license text to the end of the debian/copyright file holding license scan results

The default is add COPYING and LICENSE and license_file needs to list only the additional file names all separated by ",".

-m, --monoarch

force packages to be non-multiarch.

-o file, --option file

read optional parameters from file. (This is not for everyday use.)

The file is sourced as the Python3 code at the end of para.py. For example, the package description can be specified by the following file.

para['desc'] = 'program short description'
para['desc_long'] = '''\
 program long description which you wish to include.
 .
 Empty line is space + .
 You keep going on ...
'''
-q, --quitearly

quit early before creating files in the debian/ directory.

-s, --spec

use upstream spec (setup.py for Python, etc.) for the package description.

-v, --version

show version information.

-w "addon,…", --with "addon,…"

add extra arguments to the --with option of the dh(1) command as addon in debian/rules.

addon values are listed all separated by ",", e.g., -w "python2,autoreconf".

For Autotools based packages, setting autoreconf as addon forces to run "autoreconf -i -v -f" for every package building. Otherwise, autotools-dev as addon is used as default.

For Autotools based packages, if they install Python programs, python2 as addon is needed for packages with compat < 9 since this is non-obvious. But for setup.py based packages, python2 as addon is not needed since this is obvious and it is automatically set for the dh(1) command by the debmake command when it is required.

-x n, --extra n

generate extra configuration files as templates.

The number n changes which configuration templates are generated.

  • -x0: bare minimum configuration files. (default if these files exist already)

  • -x1: ,, + desirable configuration files. (default for new packages)

  • -x2: ,, + interesting configuration files. (recommended for experts, multi binary aware)

  • -x3: ,, + unusual configuration template files with the extra .ex suffix to ease their removal. (recommended for new users) To use these as configuration files, rename their file names into ones without the .ex suffix.

  • -x4: ,, + copyright file examples.

    -y, --yes

    force "yes" for all prompts. (without option: "ask [Y/n]"; doubled option: force "no")

EXAMPLES

For a well behaving source, you can build a good-for-local-use installable single Debian binary package easily with one command. Test install of such a package generated in this way offers a good alternative to traditional "make install" to the /usr/local directory since the Debian package can be removed cleanly by the "dpkg -P " command. Here are some examples of how to build such test packages. (These should work in most cases. If the -d does not work, try -t instead.)

For a typical C program source tree packaged with autoconf/automake:

  • debmake -d -i debuild

For a typical python module source tree:

  • debmake -d -b":python" -i debuild

For a typical python module in the package-version.tar.gz archive:

  • debmake -a package-version.tar.gz -b":python" -i debuild

For a typical perl module in the Package-version.tar.gz archive:

  • debmake -a Package-version.tar.gz -b":perl" -i debuild

HELPER PACKAGES

Packaging may require installation of some additional speciality helper packages.

  • Python3 program may require the dh-python package.

  • Autotools (Autoconf + Automake) build system may require autotools-dev or dh-autoreconf package.

  • Ruby program may require the gem2deb package.

  • Java program may require the javahelper package.

  • Gnome programs may require the gobject-introspection package.

  • etc.

CAVEAT

There are some limitations for what characters may be used as a part of the Debian package. The most notable limitation is the prohibition of uppercase letters in the package name. Here is the summary in the regular expression.

  • Upstream package name (-p): [-+.a-z0-9]{2,}

  • Binary package name (-b): [-+.a-z0-9]{2,}

  • Upstream version (-u): [0-9][-+.:~a-z0-9A-Z]*

  • Debian revision (-r): [0-9][+.~a-z0-9A-Z]*

See the exact definition in “5.6.1 Source”, “5.6.7 Package”, and “5.6.12 Version” of “Debian Policy Manual”. (http://www.debian.org/doc/debian-policy/ch-controlfields.html)

DEBUG

The character set in the environ variable $DEBUG determines the logging output level.

  • p: list all parameters

  • d: list all binary package parameters

  • f: copyright scanner input filename

  • i: copyright scanner input line

  • o: line outside of the copyright and license sections

  • c: line inside of the copyright section

  • l: line inside of the license section

AUTHOR

Copyright © 2013 Osamu Aoki <osamu@debian.org>

LICENSE

MIT License

SEE ALSO

See also debhelper(7), dpkg-buildpackage(1) debuild(1) and pdebuild(1) manpages and files in /usr/share/doc/debmake/.

Learn basics of Debian packaging with the “Debian New Maintainers' Guide” at http://www.debian.org/doc/manuals/maint-guide/ or with the maint-guide package.