trivial-dump-core is an MIT-licensed wrapper that provides a common interface between lisp implementations for the creation of lisp image files and executables.
Currently trivial-dump-core supports SBCL, Clozure CL and CLISP.
trivial-dump-core is available via quicklisp:
(ql:quickload "trivial-dump-core")
The source repository is at https://github.com/rolando2424/trivial-dump-core
There are three main functions in trivial-dump-core:
- dump-image
- dump-image-init
- save-executable
The dump-image
function is used to freeze the state of your Lisp
session and store it in an “image file.” You can then, at a later
time, load that image file back into your Lisp implementation.
The dump-image
function takes the path of the image file as its
only argument.
The save-executable
function creates an executable file that
includes the Lisp image (you can distribute it as-is without
needing to install the Lisp implementation on the target
machine). Some implementations (Clozure, SBCL) will exit after this
function is called.
The save-executable
function takes 3 arguments:
filename
- Path of the executable fileinit-function
- Zero-argument function object that acts as the entry point to your executable (the equivalent of main() in C).
Almost the same as dump-image, but takes and init-function argument, like save-executable.
Let’s open up, for example, Clozure CL:
rolando@rolando-desktop:~$ ccl Welcome to Clozure Common Lisp Version 1.7-r14925M (LinuxX8632)! ?
Now we load trivial-dump-core (we assume you have quicklisp installed already).
? (ql:quickload "trivial-dump-core") To load "trivial-dump-core": Load 1 ASDF system: trivial-dump-core ; Loading "trivial-dump-core" [package trivial-dump-core] (TRIVIAL-DUMP-CORE) ?
Let’s define a new function:
? (defun hello-world ()
(format t "Hello, World!"))
HELLO-WORLD
?
So now this lisp interpreter has a function called
hello-world
. Let’s save dump the interpreter state to a file
called “my-core.ccl”:
? (trivial-dump-core:dump-image "my-core.ccl") To run the image, use the following command in the terminal: ccl -I my-core.ccl rolando@rolando-desktop:~$
You’ll notice that we’re back in the command-line. This behaviour is implementation-dependent. For example, in CLISP you stay in the REPL even after creating an image.
Also notice the command ccl -I my-core.ccl
appeared. That’s the command
you have to type in the command-line to make ccl open the image you
just created. Even though the specific flags you need to use change
from implementation to implementation, trivial-dump-core will
always show you the command you need to use to open back the image.
So let’s open it.
rolando@rolando-desktop:~$ ccl -I my-core.ccl Welcome to Clozure Common Lisp Version 1.7-r14925M (LinuxX8632)! ?
So far, everything is the same as usual right? However, before
creating this image, we defined a new function called
hello-world
. This function should still exist, even though we
closed the lisp interpreter.
? (hello-world)
Hello, World!
NIL
?
As you can see, the function still exists.
Currently, you can use the dump-image
function in SBCL, CLISP and
Clozure CL.
Keep in mind that you can’t open an image using a implementation that’s different from the one that created it, ie. you can’t create an image in SBCL and then open it in CLISP.
This time, let’s open up SBCL.
rolando@rolando-desktop:~$ sbcl This is SBCL 1.0.55, an implementation of ANSI Common Lisp. More information about SBCL is available at <http://www.sbcl.org/>. SBCL is free software, provided as is, with absolutely no warranty. It is mostly in the public domain; some portions are provided under BSD-style licenses. See the CREDITS and COPYING files in the distribution for more information. *
As before, we’ll need to load trivial-dump-core using quicklisp.
* (ql:quickload 'trivial-dump-core) To load "trivial-dump-core": Load 1 ASDF system: trivial-dump-core ; Loading "trivial-dump-core" [package trivial-dump-core] (TRIVIAL-DUMP-CORE) *
Let’s define a new function.
* (defun hello-world () (format t "Hello, World!~%")) HELLO-WORLD *
Finally, we create an executable with the name “sbcl-hello-world”
using the save-executable
function, using the hello-world
has
the entry point.
* (trivial-dump-core:save-executable "sbcl-hello-world" #'hello-world) [undoing binding stack and other enclosing state... done] [saving current Lisp image into sbcl-hello-world: writing 3512 bytes from the read-only space at 0x01000000 writing 2224 bytes from the static space at 0x01100000 writing 32231424 bytes from the dynamic space at 0x09000000 done] rolando@rolando-desktop:~$
As it already happened with Clozure CL during the dump-image
example, what happens after you call save-executable
is
implementation-dependent. In this case, the lisp interpreter closed
and we are back in the command-line.
However, there’s now a new executable file in the folder. Let’s run it.
rolando@rolando-desktop:~$ ./sbcl-hello-world Hello, World! rolando@rolando-desktop:~$
There a problem with saving core images in SBCL when it’s running more than one thread, as is the case with the SBCL+Slime combination.
So to use trivial-dump-core with SBCL running with a Slime prompt, the process is a little different.
You call the functions dump-image
and save-executable
as usual,
but those functions instead of working the normal way, they print
out a sexp that you need to evaluate in the *inferior-lisp*
buffer.
Inside emacs press C-u M-x slime RET sbcl RET
.
When the prompt opens, load trivial-dump-core as normal.
CL-USER> (ql:quickload 'trivial-dump-core) To load "trivial-dump-core": Load 1 ASDF system: trivial-dump-core ; Loading "trivial-dump-core" (TRIVIAL-DUMP-CORE) CL-USER>
Let’s create a new image using dump-image
.
CL-USER> (trivial-dump-core:dump-image "sbcl-slime") Cannot dump an sbcl image from inside Slime. Please go to the *inferior-lisp* buffer in emacs and run the following code: (trivial-dump-core::sbcl-dump-image-slime "sbcl-slime") NIL CL-USER>
Notice the sexp in the message. Copy it into emacs’ kill-ring and
open the *inferior-lisp*
buffer using C-x b *inferior-lisp* RET
and paste the sexp there.
* (trivial-dump-core::sbcl-dump-image-slime "sbcl-slime") ;; swank:close-connection: NIL To run the image, use the following command in the terminal: sbcl --core sbcl-slime [undoing binding stack and other enclosing state... done] [saving current Lisp image into sbcl-slime: writing 3512 bytes from the read-only space at 0x01000000 writing 2224 bytes from the static space at 0x01100000 writing 35590144 bytes from the dynamic space at 0x09000000 done] Process inferior-lisp finished
The end result is a core file similar to one created in the command-line.
The same thing happens when you try to use save-executable
with
SBCL in Slime.
CL-USER> (ql:quickload 'trivial-dump-core) To load "trivial-dump-core": Load 1 ASDF system: trivial-dump-core ; Loading "trivial-dump-core" (TRIVIAL-DUMP-CORE) CL-USER> (trivial-dump-core:save-executable "sbcl-exec-slime" #'(lambda () (format t "Hello, World!"))) Cannot run save an sbcl image from inside Slime. Please go to the *inferior-lisp* buffer in emacs and run the following code: (trivial-dump-core::sbcl-save-slime-and-die "sbcl-exec-slime" #'(LAMBDA () (FORMAT T "Hello, World!"))) NIL CL-USER>
Copy and paste the form into the *inferior-lisp*
buffer to create
an executable.
* (trivial-dump-core::sbcl-save-slime-and-die "sbcl-exec-slime" #'(LAMBDA () (FORMAT T "Hello, World!"))) ;; swank:close-connection: NIL [undoing binding stack and other enclosing state... done] [saving current Lisp image into sbcl-exec-slime: writing 3512 bytes from the read-only space at 0x01000000 writing 2224 bytes from the static space at 0x01100000 writing 35340288 bytes from the dynamic space at 0x09000000 done] Process inferior-lisp finished