From: Andy Cristina
Subject: Clisp executable solution -- Feedback requested.
Date: 
Message-ID: <VIm7e.4088$9S4.1882@okepread06>
So, I'm going to this programming contest at the University of New 
Orleans this weekend, and my team wishes to use lisp.  The rules are 
that any language that can make an exe and read and write to std in can 
be used.  And fit on a floppy.  And run on windows XP.  So, this isn't 
so good for lisp.  I talked to the coordinator, and got permission to 
turn in our submissions on either CD or a usb stick, and I'm going to 
convince them that a bat file is just as good as an exe.  Especially 
since one of the officially supported languages is java.

Anyway, tonight I wrote a small program to automate making deliverable 
clisp systems.  Its not all that complete, but I'd appreciate any feedback.

The code and examples are available at 
http://www.andystuff.com/clisp-build.zip and I've included the 
build.lisp file below.

;; build.lisp
;; atc 4/13/05
;; System for making a clisp "exe"
;; if I accidentally used clisp internals
;;    this code is licensed under the GPL v2 or greater
;;   this code is licensed in the public domain.

(defparameter *compiler-dir* "C:\\clisp-2.33.1\\"
   "The directory where clisp resides.")

(defun build-distribution (filename)
   "builds a bat file for clisp distribution.
    Reads a definition file, and makes the distribution.

    Format for def file is...
    (<app-name> <dest-dir> <full | base>
     (<file-to-load>*) | <image.mem>
     <entry-function>)

    Where app-name is the name of your application,
    dest-dir is the directory you wish to store the bundle in,
    (please use the correct slash for your system!)
    specify if you want a full or base compiler used,
    a list of files that should be loaded, in order, or an existing image
    and a function with no arguments that will act as
    the entry point."
   (with-open-file (fp filename)
     (let ((data (read fp)))
       (when data
	(let ((name (first data))
	      (dir (second data))
	      (full-p (equalp 'full (third data)))
	      (files (fourth data))
	      (entry (fifth data)))
	  (build-dist name dir full-p files entry))))))

(defun build-dist (name dir full-p files entry)
   "Does all the hard work of building the system.
    See build-distribution"
   (maybe-create-directory dir)
   (let ((image (if (listp files)
		   (progn
		     ;; Have to build a memory image now...
        		     ;; So make a lisp file that the compiler will use
		     ;; to generate the image.
		     (generate-image files (format nil "~A.mem" name)
				     dir full-p))
		   (copy-mem-image files dir))))
     (build-bat-file name dir image entry)
     (copy-runtime-files dir full-p)))

(defun build-bat-file (name dir image entry)
   "Builds a clisp batch file"
   (with-open-file (stream (format nil "~A~A.bat" dir name)
			  :direction :output :if-exists :supersede)
     (format stream ·@echo off~%~A\\lisp.exe -B \"~A\\\" -M \"~A\\~A\" 
--silent -norc -x \"(progn (~A) (values))\"~%"
	    dir dir dir image entry)))


(defun maybe-create-directory (dir)
   "Creates the directory dir if it does not exist."
   (unless (directory dir)
     (ext:run-program (format nil "mkdir ~A" dir) :indirectp t)))

(defun copy-runtime-files (dst full-p)
   "Copies the lisp.exe to the dst directory"
   (let ((src (format nil "~A~A\\"
		     *compiler-dir* (if full-p
					"full"
					"base"))))
     (my-copy-file (format nil "~Alisp.exe" src) dst)))


(defun copy-mem-image (image dst)
   "Copies the memory file to the destination directory."
   (my-copy-file image dst)
   (file-namestring image))

(defun my-copy-file (src dst)
   "Copies a src file to a dst file.
    dst may be a directory, in which case the file will be
    copied to that directory."
   (ext:run-program (format nil "copy ~A ~A" src dst) :indirectp t))

(defun generate-image (files image-name dst full-p)
   "Calls the correct clisp to build these lisp or fasl files into a 
memory image."
   (with-open-file (stream (format nil "~Amk-bld-sys.lisp" dst)
			  :direction :output
			  :if-exists :supersede)
     (format stream "~{(load ~S)~%~}(ext:saveinitmem ~S)"
	    files (concatenate 'string dst image-name)))
   (ext:run-program (format nil "~A ~A ~A"
			   (concatenate 'string *compiler-dir* 
        					"compiler.bat")
			   (if full-p "full" "base")
			   (concatenate
			    'string
			    dst "mk-bld-sys.lisp")) :indirectp t)
   image-name)

			
From: Sam Steingold
Subject: Re: Clisp executable solution -- Feedback requested.
Date: 
Message-ID: <u3bttzdpa.fsf@gnu.org>
> * Andy Cristina <·············@tznvy.pbz> [2005-04-13 23:55:34 -0500]:
>
> (defun maybe-create-directory (dir)
>    "Creates the directory dir if it does not exist."
>    (unless (directory dir)
>      (ext:run-program (format nil "mkdir ~A" dir) :indirectp t)))

<http://clisp.cons.org/impnotes/file-dict.html#make-dir>
<http://www.lisp.org/HyperSpec/Body/fun_ensure-di_tories-exist.html>

> (defun my-copy-file (src dst)
>    "Copies a src file to a dst file.
>     dst may be a directory, in which case the file will be
>     copied to that directory."
>    (ext:run-program (format nil "copy ~A ~A" src dst) :indirectp t))

<http://www.podval.org/~sds/clisp/impnotes/syscalls.html#copy-file>

> (defun generate-image (files image-name dst full-p)
>    "Calls the correct clisp to build these lisp or fasl files into a
>    memory image."
>    (with-open-file (stream (format nil "~Amk-bld-sys.lisp" dst)
> 			  :direction :output
> 			  :if-exists :supersede)
>      (format stream "~{(load ~S)~%~}(ext:saveinitmem ~S)"
> 	    files (concatenate 'string dst image-name)))
>    (ext:run-program (format nil "~A ~A ~A"
> 			   (concatenate 'string *compiler-dir*
> 			   "compiler.bat")
> 			   (if full-p "full" "base")
> 			   (concatenate
> 			    'string
> 			    dst "mk-bld-sys.lisp")) :indirectp t)
>    image-name)

I don't think you need the intermediate mk-bld-sys.lisp file.

clisp -i file1 -i file2 -i file3 ... -x '(saveinitmem)'

will do.

-- 
Sam Steingold (http://www.podval.org/~sds) running w2k
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.honestreporting.com> <http://www.palestinefacts.org/>
We are born naked, wet, and hungry.  Then things get worse.