How to make executable files with CMUCL on Linux

Start by creating the file start.lisp in your CMUCLLIB directory (e.g., /usr/lib/cmucl/):

(in-package "COMMON-LISP-USER")

(setq ext::*complain-about-illegal-switches* nil)

;; Delete the command-line arguments that loaded this file
(pop lisp::lisp-command-line-list)
(do ((opt (pop lisp::lisp-command-line-list)
          (pop lisp::lisp-command-line-list)))
    ((char/= (schar opt 0) #\-)))

(ext::process-command-strings)
(setq ext::*complain-about-illegal-switches* t)

;; Allow a #! line on source files
(set-dispatch-macro-character #\# #\!
  (lambda (stream bang arg)
    (declare (ignore bang arg))
    (read-line stream)
    (values)))

(let ((file (first lisp::lisp-command-line-list)))
  (unwind-protect
      (when file (load file))
    (ext:quit)))

Compile it: lisp -eval '(compile-file "start") (quit)' and make sure any user can load it: chmod 644 start.x86f.

Put the following in /usr/local/bin/runlisp (adjusting the path to your lisp executable, if necessary):

#!/bin/sh
#
exec /usr/bin/lisp -quiet -batch -noinit -load library:start "$@"
and make it executable: chmod 755 /usr/local/bin/runlisp.

Finally, load the binfmt_misc kernel module and tell it about Lisp. You may want to do this in your boot scripts (e.g., /etc/rc.d/rc.local).

/sbin/modprobe binfmt_misc
echo :lisp:M::FASL FILE::/usr/local/bin/runlisp: >/proc/sys/fs/binfmt_misc/register

Now you should be able to run FASL (.x86f) files directly from your shell (after marking them executable with chmod), and if you put a #!/usr/local/bin/runlisp line in Lisp source files and mark them executable, you'll be able to run them, too.