6.17 Layered Installations

A typical Racket configuration includes two layers: an installation layer and a user layer. The intent is that the installation layer is read-only to all users of a system, while the user layer allows each individual user to install additional packages that extend the installation layer. The installation layer is intended not only to be read-only, but to not change after users start installing in their own layers.

In an environment where Racket itself is under development, the installation layer will change. In that setting, if the user layer is used at all, care must be taken to not create conflicts for the user layer when modifying the installation layer—or else the user layer must be repaired on occasion.

By default, raco setup updates both layers whenever it is run; if a user does not have write permission the installation, raco setup with no arguments is all but certain to report permission errors. The actions of raco setup can be constrained to the user layer by supplying the --avoid-main argument, or raco setup can be constrained to the installation layer by using the --no-user argument. When raco pkg performs setup actions, it effectively supplies one of the other of those based on the package’s scope (and raco pkg refuses to operate on both scopes/layers at once).

The user layer is always both user- and version-specific. More precisely, it is specific to the user and an installation’s name, where the installation’s name is typically its version number. However, the name of an installation can be changed through the 'installation setting in "config.rktd" (see Installation Configuration and Search Paths). Setting an installation name changes the directory where packages and executables reside within (find-system-path 'addon-dir). The result of (find-system-path 'addon-dir) itself can be changed through 'addon-dir in "config.rktd".

The installation and user configuration layers can be generalized to multiple layers by setting search paths in "config.rktd". These search paths essentially treat the layer closest to user as the installation layer that might be adjusted by raco setup and raco pkg, but search paths can chain to an existing (unchanging) implementation in much the same way that user chains to installation. To build a new layer, create new "config.rktd" that is like the underlying layer’s "config.rktd", but
  • each of 'lib-dir, 'share-dir, 'links-file, 'pkgs-dir, 'bin-dir, 'gui-bin-dir, 'apps-dir, 'doc-dir, and 'man-dir is a new directory or file; and

  • the corresponding search lists 'lib-search-dirs, 'share-search-dirs, 'links-search-files, 'pkgs-search-dirs, 'bin-search-dirs, 'gui-bin-search-dirs, (no 'apps-dir search needed), 'doc-search-dirs, and 'man-search-dirs each add the old directory or file to the search list just after #f; note that the default for each search list is (list #f).

There is no argument to raco setup that is analogous to --avoid-main to avoid modifying nested layer; instead, nested layers are expected to be fully set up so that raco setup need not change them. When raco setup would otherwise install an executable into the directory configured as 'bin-dir, it consults the 'bin-search-dirs list to check whether the executable is already installed in one of those directories, and if so, it will refrain from creating a copy in the new layer. The same search-list check also applies to native libraries, shared files, and man pages, but with the additional check that the file to install matches the one that is already installed.

The default path to "config.rktd" is hardwired within a racket executable. In some cases, it can make sense for the innermost layer’s configuration to point to another layer, perhaps because the filesystem provides an indirection. For example, on Unix, a Racket installation in "/usr" might reasonably configure the installation layer’s directories to be in "/usr/local" with "/usr" directories included in the search lists.

To use racket with a new "config.rktd", you can supply the --config or --G flag to racket or set the PLTCONFIGDIR environment variable to point to the directory containing "config.rktd". Alternatively, you can create a tethered layer that creates replacement executables like racket that are hardwired to the layer’s configuration directory.