RFC: Package Management System

A package management system is a program that manages archives of software to be automatically installed on your system. PMSes automate installation and deinstallation, and often also support automatic downloading of dependencies, listing of software from repositories, and in some cases compiling software for you.

PMSes are most commonly found in free and open source UNIX-like operating systems, such as the various GNU/Linux distributions and free BSDs. There are also a few for Mac OS X, but very few, if any, can be found for Windows.

I will not be going too far into the details of package management in this article, because that is not its point. This article is about a package manager that I am developing. Code name (and possibly normal name in the future): CANDY.

For more information on PMSes, please visit Wikipedia.

I am developing a package management systems inspired by the Slackware and MacPorts package management systems. It will be able to install two types of packages: Source and Binary packages (as with the RPM Package Manager). Source packages will function similarly to MacPorts Portfiles and RPM Specfiles. They will contain instructions on fetching, verifying, extracting, installing, and then later uninstalling software.

Source Package Format #1

Each package will get its own directory. In this directory, there will be a series of files:
  • static.yml: This file will contain static (non-scripted) information about the package, such as metadata (title, description, etc.) and dependencies.
  • features.lst: (Produced by Candy, deleted if --dont-save-features is specified.) See below: Compile-Time Features.
  • fetch.sh: This file is a Bourne Shell script that will download and verify (via WHIRLPOOL, SHA512, and RMD160 checksums) the source code. This script should not re-download archives unless the checksums do not match. If the downloaded archive still does not match, then it should exit with code 1.
  • build.sh: This file will compile and install the files. It will compile the files to install to locations that are specified by Candy's configuration file, but will actually install the files into a temporary directory via a DESTROOT (i.e. make install DESTROOT=/tmp/blah).
  • preinstall.sh: (Optional) this file will be executed before files are installed into the root directory.
  • postinstall.sh: (Optional) this file will be executed after files are installed into the root directory.
  • predeinstall.sh: (Optional) this file will be executed before files are uninstalled.
  • postdeinstall.sh: (Optional) this file will be executed after files are uninstalled.
  • patches/*.patch: (Optional) patch files to be applied to the source archive post-extraction.
  • source/: Unextracted sources. This will be produced by fetch.sh. This directory will be deletable with the clean command.
  • source-archive.*: May be an archive or a directory checked out with a version control system. If it was a VCS checkout, source/ will be a symbolic link, and the directory should have the .vcs extension. This will be produced by fetch.sh.
During any form of build procedure, build.sh will be called. However, there are two things that may happen after build.sh executes, depending on the command specified to Candy. The two commands are:
  • install: This command will run preinstall.sh, move the files into the root directory, and then run postinstall.sh. The predeinstall.sh and postdeinstall.sh files will be saved for whenever the program gets deinstalled.
  • build-binary: This command will create an archive from the temporary files which will also include the pre- and post-scripts. This package is faster to install, does not require any development utilities in most cases, but is not configurable and less portable.

Source Package Format #2

Another format that will be supported is an archive that contains the files static.yml, build.sh, preinstall.sh, postinstall.sh, predeinstall.sh, and postdeinstall.sh (all files but fetch.sh and features.lst). Along with these files will be the downloaded source files. This is more similar to RPM, while the previous format is more similar to MacPorts.

Binary Package Format

Yet another format that will be supported is an archive that contains the files static.yml, features.lst, preinstall.sh, postinstall.sh, predeinstall.sh, and postdeinstall.sh (all files but fetch.sh and build.sh). It will also contain the built program binaries (produced by build.sh) which will be extracted into the root directory.

Compile-Time Features

Like MacPorts and Portage, Candy will support Compile-Time Features (in Portage talk, USE flags). They can be enabled with -f and disabled with -F, and all features are enabled by default. static.yml will contain summaries/descriptions of these features, and information about which features are enabled/disabled will be saved in features.lst. The various scripts will use features.lst, a list of enabled features separated by newlines, to determine which features to include.

Initially, I was planning to have static.yml truncated in Binary Package Format, but I decided that it was useful for users to have information about which features were enabled/disabled by the binary package author.


Packages will be passed the variable $DIALOG, which will evaluate to a program compatible with dialog which will vary between the original program or a graphical replica.

Amendment 1: File Selection and Multi-Package Output

This is an amendment to the previous section. It was added after the original article was written but before the article was published. I found that it would cause inconsistencies in the article to edit this in, so I decided to add it in this section. Further amendments will be posted in separate posts and linked to from here.

In the original design specified in this document, all of the files installed into a temporary directory are installed or archived in Source Package Format #2 or Binary Package Format. This amendment changes this: static.yml will contain globs (a.k.a. wildcards) specifying which files in the temporary directory are to be installed or archived (where /**/* would specify all files recursively). All files are excluded by default, since certain files such as the GNU Info dir file should be excluded.

Furthermore, the globs may be specified to specific Binary Packages, meaning that although both Source Packages will see them all as one tree, multiple Binary Packages may be generated. By standard, architecture-specific files, non-architecture-specific files, documentation, and development files (headers and static libraries) will be in separate packages. All of them will share the same package root name, but have the following mechanism for distinguishing them (by standard):

  • packagerootname: Architecture-specific files.
  • packagerootname-share: Non-architecture-specific files (will be stored in just packagerootname if there are no architecture-specific files.
  • packagerootname-doc: Documentation files (man pages will be stored in packagerootname-share or packagerootname if there are no non-architecture-specific files).
  • packagerootname-devel: Development header files.
  • packagerootname-static: Static object files (if it is a library, that is).
Furthermore, while I am describing conventions, libraries will be prefixed with lib.


As you can see I have a lot of plans for this program, and I hope you have become interested in them. The RFC in the title of this post stands for Request For Comments, which means that I want you to tell me what you think. I am interested in knowing what others think of my ideas, and since this is really, really early in development, Candy can be subjected to radical changes (although I would prefer to avoid them).

No comments:

Post a Comment

Please, no spam. Complete sentences would be nice, too. :D