pkgwrite - Make RedHat and Debian packages from the same source.


 pkgwrite  (--tarball=TARBALL | --srcdir=SRCDIR) \
          [--pkgwriteinfo-file=pkgwriteinfo] \
          --arch=ARCH \
 pkgwrite --query-list=LISTNAME


pkgwrite takes a standard automake package, either from a source directory or from a distributed tarball, and a pkgwrite input file and makes either RedHat or Debian packages.

The actual package source code must be specified either by directory (using --srcdir) or from a tarball created with `make dist' (using --tarball).

Additional packaging information is taken from pkgwriteinfo. If --pkgwriteinfo-file is omitted, pkgwriteinfo from the source directory or tarball is taken instead. (after configure is run, so you might generally use a

There are a few command-line parameters which affect the package-making:

Don't force the user's changelog and pkgwriteinfo file to have the same version. (If the packaging system requires that the changelog's latest entry be equal to the package's version, then pkgwrite will generate a changelog entry. This happens under Debian.)

Don't remove the temporary directory (which will be /tmp/mkpkg-###-$USER). Useful for debugging.

Generate packaging for the given debian distribution: this mostly affects the changelog so setting DIST to stable or unstable is recommended.

Disable the usual checks that the package is valid. The package may still partially work, even if a sanity-check would normally fail.


A family of packages for various distributions which all come from one tarball and one pkgwriteinfo file.

A compilation of the source code into binaries. Some packages require multiple builds, for example, to make debugging and nondebugging versions of a libraries. Normally you just use the {MAIN} build.

A single set of installed files in a package. Simple packages only have a single target {MAIN} because the package is an all-or-nothing proposition.

Some packages contain many parts, not all applicable to all users. These packages should be broken in to different targets.

For example, a client/server based application might be conveniently packaged foo-server, foo-client-curses, foo-client-gtk. That way, users without X can use the curses version without installing gtk+, often the clients and servers are run exclusively on different machines, so installing both is a waste of disk space.

The resulting system-dependent binary's name is just the main Package: name if the Target: is {MAIN}; otherwise it will be the Package and Target separated by a hyphen (-).


We recommend that you maintain a changelog in debian format, here is an example:

 gdam (0.934-1) unstable; urgency=low
   * many bug fixes
   * split into many packages
  -- David Benson <>  Wed, 17 Jan 2000 13:09:36 -0800

(No spaces for each version banner; 2 spaces on each bullet; 1 space before the packager byline.)

If you don't maintain a changelog, we will generate a changelog with just this version of the package in it.

You should specify the changelog using the Changelog: directive.


Here are a few examples of common types of packages. The pkgwrite distribution includes these packages inside the examples/tiny directory.


The most common type of package has one set of files it installs or uninstalls: there are no packaged bits or pieces. (A Target in pkgwrite terminology is the installed set of files.)

Here is the pkgwrite file from the single-target example included with the pkgwrite distribution:

  Package: aa
  Section: text
  Group: Applications/Text
  Priority: low
  Home-Page: NONE
  Source-Url: NONE
  Author: David Benson <>
  Version: 0.0.8
  Release: 1
  Synopsis: test package aa
  Packager: daveb
  License: NONE
  Description: test package (aa).
  Build: {MAIN}
  Target: {MAIN}
  Files: /usr/bin/dummy-*
  Synopsis: test a (single-target package)

This package's name is aa; this file will produce a binary RPM named aa-0.0-1.$ARCH.rpm.


A multi-target, single-build package is a package that need only be compiled once, but which must be separated into several system packages, because the targets appeal to different users or have different dependencies.

Here is the pkgwriteinfo file from the example multi-target single-build package:

  Package: bb
  Section: text
  Group: Applications/Text
  Priority: low
  Home-Page: NONE
  Source-Url: NONE
  Author: David Benson <>
  Version: 0.0
  Release: 1
  Synopsis: test package bb
  Packager: daveb
  License: NONE
  Description: test package (bb).
  Build: {MAIN}
  Target: a
  Files: /usr/bin/bb-a
  Synopsis: part a of package bb
  Description: whatever (bb-a)
  Target: b
  Files: /usr/bin/bb-b
  Synopsis: part b of package bb
  Description: whatever (bb-b)

In this package, only a single default Build: is required. Some packages may require the Configure-Flags or Configure-Envars fields in order to compile correctly.

By default, all the targets use the {MAIN} Build.

Then each package contains a default file list, a description and a synopsis.


The most complex type of package must be built multiple times, with different configure or make flags. Each target must then refer to the build from which it was produced, using the Which-Build field (the default is {MAIN}).

Here is the example of such a package from the pkgwrite distribution:

  Package: cc
  Section: text
  Group: Applications/Text
  Priority: low
  Home-Page: NONE
  Source-Url: NONE
  Author: David Benson <>
  Version: 0.0
  Release: 1
  Synopsis: test package cc
  Packager: daveb
  License: NONE
  Description: test package (cc).
  Build: nond
  Configure-Flags: --program-suffix=-nondebug
  Build: d
  Configure-Flags: --program-suffix=-debug
  Target: nondebug
  Which-Build: nond
  Files: /usr/bin/test-nondebug
  Synopsis: nondebug package cc
  Description: whatever (cc-nondebug)
  Target: debug
  Which-Build: d
  Files: /usr/bin/test-debug
  Synopsis: debug package cc
  Description: whatever (cc-debug)

Each Build section corresponds to a complete configure, build, install phase. In this package, the nond build just wants configure to be run configure --program-suffix=-nondebug ... whereas for the d build, configure --program-suffix=-debug ... (Note that the ... will be somewhat different from distribution to distribution)

Also, it is often convenient to use the same names for the builds and the targets. We would rename nond as nondebug and d as debug if this were a real package -- we did this to discuss it more conveniently.

It is perfectly possible to have more than one Target pointing to the same Build, just as multi-target single-build packages do. But the opposite is not allowed: a Target must specify exactly one Build.


Many lists and values are hardcoded into pkgwrite. You may query these lists through the --query-list flag. Here are the lists you may obtain in this manner:

Known allowed Section: fields for debian packages.

Known allowed Group: fields for redhat packages.

Known allowed Priority: fields for debian packages.

For example to get a list of allowed values for the Section: field, use pkgwrite --query-list=deb-sections.

PKGWRITE'S pkgwriteinfo FORMAT

This (long) section describes the file that describes the targets to build from a tarball. This description file is called a pkgwriteinfo file.

The pkgwriteinfo file consists of one package description part, then a number of Build sections, then a number of Target sections.


The package file should begin with a section that describes the overall source code of the package:

   Package: gdam
   Section: sound
   Group: Multimedia/Sound
   Priority: optional
   Version: 0.0.930
   Release: 1
   Author: David Benson <>

Here is a description of each allowed field:

Name of the source package.

Sometimes, all packages from a tarball use a somewhat different name than the tarball itself. This is used as a bit of a hack to support co-installation of multiple versions of a package. This is like gtk, which has gtk1.2 and gtk2.0 packages, which can be installed concurrently.

The version number given to this version of the package by its maintainer.

Increment this each time a new package is released without a corresponding upstream version-number change.

The debian section this package belongs in.

The redhat group this package belongs in.

Priority of this package (debian-style).

A URL giving the home page for this package or project.

A URL describing how to download this package.

An author of this package, with email optional.

Under one line summary of this target.

Multiple-line description of this target.

Full name of the person who made this packaging.

Email address at which to reach the packager.

Specify the location of a Debian format changelog to include with the package (it will be converted to another standard format, if needed)

Whether the packager (the person running pkgwrite) is the same as the upstream maintainer of a package.

Right now, this only affects the filename used for the changelog, it will either be changelog.gz if they are the same person, or changelog.Debian.gz if they are not.


For each output binary package there must be a ``target'' section:

  Target: xmms-plugins
  Depends: gdam-clients-gtk, gdam-server, xmms
  Synopsis: GDAM XMMS plugin support
  Description: use XMMS visualization plugins with GDAM.
  Files: /usr/bin/gdamxmmsvishelper
Name of this target. The name of the package that results will be prepended with SOURCE-; in this example the package's name is gdam-xmms-plugins.

Set this to yes if this package will be installable on any architecture (it contains no system-specific or compiled code).

Set this to no for packages containing compiled, architecture-specific binaries.

Debian-formatted dependency lists for this package.

Specify the redhat packages that this one depends on. (We will try to compute this from the Depends: lines by default; this is just in case we cannot guess correctly.)

Debian-formatted list of packages that conflict with this one.

Redhat-formatted list of packages that conflict with this one. Computed from Conflicts: by default.

Under one line summary of this target.

The basename of a man page, for example pkgwrite.1. It will automatically be installed into the correct section directory based on its extension.

Miscellaneous documentation. Each path is assumed to be inside the installed area.

It will be always be copied into the distribution's documentation area, and it will be gzip'd if that is needed. Also, whole directories will be recursively copied, if the entry ends with a /, for example,

   Doc: /usr/share/doc/gdam/example-configs/

Miscellaneous documentation that is not normally installed by this package's makefile:

These must be files directly from the distributed tarball. They will be always be copied into the distribution's documentation area and will be gzip'd if that is needed. Whole directories will be recursively copied, if the entry ends with a /.

Multiple-line description of this target.

Name of the build whose files should be used. (Defaults to {MAIN}).

A wildcard matching ordinary files to be distributed with this target.


The name of this build. The default build should be named {MAIN}.

Options to be passed to the configure script.

Space-separated environment variables to add when configuring.

Extra parameters to the make program during both the build and the install phase.

Extra parameters to the make program during just the build phase.

Extra parameters to the make program during just the install phase.

Another make target that is necessary to build the package, that is not run by the default target. This must not require root priviledges. (You may specify any number of Extra-Build-Targets: lines.)

Another make target that is necessary to install the package, that is not run by the default target. On Debian systems, these commands may require root or fakeroot. (You may specify any number of Extra-Install-Targets: lines.)


If you have problems, here are some hints:


Here are some trivial mistakes made often:


Of course, you can and should work however you want, but for your information, I will write the testing process I use for releasing packages.

I always make automake packages that use pkgwriteinfo inside the tarball.

It is important to note that my packages always support make rpm and make deb using pkgwrite, and that these targets only make dist if the tarball isn't present!

  1. Check out the package from CVS. Then either use whichever bootstrap script is provided: my recent packages use bootstrap (as recommended by the automake authors), but many packages use ./, which traditionally also runs ./configure.

    If you used bootstrap, you will need to run ./configure.

    Then make the tarball using make distcheck.

  2. On a RedHat machine and a Debian machine, untar the tarball and copy that same tarball into the PACKAGE-VERSION directory that was created. (This way, the exact same tarball will be reused).

  3. On each system, run ./configure, then make rpm and make deb, respectively.

  4. Copy all the returned packages, the dist tarball, into a directory which you will upload.

  5. Test install those packages on machines.

    I also inspect them with the following commands:

             System|     RedHat                        Debian
     Action        |
     List of files | rpm -qpl *.rpm               dpkg-deb -c *.deb
     General data  | rpm -qpi *.rpm               dpkg-deb -e *.deb




Written by Dave Benson <>.