swpkg - Software Packaging

Philosophy

Table of contents

Site Map
News
Overview
Philosophy
Building Software
Docs
Maintenance
Download

Related Work
Other Projects


History

The concept of installing additional software on a system under /usr/local is (relatively) old. Typically, the hierarchy found under /usr/local replicates the one found under /usr where most of the base system is installed. This can get confusing, as conventions have changed with time. For example, under SunOS (e.g. in the pre Solaris days), binaries were often located under the "etc" directory, something that many people now regard as wrong or even evil. Also, while a particular vendor has complete control of its system, third party software comes in various forms and shapes, following what sometimes feels like random conventions. And this actually brings us to the problem with the usual /usr/local approach: it is not centrally controlled nor managed. Not only this, but most vendors have software package tools aimed and managing the installation, updates, removal, and dependencies between the different software components they ship. They have a fairly easy job, as they have complete control over things.

Of course, each vendor uses their own proprietary package tools, so if it would be a real headache for software maintainers to ship their product for multiple OS flavors as they'd need to understand and master all of these tools, not to mention the fact that third party software is most often distributed in source form, not binary form ready to be installed and used.

Because of the lack of management, it is often difficult to upgrade or remove a particular software, meaning that /usr/local is almost never cleaned up, and piles up. It is also practically impossible to know or understand the many dependencies existing between different packages.

Finally, as there are now thousands of freely available software applications available out there, and almost as many maintainers, it is highly unlikely for any package management tool to ever become universaly used. In other words, any system we develop should assume as little as possible and work with software as installed following the maintainer's specifications.

Design requirements and goals

The "swpkg philosophy" was born several years ago and first implemented in an early form at Bell Laboratories. Although it has kept evolving, little has changed. The management tools part of the swpkg were written with the following requirements in mind:

Also, these are the goals swpkg aims to solve:

In particular one should note that swpkg makes no attempt to address the distribution of installed software packages across systems. It is believed that that by keeping the swpkg tools simple and flexible, it will be possible to build a distribution mechanism on top of it.


The basics

To avoid the chaos which is inherant to installing many very different software packages under the same subtree, a simple solution is used: each software package is installed under its very own directory. (You're probably familiar with "GNU configure" scripts, this amounts to using the "--prefix" option.) This directory is named after the software and its version.

To keep this transparent to users, symbolic links are used to populate a common directory. The subtree located in this directory is what gets used and referenced to access the installed software.

All packages should be installed under a common directory called the source directory, and the directory under which symbolic links are created is called the target directory. These default to /usr/local/pkgs and /usr/local, respectively.

Here's an example of what one may find under a source directory:

drwxr-sr-x   6 swpkg    swpkg        512 Jun  4 08:57 amanda-2.4.2p2
drwxr-sr-x   6 swpkg    swpkg        512 Mar 27  2001 apache-1.3.12
drwxr-sr-x  10 swpkg    swpkg        512 Aug 15 09:51 bind-9.1.3
drwxr-sr-x   6 swpkg    swpkg        512 Sep 25  2000 bzip2-1.0.1
drwxr-sr-x   7 swpkg    swpkg        512 Feb 13  2001 clearcase-4.0
drwxr-sr-x   8 swpkg    swpkg        512 Dec 12  2000 gcc-2.95.2
drwxr-sr-x   6 swpkg    swpkg        512 Sep 26  2000 gdb-5.0
drwxr-sr-x   3 swpkg    swpkg        512 Jul 25  2000 memconf-1.69
drwxr-sr-x   8 swpkg    swpkg        512 Aug  2 17:26 net-snmp-4.2.1
drwxr-sr-x   5 swpkg    swpkg        512 Jan 13  2000 perl-5.005_03
drwxr-sr-x   4 swpkg    swpkg        512 Jan 21  2001 rsync-2.4.6
drwxr-sr-x   4 swpkg    swpkg        512 Apr 11  2000 screen-3.9.4
drwxr-sr-x   7 swpkg    swpkg        512 Sep 20 11:22 tar-1.13.23
And here is how the bzip2-1.0.1 package appears to users:
drwxrwsr-x   2 swpkg    swpkg       9728 Sep  1 08:00 /usr/local/bin
lrwxrwxrwx   1 swpkg    swpkg         39 Jun 20 13:59 /usr/local/bin/bunzip2
                                                      -> /usr/local/pkgs/bzip2-1.0.1/bin/bunzip2
lrwxrwxrwx   1 swpkg    swpkg         37 Jun 20 13:59 /usr/local/bin/bzcat
                                                      -> /usr/local/pkgs/bzip2-1.0.1/bin/bzcat
lrwxrwxrwx   1 swpkg    swpkg         37 Jun 20 13:59 /usr/local/bin/bzip2
                                                      -> /usr/local/pkgs/bzip2-1.0.1/bin/bzip2
lrwxrwxrwx   1 swpkg    swpkg         44 Jun 20 13:59 /usr/local/bin/bzip2recover
                                                      -> /usr/local/pkgs/bzip2-1.0.1/bin/bzip2recover
drwxrwsr-x  10 swpkg    swpkg       1024 Aug 20 16:31 /usr/local/include
lrwxrwxrwx   1 swpkg    swpkg         43 Jun 20 13:59 /usr/local/include/bzlib.h
                                                      -> /usr/local/pkgs/bzip2-1.0.1/include/bzlib.h
drwxrwsr-x  29 swpkg    swpkg       3072 Aug 20 16:31 /usr/local/lib
lrwxrwxrwx   1 swpkg    swpkg         40 Jun 20 14:04 /usr/local/lib/libbz2.a
                                                      -> /usr/local/pkgs/bzip2-1.0.1/lib/libbz2.a
drwxrwsr-x  15 swpkg    swpkg        512 Sep 22 02:01 /usr/local/man
drwxrwsr-x  15 swpkg    swpkg        512 Sep 22 02:01 /usr/local/man/man1
lrwxrwxrwx   1 swpkg    swpkg         44 Jun 20 14:04 /usr/local/man/man1/bzip2.1
                                                      -> /usr/local/pkgs/bzip2-1.0.1/man/man1/bzip2.1

The source directory

Each package is entirely installed and self-contained under its own directory in the source directory. While it may seem reasonnable to directly access installed files using their real path, it is very important to understand that this must never be done as it will only lead to problems.

For example, if you write a shell script using bzip2, and use its real PATH "/usr/local/pkgs/bzip2-1.0.1/bin/bzip2". This works fine and may seem alright, up to the day when the system administrator installs the latest version of bzip2, and removes the old one. When this happens, "/usr/local/bin/bzip2" will still exist and point to the newer version, while /usr/local/pkgs/bzip2-1.0.1/bin/bzip2 no longer will.

The above holds true for binaries, but also and even more for other files, such as dynamic libraries and so on.

The target directory: to link or not link?

At first, it seems that the target directory should be the union of all the packages found in the source directory, with every single file found in these packages represented by a symbolic link in the target directory. While collisions between different packages will occasionally occur, there is nothing really wrong with doing this, but there is also little sense in doing so, and it may also be wrong/misleading.

Let's take the example of a perl installation. As you may know, perl comes with a number of base modules which may be used in scripts, and more modules can be added to the installation. Such extra modules are "site" specific, and installed under a "site_perl" directory:

drwxr-sr-x   3 swpkg    swpkg        512 Jan 13  2000 /usr/local/pkgs/perl-5.005_03/lib/perl5/site_perl/
drwxr-sr-x  32 swpkg    swpkg       1024 Sep 13 10:01 /usr/local/pkgs/perl-5.005_03/lib/perl5/site_perl/5.005
-r--r--r--   1 swpkg    swpkg      36021 Sep  3  1998 /usr/local/pkgs/perl-5.005_03/lib/perl5/site_perl/5.005/Expect.pm
If all files are linked in the target directory, here's how it looks like:
drwxr-sr-x   3 swpkg    swpkg        512 Jan 13  2000 /usr/local/lib/perl5/site_perl
drwxr-sr-x  23 swpkg    swpkg       1024 Nov 13  2000 /usr/local/lib/perl5/site_perl/5.005
lrwxrwxrwx   1 swpkg    swpkg         65 Jun 20 14:04 /usr/local/lib/perl5/site_perl/5.005/Expect.pm
                                                      -> /usr/local/pkgs/perl-5.005_03/lib/perl5/site_perl/5.005/Expect.pm
There is nothing wrong with this, but it is easily misleading. Why not install additional modules directly under "/usr/local/lib/perl5/site_perl"? Very simply, because unless you take special steps, it will have no effect, as perl will not be looking there since it was installed under the source directory:
$ perl -V
Summary of my perl5 (5.0 patchlevel 5 subversion 3) configuration:
[...]
Characteristics of this binary (from libperl):
  Built under solaris
  Compiled at Jan 13 2000 15:23:07
  @INC:
    /usr/local/pkgs/perl-5.005_03/lib/perl5/5.00503/sun4-solaris
    /usr/local/pkgs/perl-5.005_03/lib/perl5/5.00503
    /usr/local/pkgs/perl-5.005_03/lib/perl5/site_perl/5.005/sun4-solaris
    /usr/local/pkgs/perl-5.005_03/lib/perl5/site_perl/5.005
There is here no mention at all of /usr/local/lib/perl5/site_perl. (How to handle this particular case as well as other similar ones is examined further below.)

Each installation and site should decide how much to link in the target directory. Ask yourself what is really needed, and only link the minimum. Typically, this means that only binaries found under the bin directory and some others should be linked. Unless some users are developers needing some of the libraries installed, C header files (typically found under the include directory), static and dynamic libraries (typically found under the lib directory) don't need to be linked. Some other files may be linked simply for ease of access, for example configuration files (typically found under the etc directory) often accessed by system administrators.

By default, it is recommended to only link files found below one of the following directories:


Handling dependencies

Many software packages depend on others. There are two ways to approach the problem:

The easy way is not recommended, but appropriate for some environments. However, to get the full benefits of a properly managed installation, with dependencies clearly identified and managed, you will need to put in the extra work necessary to be thorough.

The target directory: which path to use?

As mentioned above, the default is /usr/local. It is important not to read to much into this, and to understand that this was chosen more so that it would speak to people and out of the need to have a default than anything else. It is also what makes the most sense if you want to migrate an existing base of installed software (which for most organizations is installed under /usr/local.

The truth is that /usr/local is a poor choice, especially if you plan to handle dependencies the "detailed way". Too many scripts (and in particular configuration ones) are too smart for their own good and will try very hard to find everything they need anywhere on your system. This means that they will probe a number of "standard" directories searching for things, and will use anything they find, often without even making it clear where the goods where found. /usr/local is too standard and common a location to escape such probing, and it makes installing new software without dependencies to /usr/local harder than it should be.

In other words, it is strongly recommended to use an obscure path as the target directory. However, this is not always practical, especially when migrating. It is also a good idea to choose a source directory that is not under the target directory (and vice-versa).

What if you are stuck with /usr/local?
Well, as mentioned above, it will make things harder, but there are ways you can help yourself:

"Local" software

Most environments have locally developed software installed on their systems, ranging from simple shell scripts to extensive C programs. No, there isn't anything wrong with these, but where do they fit in all this?

While they could be installed in the target directory, it doesn't make sense to mess up a nice and clean setup. Instead, they should be grouped under one or more packages in the source directory and linked in the target directory as any other package. Name your package in a way that will not conflict with real packages, use the version number in the name or not depending whether you actively maintain different versions. Don't necessarily create a package for each little piece of code locally written and maintained, but group these into a bigger package. In short, do what makes sense, and if you can't decide on a name consider using "local".

Handling additions to packages already installed

For most packages, once you've installed them, it's all over, and nothing else will need to be done with them. Some packages aren't this way, and will need some special attention and care. The following gives some examples along with recommendations to handle such packages:

Handling man pages and Info documents

Manual pages and Info documents are just like any other file, they can (and should be linked in the target directory without any adverse effect. What gets them to be mentioned here is that in both cases, there is an extra file than needs to be updated as files are added or removed:

Most systems come with a command to maintain man database files, however there is no similar command to update Info directory files. For this reason, swpkg provides a simple tool for this.

Static versus dynamic libraries

swpkg offers no new insight to the often heated debate over static versus dynamic libraries. It is however important to realize that when building a package from source, you should almost never remove the dependencies used during the build once you have completed it, even for static libraries which code may contain direct references to files under its own source directory. If you were to remove the dependency once the package is built, you may later mistakenly delete that package thinking nothing depends on it.


In short

The philosophy at the base of swpkg allows for a great deal of flexibility. The following items are a summary of its key points, and the way things should be done:


© 2001-2008 - Christophe Kalt