The typical route involves loading all of the program's code into the Lisp environment, dumping the current state of the Lisp process into a disk image, and identifying a start function (ie main).
Since the disk image contains the entire Common Lisp system (compiler, debugger, documentation strings, etc.), the executable will be typically larger than a compiled C program (even if you statically link the C code).
Another form of disk image requires a copy of the particular Lisp implementation to be installed on the recipient's machine. This is no different in principle from a C application requiring platform-specific dynamic libraries to run. This complicates deployment - the disk image is tied to a particular implementation version, and you typically end up having to include the Lisp implementation executable anyway.
Due to platform limitations, some Lisp implementations can't produce native executables (for example, ABCL can only make JAR files). Other implementations are only able to dump disk images that require a separate copy of the implementation executable. An alternative to executables is available on Unix platforms in the form of shell scripting.
There are a few tools designed to help with creating executables:
- buildapp - Buildapp is an SBCL tool for creating executables
- lisp-executable - The lisp-executable library provides a language for defining programs and creating executables from Lisp systems
- trivial-dump-core - trivial-dump-core is a small portability wrapper for dumping core and creating executables for CCL, CLISP, and SBCL
- Saving an Image on CLISP and Application Delivery for CLISP
- Saving a Core Image for SBCL
- Saving Applications on OpenMCL/Clozure Common Lisp
- Building standalone executables for ECL (which supports multiple methods of code delivery)
- Only supports creating executables on Linux and FreeBSD on x86 (see CMUCL FAQ)
The best support (tree shaking, binary patches, etc.) for executables is available in commercial implementations: