Building Programs
stift build # the project's one system that names a build operation
stift build hello/cli # the system named
stift build --lisp ccl # with CCL
stift build --compress # the executable compressed, where the Lisp can
stift build builds a system as asdf:make does, in a new Lisp started
as stift exec starts one, with the build list: SBCL, unless --lisp
names CCL. In a workspace, the build list is the workspace's (see
Workspaces).
The build operation
asdf:make performs the build operation the system's defsystem names.
program-op writes an executable to the file :build-pathname names,
relative to the system's directory, which starts in the function
:entry-point names:
(defsystem "hello"
:depends-on ("alexandria")
:build-operation "program-op"
:build-pathname "bin/hello"
:entry-point "hello:main"
:components ((:file "hello")))
$ stift build
Built hello with sbcl: /home/me/hello/bin/hello
On Windows the file is bin\hello.exe. The executable holds everything
the Lisp loaded, so it runs without stift and without the cache. Any
other build operation builds the same way, and stift prints the files
ASDF says it writes.
The build writes its files anew each time. asdf:make alone would keep an
executable that is newer than everything it was built from, though built
otherwise, as compressed or not.
Compressed executables
--compress compresses the executable program-op writes, or the image
image-op writes, on an SBCL built with core compression, as Debian's
is:
$ stift build --lisp /usr/bin/sbcl --compress
Built hello with /usr/bin/sbcl, compressed: /home/me/hello/bin/hello
A compressed executable takes less space on disk, more in memory, and longer to start: the whole image is decompressed into memory when it starts, where an uncompressed one is read in as it is used. For a small program:
| On disk | Memory | Start | |
|---|---|---|---|
| Uncompressed | 37 MB | 20 MB | 3 ms |
| Compressed | 11 MB | 45 MB | 33 ms |
A Lisp that cannot compress builds the executable uncompressed, and stift says why. That is CCL, which cannot compress images, and any SBCL built without core compression, such as the releases of sbcl.org:
stift: SBCL 2.6.9 was built without core compression, so hello was built uncompressed. An SBCL built with it, as Debian's is, compresses.
So does a system built with another operation than program-op or
image-op, since stift compresses only what those two dump. (member :sb-core-compression *features*) tells whether an SBCL can compress.
Which system
With no system named, stift builds the one system of the project's .asd
files that names a build operation; at a workspace's root, outside its
members, of the members' files. When none does, or several do, it says so
and stops: give the defsystem a build operation, or name the system:
stift: example.org/me/tools has several systems that name a build operation: "tools/one", "tools/two". Name the one to build, as stift build tools/one.
A system named that names no build operation is refused, as asdf:make
would only load it.
What it prints
The Lisp's own output, the compiler's included, goes to the terminal as it comes. At the end stift prints the files it built. It exits with 1 when the build fails, with what the error said, and with 0 otherwise.
--lisp takes one Lisp: two would write the same file.
How it works
program-op dumps the Lisp as the executable, which ends it, and nothing
runs after that. So the Lisp writes what it is about to build, the system
and its files, to a file stift reads, before it builds, as the Lisp of
stift check does; afterwards stift looks for the files.
From Lisp
stift:build-system takes :system, :lisp, :directory, :compress
and :settings, and returns the files built, the system's name, and
whether the image is compressed. A build that was asked to compress and
could not signals a stift-warning that says why; see the
API Reference.