From: Jeff Dalton
Subject: Re: Q: How do I compile Lisp source into an executable?
Date:
Message-ID: <D5t3G9.ED3@cogsci.ed.ac.uk>
In article <··········@eclipse.torolab.ibm.com> ·····@flogger.torolab.ibm.com (Itrat Khan) writes:
>Is there a way to compile a Lisp program? I've read the FAQ which makes
>it sound like you can't or that it's not a standard thing. I'm using
>GNU Common Lisp 1.0 for AIX to run a short LISP program. I'd like this
>program to be a standalone executable. Currently, I do something like
>this:
>
> gcl < source.lsp
>
>to run my Lisp code. Unfortunately, this dumps out all the "interactive"
>stuff like the results of a setq and stuff. This still works for me
>since all my output goes to files, but it's ugly. (Can you turn this
>output off?)
>
>I find it hard to believe that something as old as Lisp can't be compiled
>into an executable. I'd appreciate any suggestions or explanations about
>compiling Lisp programs. For now, I'll just keep using the interpreter.
Distinguish between:
Lisp (a family of languages),
Common Lisp (one language in the family),
Common Lisp implementations.
Lisp (the family) is fairly old. The present-day languages and
implementations are less so. A number of Lisps are small and easy
to implement as interpreters. A compiler is harder. So there
are a large number of Lisp interpreters out there. However,
Lisp compilers are fairly common. Almost all Common Lisp
implementations have a compiler of one sort or another.
Most compile to machine code, but there's at least one byte-compiler.
Whether a compiler exists and how it's used depends on the language
and the implementation.
In Common Lisp, you can use the function compile-file to compile
a file of Lisp code. The load function can be used to load both
compiled and non-compiled files. In GCL on ondinary Unix machines
(I don't know about the AIX version), you can save an image with
si:save-system. This saves the whole GCL system, plus any code
you've loaded in. The result is kind of large. Other Lisps
might let you save something much smaller.
Example:
Run GCL and type
(compile-file "mycode.lsp")
[Optionally] exit and rerun it (so you get a cleaner image). Then:
(load "mycode.o")
(si:save-system "mysystem")
The file mysystem should be an executable. It will behave like an
ordinary GCL except that your code will be built-in. However, you
can change its behavior by redefining si:top-level. When doing
this, I use the following, which I define in different ways for
different Common Lisps (this is the AKCL/GCL version):
(defun save-image (filename top-level-fn)
(setf (symbol-function 'si:top-level)
top-level-fn)
(si:save-system filename))
I also define things like this (again the AKCL/GCL versions):
(defun argc ()
(si:argc))
(defun argv (n) ; -> string or nil
(if (< n (si:argc))
(si:argv n)
nil))
And here's an example of a top-level fn that can be installed as
si:top-level (as above):
(defun a-top-level ()
(handler-bind ((condition #'last-resort-condition-handler))
(top-level-init)
(main-program)
(bye 0)))
(defun top-level-init ()
(let ((init-file-p t)
(i 1))
(labels ((arg ()
(argv i))
(pop-arg ()
(prog1 (arg) (incf i))))
(loop
(when (null (arg))
(return))
(case (intern (string-upcase (arg)))
(-load (pop-arg) (load (pop-arg)))
(-break (pop-arg) (break "~A" '-break))
(-eval (pop-arg) (eval (read-from-string (pop-arg))))
...)))))
An alternative to building a large image is to write a shell script
that runs GCL (or perhaps a modified GCL) and tells it to load
your compiled code. By a "modified GCL" I have in mind that you
would save a full image, but it would be one that you could use
in a number of different cases. For instance, you might provide
convenient command-line arguments as in a-top-level above.
-- jd