While there are plenty of guides available on how to write good code for Unix-like operating systems, there's not a lot of information out there about how to package it up for other people to use. This page lists some of the things you should think about when distributing source code for other people to install and produce binary packages from.
(One document I did find was the GNU Coding Standards which contains a section on The Release Process, which is also worth reading if you're interested in this sort of thing.)
I've tried to make the advice here as general as possible, but there's an inevitable slant towards the things I've discovered while packaging software for GARStow. If you're aware of anything I've missed, please let me know.
The most important thing I've got to say here: please, please, don't roll your own custom configuration system. Use GNU autoconf and automake instead. Yes, they're awkward for many things, but they make life very easy for packagers when used correctly. If you're not using automake, then it's very tricky to get everything below correct unless your program is absolutely trivial (and if it's trivial, then it'd be very easy to write an automake config for).
The exception is for add-on modules for programming languages where there's an existing packaging system that's widely-used: for Perl use CPAN, for Python use distutils, and so on.
Be very cautious about systems that have been designed to replace automake; all that I've encountered have been very convenient for developers, but cause problems for end users and packagers (for example, assuming standard locations for files, or not allowing environment variables to be passed to compilers, or not supporting installation staging). If you really have to use something other than automake, then make certain that it's actually possible to use it to install the software and produce packages.
Don't interleave building and installation steps; construct your build system so that the entire package is configured and built, and then the entire package is installed. Installation should not touch the source directory at all, nor should configuration or building touch the destination directories; it's recommended practice to compile software as a non-privileged user and install as root.
If you're installing a shared library, also install a pkg-config file; this makes detecting and using the library in other packages easier and more reliable. (The uptake of pkg-config has been surprisingly rapid among libraries; even X uses it these days.)
Do not do interactive configuration by default; it's important that package builds should be automatable. If you want an interactive configuration system, then do as the Linux kernel and busybox do, and make it generate a config file that can be machine-edited and stored by packagers.
Check the output from
./configure --help to make sure
that all the options are listed, and that the defaults are sensible and
Don't hardcode paths into your source code; make them an option at configuration time. If your program automatically detects where its binary is, make sure it doesn't break in the presence of something like stow (i.e. that it isn't overly enthusiastic about following symlinks -- Python has this problem).
If you've written test cases for your code, then make them available
make check, in order to reassure users that the
executables they've just built work.
The tests should run to completion and exit 0 if they succeed; if any
of them fail,
make check must exit non-zero.
Don't rely on users inspecting the output to check the tests passed!
Follow the GNU standards for how
prefix and the related
variables work. In particular, note that
bindir and similar
variables should default to depending on
install time; don't set
bindir to a fixed path at
configure time (unless the user's explicitly specified one). Don't make
up your own names for the variables (some packages use
PREFIX or, worse,
DESTDIR to mean the same
DESTDIR. This is much more convenient for some
packaging systems, so people building RPMs or Debian packages will find
their jobs rather easier if you support it.
Don't assume that installation paths exist; use
-p to make
bindir etc. before you try installing
files into them. (This applies even if your build depends on a
directory existing -- remember that the prefix you install into may be
different from the one you had at build time.)
Don't assume you can edit or replace existing files and directories in your installation prefix, since at install time it might just be a staging directory. This means that each file should only be provided by one source package. If you want several packages to provide data for another program, have them write to different files in a shared directory (which is the approach taken by pkg-config, among others).
Similarly, don't assume that you can check for the existence of files in your installation prefix at install time.
Don't install things in a directory that you haven't been told about.
I don't necessarily want config files installed in
particularly if I'm not root.
Don't explicitly set ownership of installed files unless they're suid -- you don't know what the administrator's conventions for file ownership are. If you're installing suid stuff, add a configure-time option not to do so, for people who're installing your software without being root.
If your program is named
gnomovision and it's at
version 3.4, then your distribution tarball should be named
.bz2) and it should
contain a single directory called
gnomovision-3.4. If you
release a bug-fix version, make sure the directory name is changed to
match the tarball name. If you release patch files, generate them with
diff -Naur old-version new-version, so they can be applied
Use GPG to sign your distribution files. Provide a detached
signature file, named the same as the matching distribution file plus
-a your-file will do the right thing).
Document your package's dependencies somewhere -- such as the
download web page for your project, or the
INSTALL file in
the distribution. If you're depending on another package that's uncommon
or otherwise hard to search for, give the URL where it can be
Make certain that your package actually contains all the files
necessary to build it. It's easy to leave out a source file by accident,
configure.ac before release and forget to
configure (which, unless you've used
AM_MAINTAINER_MODE, will produce interesting errors for
users who don't have the same version of autoconf as you), or to forget
to clean out version control or object files from your tree.
Make your version control repository public (or at least provide daily snapshots), and make sure you check changes into it before you release a tarball. If a user finds a bug in your package, it's useful to be able to check the repository first to see if it's already been fixed.
Finally, make sure that you try out your package on a different machine from the one you developed it on -- ideally one without much extra stuff installed -- and make sure it works before you release it!