trivial-dump-core

2017-02-27

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.

Installation

trivial-dump-core is available via quicklisp:

  (ql:quickload "trivial-dump-core")

The source repository is at https://github.com/rolando2424/trivial-dump-core

Library functions

There are three main functions in trivial-dump-core:

  • dump-image

  • dump-image-init

  • save-executable

dump-image

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.

save-executable

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 file

  • init-function - Zero-argument function object that acts as the entry point to your executable (the equivalent of main() in C).

dump-image-init

Almost the same as dump-image, but takes and init-function argument, like save-executable.

Examples

dump-image

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.

save-executable

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:~$

SBCL and Slime

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.

Example

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
Author
Rolando Pereira <rolando_pereira_2@hotmail.com>
License
MIT License
Categories
creating executables, mit-license