3. What the compilers must implement

The Cabal requires that the Haskell implementations be somewhat package-aware. This section documents those requirements.

3.1. Building and registering a package

Installing a package ultimately involves these steps:

It must be possible to register many versions of the same package.

3.1.1. Global packages and user packages

A package can be registered either as a global package or as a user package. The former means that anyone invoking hc will see the new package. The latter means that only the user who installed the package will see it.

User packages shadow global packages, in the following sense:

  • A Haskell import for module M will seek M in a user package first.

  • The hc-pkg commands that take package IDs will look for a user package first.

Each user has one package database per compiler and version. That is, the user packages for GHC 6.2 are separate from those for GHC 6.2.1. If there are multiple installations of a particular compiler version on the system, then they will all use the same user packages, so the user should refrain from using user packages with different installations of the same compiler version, unless they can guarantee that the different installations are binary compatible, such as if they were installed from identical binary distributions.

For instance, lets say that Joe User mounts his home directory on his Linux machine and on his Solaris machine. He also uses ghc-6.2 on both machines. His user packages are installed in ~/ghc-6.2-packages (or something) and are compiled for Linux. Now he had better not use these packages with the Solaris compiler, because they are in a spot where the Solaris compiler will find them!

3.1.2. Exposed packages and hidden packages

An installed package can be exposed or hidden. An exposed package populates the module name space, while a hidden package does not. Hidden packages are nevertheless necessary. For example, the user might use package A-2.1 and B-1.0; but B-1.0 might depend on A-1.9. So the latter must be installed (else B-1.0 could not be installed), but should be hidden, so that user imports see A-2.1. (However, note that the whole-program invariant described in Section 2.2 implies that a program using B-1.0 could not also use A-2.1, because then both A-2.1 and A-1.9 would form part of the program, and they almost certainly use the same module names.)

The registration program hc-pkg provides operations to expose or hide an already-installed package. By default, installing a package installs it exposed, and hides any existing installed package of the same name (and presumably different version).

Hiding or exposing a package is an operation that can be performed, by hc-pkg, on any package. It is quite distinct from the question of which modules in a package are hidden or exposed (see Section 2.1), which is a property of the package itself. Only the exposed modules of an exposed package populate the module name space seen by a Haskell import statement.

3.1.3. Registration invariants

The registration program hc-pkg checks the following invariants:

  • Before registering a package P, check all the packages that P depends on are already registered. If P is being registered as a global package, P's dependencies must also be global packages.

  • Before registering an exposed user package P, check that the modules that are exposed by P do not have the same names (in the hierarchical module name space) as any other module in an exposed user package Q. Similarly for system packages. (However, one may register a system package which exposes a module with the same name as a user package, and vice-versa.)

  • Before un-registering a package P, check that no package that depends on P is registered. The exception is that when un-registering a global package, hc-pkg cannot check that no user has a user package depending on P.

3.2. The -package compiler flag

By default, the module namespace is populated only by the exposed modules of exposed packages. This can be overridden using the -package flag, which temporarily exposes a particular package, hiding any other packages of the same name.

Later options override earlier ones, so that for example -package hunit-1.2 -package hunit-1.3 will result in hunit-1.3 being exposed.

Additionally, compilers should provide a -hide-package flag, which does the opposite of -package: it temporarily hides a package for this run of the compiler.

When all the -package and -hide-package flags on the compiler's command line have been processed, the resulting module namespace must not contain any overlapping modules; the compiler should check this and report any errors.

3.3. The interface to hc-pkg

Registering a package with a compiler records the package information in some implementation-specific way; how it does so is not constrained by the Cabal. Much of an IPD is independent of the compiler, but it may also include compiler-specific fields.

Each Haskell implementation hc must provide an associated program hc-pkg which allows a user to make a new package known to the compiler, and to ask what packages it knows. Here is a summary of its interface

Note

Some of these commands (unregister, hide, and describe) make sense for package IDs which offer a range, such as "hc-pkg unregister hunit<2.3".

Table 1. hc-pkg interface

hc-pkg register {filename | -} [--user | --global]

Register the package using the specified installed package description. The syntax for the latter is given in Section 3.4.

hc-pkg unregister [pkg-id]

Unregister the specified package.

hc-pkg expose [pkg-id]

Expose the specified package.

hc-pkg hide [pkg-id]

Hide the specified package.

hc-pkg list

List all registered packages, both global and user, hidden and exposed.

hc-pkg describe {pkg-id }

Give the registered description for the specified package. The description is returned in precisely the syntax required by hc-pkg register.

hc-pkg field {pkg-id } {field }

Extract the specified field of the package description for the specified package.

A pkg argument can be a package ID, such as "hunit-2.3", or just a package name, such as "hunit". To determine which package is meant, hc-pkg searches first the registered user packages and then the global packages. If no such package exists, the command fails; that is, it does nothing, returning a non-zero error code. If only a name is specified, hc-pkg fails unless the name identifies a unique package among the user packages, or among the global packages. As usual, the user packages win.

Note

Can we give the --user flag to hide, expose, describe? Can we register a package that is already registered? What if it's registered as a global package and we register it as a user package?

3.4. Syntax of installed package description

Note

...include the list of ``externally visible modules''.