All Manuals > LispWorks® User Guide and Reference Manual > 13 Customization of LispWorks

13.3 Saving a LispWorks image

There are two ways to save an image with changes pre-loaded.

13.3.1 The configuration file

First create a file my-configuration.lisp containing the settings you want in your saved image. You may want to change some of the pre-configured settings shown in config/configure.lisp, add customizations from the rest of this chapter, or load your application code.

13.3.2 The save-image script

Now create a save-image script which is a file save-image.lisp containing something like:

(in-package "CL-USER")
(load #-mswindows "/tmp/my-configuration.lisp"
      #+mswindows "C:/temp/my-configuration.lisp")
  "/Applications/LispWorks 8.0 (64-bit)/My")
 #-:cocoa "my-lispworks")

The script shown loads my-configuration.lisp from a temporary directory. You may need to modify this.

13.3.3 Save your new image

The simplest way to save your new image is to use the Application Builder tool in the LispWorks IDE. Start the Application Builder as described in the LispWorks IDE User Guide, enter the path of your save-image script in the Build script: pane, and press the Build the application using the script button.

Alternatively you can run LispWorks in a command interpreter and pass your save-image script in the command line as shown below.

For other platforms and for 64-bit LispWorks the image name varies from that shown, but the principle is the same.

13.3.4 Use your new image

Your new LispWorks image contains the settings you specified in my-configuration.lisp pre-loaded.

You can add further customizations on start up via the initialization files mentioned in 13.2.2 Initialization files.

Note that your newly saved image runs itself, not a saved session.

13.3.5 Saving a non-GUI image with multiprocessing enabled

To create an image which does not start the LispWorks IDE automatically, make a save-image script, for example in /tmp/resave.lisp, containing:

(in-package "CL-USER")
(save-image "~/lw-console"
            :console t
            :multiprocessing t
            :environment nil)

Run LispWorks like this to create the new image ~/lw-console:

lispworks-8-0-0-x86-linux -build /tmp/resave.lisp

13.3.6 Code signing in saved images

This section briefly describe when and how LispWorks images are code signed. Signing your development image

On Microsoft Windows and macOS you can sign a development image saved using save-image with the :split argument. Signing in the distributed LispWorks executable

The LispWorks Professional and Enterprise Edition images distributed are not signed, because of the complications around image saving and delivery that this would cause.

The LispWorks for Macintosh Personal Edition application bundle and the LispWorks for Windows Personal Edition executable are both signed in the name of LispWorks Ltd. Signing your runtime application

On Microsoft Windows and macOS you can sign a runtime executable or dynamic library which was saved using deliver with the :split argument.

13.3.7 Saving images and delivering on Apple silicon Macs

On Apple silicon Macs (based on the arm64 architecture), creating code dynamically like Lisp does using compile or when loading fasl files is not allowed by default. To be able to create code dynamically, LispWorks uses the macOS JIT mechanism, which involves mapping the code segments with MAP_JIT in the call to mmap, and using pthread_jit_write_protect_np to switch the status of the memory from executable to writable and back (MAP_JIT and pthread_jit_write_protect_np are macOS-specific features).

To be able to use the JIT mechanism, LispWorks executables must be signed with the entitltment set to true ("have the entitlement"). To be signed, the executable and Lisp heap must be split into separate files, which is controlled by the split argument in save-image and deliver. The released images on macOS are split, and the value of split in save-image and deliver defaults to t when they save executables. The executable they create inherits the signing and entitlements.

LispWorks can also run without the entitlement, and hence without the JIT mechanism, if it has the entitlement. But in this case it cannot create code dynamically, and will signal an error when an operation (loading a fasl or compile) tries to create code dynamically. This may be useful in a delivered application where the entitlement is undesirable from some reason, or when LispWorks is delivered as a dynamic library and loaded into a process that does not have Note that LispWorks itself occasionally use compile internally for various optimizations, which will also signal an error in this situation, so LispWorks should be delivered without the compiler to ensure that works properly (the keyword :redefine-compile-p in deliver needs to be non-nil).

When LispWorks is saved or delivered as a dynamic library and loaded by another process, then the entitlements that LispWorks has are the entitlements that the loading process has. If it has, then LispWorks can work as usual. If it does not have, but does have, then LispWorks can work, but cannot load fasl files or compile code using compile. Without either entitlements, LispWorks cannot work at all.

Since the entitlements of the dynamic library are not used, a LispWorks dynamic library itself does not need the entitlements above.

On iOS you cannot generate new code at all, and on Android the restrictions above do not apply, so when delivering to iOS or Android the discussion above does not apply.


You may already have code that passes :split nil to save-image or deliver, which will override the default and will produce an unspitted and unsigned image.

If you sign the executable yourself (recommended), you will have to ensure that it has one the or entitlements.

You will also need to have the entitlement if your application loads any shared libraries that are not signed by Apple or by your developer team ID. The released images on macOS have both and entitlements.

LispWorks® User Guide and Reference Manual - 01 Dec 2021 19:30:20