Starting Lisps
stift exec
stift exec sbcl
stift exec ccl
stift exec sbcl --non-interactive --eval '(asdf:test-system "hello")'
For SBCL and CCL, stift adds the options that skip the init files and load
the build list's setup file before anything else: for SBCL after its
runtime options, such as --dynamic-space-size, and before --script;
for CCL first. Init files are skipped because Quicklisp, loaded from one,
adds a search of its own to ASDF, and a system missing from the build list
would then come from Quicklisp without a word.
stift gives the program the terminal, waits for it, and exits with its status. Ctrl-C reaches the program, which handles it, and stift waits on. On Windows the console sends Ctrl-C to every program attached to it, stift included; that stift waits on there is not tested yet.
In a workspace, stift exec in any member, or at the workspace's root,
starts the Lisp with the workspace's build list, the members' checkouts
included (see Workspaces).
The setup file
Before it writes the setup file, stift checks that the stiftfile holds a consistent build list, and that no two of its projects provide one system (see Choosing Commits).
stift writes the setup file into its cache before every run, named after the build list, so it never goes stale. It calls ASDF and UIOP only, and defines nothing of its own. Loading it:
- checks that each directory of the build list is there;
- checks that only ASDF's own searches find systems: an
asdf:*central-registry*that holds something, or a search Quicklisp added, is an error, with acontinuerestart that removes them; - checks that no system already loaded would now be found in another directory, since loaded code cannot be replaced;
- sets ASDF's source registry to the directories of the build list's
projects that hold
.asdfiles, and nothing else, leaving out hidden directories such as.gitand.qlot, and those an:excludenames; - sets an output translation for each directory, so that its fasls go to
fasl/IMPLEMENTATION/KEY/PROJECT/in the cache.
KEY is a hash of the build list. Sources are shared by every build list
that has their commit; fasls only by identical build lists.
The setup file names each directory that holds a system, in the order in
which ASDF prefers one of two .asd files of one name in a project: the
shallower first. A system put in a directory that held none is found once
stift writes the setup file again, at the next stift exec or stift setup.
When the build list holds a newer ASDF, ASDF upgrades itself at the first operation.
Other programs
Any other program gets the build list in the environment variables ASDF reads, so that a Lisp it starts finds the build list:
CL_SOURCE_REGISTRYandASDF_OUTPUT_TRANSLATIONS;STIFT_SETUP, the setup file's path.
stift exec make test
The init files of a Lisp such a program starts are the program's business.
From CCL on Windows
The stift executable is built with SBCL, and starts any program on
every system. The library, stift:exec-program, run in CCL on Windows,
does not do all of it, because CCL there gives a program no environment
variables of its own and passes some arguments wrongly. stift says so
rather than run the program otherwise:
- it starts no program other than a Lisp, which would not get the build list;
- it passes no empty argument, and none with two spaces or tabs in a row,
which CCL writes as
"", which Windows reads as a quote.
SLY
SLY starts its Lisp through stift as it would through qlot exec:
(setq sly-lisp-implementations
'((sbcl ("stift" "exec" "sbcl"))
(ccl ("stift" "exec" "ccl"))))
Start it from a file of the project, so that stift finds the stiftfile.
A Lisp that runs already
stift setup fetches what the build list lacks, writes the setup file and
prints its path:
(load (uiop:run-program '("stift" "setup") :output '(:string :stripped t)))