458 lines
16 KiB
Plaintext
458 lines
16 KiB
Plaintext
|
In Emacs, read this file in -*- Outline -*- mode.
|
||
|
|
||
|
* Introduction
|
||
|
|
||
|
The aim of the following proposal is to define a standard for the
|
||
|
packaging, distribution, installation, use and removal of libraries
|
||
|
for scsh. Such packaged libraries are called "scsh packages" or simply
|
||
|
"packages" below.
|
||
|
|
||
|
This proposal attempts to cover both libraries containing only Scheme
|
||
|
code and libraries containing additional C code. It does not try to
|
||
|
cover applications written in scsh, which are currently considered to
|
||
|
be outside of its scope.
|
||
|
|
||
|
** Package identification and naming
|
||
|
|
||
|
Packages are identified by a globally-unique name. This name should
|
||
|
start with an ASCII letter (a-z or A-Z) and should consist only of
|
||
|
ASCII letters, digits or underscore characters (_). Package names are
|
||
|
case-sensitive, but there should not be two packages with names which
|
||
|
differ only by their capitalisation.
|
||
|
|
||
|
Rationale:
|
||
|
|
||
|
This restriction on package names ensures that they can be used to
|
||
|
name directories on current operating systems.
|
||
|
|
||
|
Several versions of a given package can exist. A version is identified
|
||
|
by a sequence of non-negative integers. Versions are ordered
|
||
|
lexicographically.
|
||
|
|
||
|
A version has a printed representation which is obtained by separating
|
||
|
(the printed representation of) its components by dots. For example,
|
||
|
the printed representation of a version composed of the integer 1
|
||
|
followed by the integer 2 is the string "1.2". Below, versions are
|
||
|
usually represented using their printed representation for simplicity,
|
||
|
but it is important to keep in mind that versions are sequences of
|
||
|
integers, not strings.
|
||
|
|
||
|
A specific version of a package is therefore identified by a name and
|
||
|
a version. The full name of a version of a package is obtained by
|
||
|
concatenating:
|
||
|
|
||
|
- the name of the package,
|
||
|
|
||
|
- a hyphen (-),
|
||
|
|
||
|
- the printed representation of the version.
|
||
|
|
||
|
In what follows, the term "package" is often used to designate a
|
||
|
specific version of a package, but this should be clear from the
|
||
|
context.
|
||
|
|
||
|
* Distribution of packages
|
||
|
|
||
|
Packages are distributed in TAR archives, which can optionally be
|
||
|
compressed by GZIP or BZIP2.
|
||
|
|
||
|
The name of the archive is composed by appending:
|
||
|
|
||
|
- the full name of the package,
|
||
|
|
||
|
- the string ".tar" indicating that it's a TAR archive,
|
||
|
|
||
|
- either the string ".gz" if the archive is compressed using GZIP,
|
||
|
or the string ".bz2" if the archive is compressed using BZIP2, or
|
||
|
nothing if the archive is not compressed.
|
||
|
|
||
|
** Archive contents
|
||
|
|
||
|
The archive is organised so that it contains one top-level directory
|
||
|
whose name is the full name of the package. This directory is called
|
||
|
the package unpacking directory. All the files belonging to the
|
||
|
package are stored below it.
|
||
|
|
||
|
The unpacking directory contains at least the following files:
|
||
|
|
||
|
- install-pkg
|
||
|
a script performing the installation of the package,
|
||
|
|
||
|
- README
|
||
|
a textual file containing a short description of the package,
|
||
|
|
||
|
- COPYING
|
||
|
a textual file containing the license of the package.
|
||
|
|
||
|
* Downloading and installation of packages
|
||
|
|
||
|
A package can be installed on a target machine by downloading its
|
||
|
archive, expanding it and finally running the installation script
|
||
|
located in the unpacking directory.
|
||
|
|
||
|
All files belonging to a package will be installed in a single
|
||
|
directory called the "package installation directory". The package
|
||
|
installation directory contains all files, and only files belonging to
|
||
|
the (version of the) package.
|
||
|
|
||
|
Rationale:
|
||
|
|
||
|
Such an organisation makes it easy to uninstall package by just
|
||
|
recursively deleting a single directory. It also makes it trivial to
|
||
|
know to which package a given file belongs.
|
||
|
|
||
|
** Root directory layout
|
||
|
|
||
|
The package installation directory will be an indirect sub-directory
|
||
|
of some "package root directory". A package root directory is a
|
||
|
directory on the target machine which contains all installed packages.
|
||
|
There can be several package roots on a target machine, for example
|
||
|
one for packages installed globally, and one per user for "personal"
|
||
|
packages.
|
||
|
|
||
|
A package root directory contains exactly two sub-directories, and
|
||
|
nothing else. These directories are called "installed" and "active".
|
||
|
|
||
|
The "installed" directory contains exactly one directory per package,
|
||
|
and nothing else (N.B. here "package" really means "package" and not
|
||
|
"package version"). These directories have the same name as the
|
||
|
package they contain. For every installed version of a package, there
|
||
|
is a sub-directory of the package directory. These directories are
|
||
|
named using the printed representation of the version they contain.
|
||
|
|
||
|
The "active" directory contains only symbolic links which point to
|
||
|
package version directories. There is at most one symbolic link per
|
||
|
installed package. These symbolic links identify the active (or
|
||
|
default) version of a package, that is the version will be used if a
|
||
|
script asks for a given package without explicitly which version is
|
||
|
required.
|
||
|
|
||
|
Example:
|
||
|
|
||
|
Let's imagine a system on which the directory
|
||
|
"/usr/local/lib/scsh/modules" serves as the package root directory. On
|
||
|
this system, versions 1.0 and 2.0 of a package called "package_1" are
|
||
|
installed, the latter being active. Further, version 1.5.4 of a
|
||
|
package called "package_2" is installed and active. The contents of
|
||
|
the package root would look as follows:
|
||
|
|
||
|
/usr/local/lib/scsh/modules/
|
||
|
installed/
|
||
|
package_1/
|
||
|
1.0/
|
||
|
all files belonging to v1.0 of package_1 (and nothing else)
|
||
|
2.0/
|
||
|
all files belonging to v2.0 of package_1
|
||
|
package_2/
|
||
|
1.5.4/
|
||
|
all files belonging to v1.5.4 of package_2
|
||
|
active/
|
||
|
package_1 -> ../installed/package_1/2.0
|
||
|
package_2 -> ../installed/package_2/1.5.4
|
||
|
|
||
|
** Package directory layout
|
||
|
|
||
|
Even though the exact contents of the package directory will depend on
|
||
|
the package, all package directories are laid out according to the
|
||
|
rules below. These rules make it easy to examine the contents of a
|
||
|
package directory, and find important data like the package
|
||
|
documentation.
|
||
|
|
||
|
The standard layout is shown below. Some directories are of course
|
||
|
optional because not all packages have something to put in all of
|
||
|
them.
|
||
|
|
||
|
load.scm
|
||
|
|
||
|
Scheme file written in Scheme 48's exec language, whose role is to
|
||
|
define all the structures which belong to a package.
|
||
|
|
||
|
scheme/
|
||
|
|
||
|
Directory containing all the Scheme code of the package.
|
||
|
|
||
|
lib/
|
||
|
|
||
|
Directory containing one sub-directory per platform for which the
|
||
|
package was installed. These sub-directories contain the shared
|
||
|
libraries for the given platform; the name of a given platform is
|
||
|
the one given by autoconf's "config.guess" script.
|
||
|
|
||
|
<platform>/
|
||
|
|
||
|
Directory containing the shared libraries for <platform>.
|
||
|
|
||
|
doc/
|
||
|
|
||
|
Directory containing the documentation of the package, possibly in
|
||
|
different formats.
|
||
|
|
||
|
html/
|
||
|
|
||
|
Directory containing the HTML documentation of the package, if
|
||
|
any; this directory should at least contain one file called
|
||
|
"index.html" serving as an entry point to the documentation.
|
||
|
|
||
|
pdf/
|
||
|
|
||
|
Directory containing the PDF documentation of the package, if
|
||
|
any; this directory should contain at least one file called
|
||
|
"<package>.pdf" where "<package>" is the name of the package.
|
||
|
|
||
|
ps/
|
||
|
|
||
|
Directory containing the PostScript documentation of the
|
||
|
package, if any; this directory should contain at least one file
|
||
|
called "<package>.ps" where "<package>" is the name of the
|
||
|
package.
|
||
|
|
||
|
** File permissions
|
||
|
|
||
|
TODO
|
||
|
|
||
|
** Installation procedure
|
||
|
|
||
|
Packages are installed using the "install-pkg" script located in the
|
||
|
package archive. This script must be given the name of the root
|
||
|
directory in which to perform installation with the "--root" option.
|
||
|
It also accepts the following options:
|
||
|
|
||
|
--dry-run or -n
|
||
|
|
||
|
Print what actions would be performed to install the package, but
|
||
|
do not perform them.
|
||
|
|
||
|
--inactive or -i
|
||
|
|
||
|
Do not activate package after installing it.
|
||
|
|
||
|
** Creating images
|
||
|
|
||
|
TODO (my current idea is to add support to install-lib to easily
|
||
|
create an image containing the package being installed, and
|
||
|
maybe some structures opened. Then, at install time, users could
|
||
|
say that they want an image to be created, and the install
|
||
|
script would do that).
|
||
|
|
||
|
* Using packages
|
||
|
|
||
|
To use a package, its "loading script" must be loaded in Scheme 48's
|
||
|
exec package. The loading script for a package is a file written in
|
||
|
the Scheme 48 exec language, whose name is "load.scm" and which is
|
||
|
located directly in the package installation directory.
|
||
|
|
||
|
To load this file, one typically uses scsh's "-lel" option along with
|
||
|
a properly defined SCSH_LIB_DIRS environment variable.
|
||
|
|
||
|
Scsh has a list of directories, called the library directories, in
|
||
|
which it looks for files to load when the options -ll or -lel are
|
||
|
used. This list can be given a default value during scsh's
|
||
|
configuration, and this value can be overridden by setting the
|
||
|
environment variable SCSH_LIB_DIRS before running scsh.
|
||
|
|
||
|
In order for scsh to find the package loading scripts, one must make
|
||
|
sure that scsh's library search path contains the names of both the
|
||
|
"installed" and the "active" directories of *every* existing package
|
||
|
root directories.
|
||
|
|
||
|
Example:
|
||
|
|
||
|
On a system where the package root directory is
|
||
|
"/usr/local/lib/scsh/modules", the SCSH_LIB_DIRS environment variable
|
||
|
has to contain at least the following two directories:
|
||
|
|
||
|
/usr/local/lib/scsh/modules/active
|
||
|
/usr/local/lib/scsh/modules/installed
|
||
|
|
||
|
The names of these directories should not end with a slash (/), as
|
||
|
this forces scsh to search them recursively. This could *drastically*
|
||
|
slow down scsh when looking for packages.
|
||
|
|
||
|
A package named "foo" can then be used from a script provided that the
|
||
|
following option is added to its command line:
|
||
|
|
||
|
-lel foo/load.scm
|
||
|
|
||
|
* Writing packages
|
||
|
|
||
|
Once the Scheme and/or C code for a package has been written, the last
|
||
|
step in turning it into a standard package as defined by this proposal
|
||
|
is to write the installation script.
|
||
|
|
||
|
This script could be written fully by the package author, but in order
|
||
|
to simplify this task a small scsh installation framework is provided.
|
||
|
This framework is composed of several files which are meant to be
|
||
|
included in the package archive. These files are:
|
||
|
|
||
|
- install-pkg
|
||
|
|
||
|
a trivial sh script which launches scsh on the main function of
|
||
|
the installation library, passing it all the arguments given by
|
||
|
the user,
|
||
|
|
||
|
- install-lib.scm
|
||
|
|
||
|
the code for the installation library, documented below,
|
||
|
|
||
|
- install-lib-module.scm
|
||
|
|
||
|
Scheme 48 interface and structure definitions for the installation
|
||
|
library.
|
||
|
|
||
|
As explained above, when the install-pkg script is invoked, it launches
|
||
|
scsh on the main function of the installation library, which does the
|
||
|
following:
|
||
|
|
||
|
- parse the command line arguments (e.g the --root option),
|
||
|
|
||
|
- load the package definition file, a (Scheme) file called
|
||
|
"pkg-def.scm", which is supplied by the package author and which
|
||
|
contains the installation procedure for the package,
|
||
|
|
||
|
- install the package which was defined in the previous step.
|
||
|
|
||
|
It is actually possible to define several packages in "pkg-def.scm",
|
||
|
and all will be installed. It should not be often useful, though.
|
||
|
|
||
|
The main job of the package author is therefore to write the package
|
||
|
definition file, "pkg-def.scm".
|
||
|
|
||
|
This file is mostly composed of a package definition statement, which
|
||
|
specifies the name, version and installation code for the package. The
|
||
|
package definition statement is expressed using the following syntax
|
||
|
exported from the installation library:
|
||
|
|
||
|
(define-package <name> <version> <body> ...) (syntax)
|
||
|
|
||
|
Define a package to be installed. NAME is the package name (a
|
||
|
string), VERSION its version (a list of integers) and BODY is the
|
||
|
list of statements to be evaluated in order to install the package.
|
||
|
|
||
|
The installation statements typically use functions of the
|
||
|
installation library in order to install files in their target
|
||
|
location. The following functions are currently exported:
|
||
|
|
||
|
(install-file <file> [<target-dir>] [<perms>])
|
||
|
|
||
|
Install the given file in TARGET-DIR. TARGET-DIR is specified
|
||
|
relative to the package directory, and defaults to "." (i.e. the
|
||
|
package directory itself). If the target directory does not exist,
|
||
|
it is created along with all its parents, as needed.
|
||
|
|
||
|
The copied file and all directories created by this command have
|
||
|
their permissions set to PERMS, an integer which defaults to #o755
|
||
|
(i.e. read, write and execute for the owner, read and execute for
|
||
|
the rest).
|
||
|
|
||
|
(install-files <file-list> [<target-dir>] [<perms>])
|
||
|
|
||
|
Like install-file but for several files, which are specified as a
|
||
|
list.
|
||
|
|
||
|
(install-directory <dir> [<target-dir>] [<perms>])
|
||
|
|
||
|
Install the given directory and all its contents, including
|
||
|
sub-directories, in TARGET-DIR. This is similar to what INSTALL-FILE
|
||
|
does, but for complete hierarchies.
|
||
|
|
||
|
Notice that DIR will be installed as a sub-directory of TARGET-DIR.
|
||
|
|
||
|
(install-directories <dir-list> [<target-dir>] [<perms>])
|
||
|
|
||
|
Install several directories in one go.
|
||
|
|
||
|
Example:
|
||
|
|
||
|
A typical package definition file for a simple package called
|
||
|
"my_package" whose version is 1.2 could look like this:
|
||
|
|
||
|
(define-package "my_package" (1 2)
|
||
|
(install-file "load.scm")
|
||
|
(install-directories '("scheme" "doc")))
|
||
|
|
||
|
With such a definition, invoking the installation script with
|
||
|
"/usr/local/lib/scsh/modules" as package root would have the
|
||
|
following effects:
|
||
|
|
||
|
1. The package directory
|
||
|
|
||
|
/usr/local/lib/scsh/modules/installed/my_package/1.2
|
||
|
|
||
|
would be created.
|
||
|
|
||
|
2. File "load.scm" would be copied to this directory.
|
||
|
|
||
|
3. All the contents of the directory called "scheme" would be copied
|
||
|
to directory
|
||
|
|
||
|
/usr/local/lib/scsh/modules/installed/my_package/1.2/scheme
|
||
|
|
||
|
The same would happen for the contents of directory "doc".
|
||
|
|
||
|
4. The package would be activated by creating a symbolic link with
|
||
|
name
|
||
|
|
||
|
/usr/local/lib/scsh/modules/active/my_package
|
||
|
|
||
|
pointing to
|
||
|
|
||
|
../installed/my_package/1.2
|
||
|
|
||
|
** Packages containing C code (for shared libraries)
|
||
|
|
||
|
Packages containing C code are more challenging to write, since all
|
||
|
the problems related to C's portability and incompatibilities between
|
||
|
the APIs of the various platforms have to be accounted for.
|
||
|
Fortunately, the GNU Autoconf system simplifies the management of
|
||
|
these problems, and authors of scsh packages containing C code are
|
||
|
strongly encouraged to use it.
|
||
|
|
||
|
Integrating Autoconf into the installation procedure should not be a
|
||
|
major problem thanks to scsh's ability to run separate programs.
|
||
|
|
||
|
* Packaging packages
|
||
|
|
||
|
Most important Unix systems today have one (or several) package
|
||
|
management systems which ease the installation of packages on a
|
||
|
system. In order to avoid confusion between these packages and the
|
||
|
scsh packages discussed above, they will be called "system packages"
|
||
|
in what follows.
|
||
|
|
||
|
It makes perfect sense to provide system packages for scsh packages.
|
||
|
System packages should as much as possible try to use the standard
|
||
|
installation script described above to install scsh packages. This
|
||
|
script currently provides some support for staged installations,
|
||
|
which are required by several packaging systems.
|
||
|
|
||
|
This support is provided through an additional option, --dest-root,
|
||
|
which specifies the package root in which the files have to be copied
|
||
|
by the installation script. The files will then have to be moved from
|
||
|
this location to their final root directory, i.e. the one given
|
||
|
through the --root option, by the system packaging tools.
|
||
|
|
||
|
(The --dest-root option plays the same role as the DEST_DIR
|
||
|
variable which is typically given to "make install", for makefiles
|
||
|
which support staging directories).
|
||
|
|
||
|
* Glossary
|
||
|
|
||
|
TODO define the following terms
|
||
|
|
||
|
Version
|
||
|
|
||
|
Target machine
|
||
|
|
||
|
Package
|
||
|
|
||
|
(Package) unpacking directory
|
||
|
|
||
|
(Packages) root directory
|
||
|
|
||
|
(Package) installation directory
|
||
|
|
||
|
Package loading script
|
||
|
|
||
|
* Version
|
||
|
|
||
|
$Id: proposal.txt,v 1.1 2003/12/14 12:14:21 michel-schinz Exp $
|