Certain implementations such as CLISP have a -c commandline switch that allows you to invoke the file compiler from the shell. CMUCL's commandline switches are user-extensible, so you can emulate this behaviour with code such as the following, in your site-init.lisp or ~/.cmucl-init initialization files.
(macrolet ((with-batch-processing (&body body) `(handler-case (prog1 t ,@body) (serious-condition (condition) (format *error-output* "Error in batch processing:~%~A~%" condition) (finish-output *error-output*) (throw 'lisp::%end-of-the-world 1)) (:no-error (value) (declare (ignore value)) (throw 'lisp::%end-of-the-world 0))))) (ext:defswitch "compile" #'(lambda (switch) (with-batch-processing (mapc #'compile-file (ext:cmd-switch-words switch))))) (ext:defswitch "compile-and-load" #'(lambda (switch) (with-batch-processing (mapc #'(lambda (file) (compile-file file :load t)) (ext:cmd-switch-words switch))))) ) ; macrolet
Now you can use the following to compile (and load) from the command line:
lisp -compile-and-load demo.lisp demo2.lisp
If errors are encountered during processing, CMUCL is aborted, with a return value of 1, otherwise it returns 0 (i.e. success). This can be combined with the -quiet flag (put it at the start of the commandline) if wanted.
An alternative to this form of interaction with the file compiler is to load the files and compile them from a stream, so you don't have any FASL files hanging around on disk (thus avoiding problems with binary compatibility between different CMUCL releases), yet still benefit from compiled performance. You can do this with code such as:
(defun process-switch-demon (switch) (let ((files (copy-list (ext:cmd-switch-words switch)))) (push #'(lambda () (dolist (file files) (format *terminal-io* "~&;;; Processing compiled code from ~A.~%" file) (with-open-file (s file) (ext:compile-from-stream s)))) *run-actions*))) (ext:defswitch "process" #'process-switch-demon)
Adapted from article firstname.lastname@example.org posted to comp.lang.lisp by Pierre Mai, on 2001-11-30.