[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Delivering Systems

    Date: Thu, 8 Oct 1992 23:05 EDT
    From: chyde@chesapeake.ads.com (Clinton Hyde)

    I have a defsystem I want to deliver sans source-code. how do I manage
    this? at the moment, Genera appears to always check for the existence
    of source files.

     -- clint

I'm sending you a short version of an answer to your question. If you
want a fuller explanation and all of the code involved I'll send it.

First, I use the same source files for Genera, Lucid, Franz, and MCL
running on Symbolics, Suns, and Macs. All of the customization is done
on the SYSTEM.LISP file and is handled via the *FEATURES* variable.
(If *FEATURES* is something you don't know about, you must look it up.
Also, evaluate it on your systems to get a feel for what is contains.)
Thus, SYSTEM.LISP suffers from a split personality. The result is
positive, that the other files aren't cluttered up by machine- or
version-specific details. Moreover, when things don't work, you tinker
with only the system file.

Some of the features of my system files are given below. By the way,
FBI is the name of the system I'll be using as an example. Here is the
goal: the user connects to the proper directory, enters Lisp, types
1(load "system.lisp")0 and (define-fbi ... ) with appropriate arguments,
and then the system loads and the CLIM user interface pops up. Voila!

Things to note about the system file:

Start with (in-package "CL-USER"). 

Here's a typical use of *FEATURES*:

  2; Unlock the packages that Allegro wants to lock.
0  #+:allegro (setf excl:*enable-package-locked-errors* nil)

The most difficult thing is the DEFPACKAGE, because that's what
reflects most of the inter-system differences. (Start simple. Fix what
breaks incrementally.) For example, I use ARGLIST explicitly so I need

  #+:allegro (:shadowing-import-from "EXCL" arglist)

The above is CL syntax, which imports FROM. In Genera it's different; 
the package-referenced symbols to be imported are given:

  #+:Genera (:shadowing-import
	       conditions:handler-case ... clos:defmethod  ...)

Of course, in Genera, I next evaluate the DEFSYSTEM,

  #+:genera (defsystem 3fbi0 (:pretty-name "..." ... ) ... ),

which gives me all I want on my Lisp machine. But on all systems, even
the Lisp machine, I define an alternate set of functions to do what we
think of as "Load System" and "Compile System".

Among the variables I have a list of files that define the system:

  (defvar 3fbi-files-in-use0 
    '("basics" "fcn-handlers" ... #-:lucid "clim-tools" ... 
      #+:genera "documentation-aux" ... ))

You may ask "where's the rest of these pathnames?" In lieu of CL's
logical pathname mechanism, I use the *FEATURES* to determine strings
for directories (the source and compiled files need not be on the same
directory) and extensions, such as "lisp" or "lsp", or "bin", "ibin",
or "fasl". When it's a system on which FBI has been previously
installed, they are correct; otherwise, they are educated guesses and
the user is prompted to accept or replace them during initialization,
that is, the running of DEFINE-FBI. For example, on this MacIvory,
named Henry,

  (fbi-pathnames) --> ("cleves:>fbi>clos>*.lisp" 

Now we're down to code that does the loading and compiling.

2  ; Compiles a source file if it's newer than its compiled version.
0  (defun 3compile-if-needed0 (source-pathname compiled-pathname)
    (when (not (probe-file source-pathname))
      (warn "Can't find the file ~a." source-pathname)
      (return-from compile-if-needed nil))
    (unless (and (probe-file compiled-pathname)
		 (< (file-write-date source-pathname)
		    (file-write-date compiled-pathname)))
      (compile-file source-pathname :output-file compiled-pathname)))

In the next function I have put in italics my way of dealing with the
two files that are the only ones defining macros. I did this quite a
while ago and now I'm not sure that it is necessary.

  (defun 3define-fbi0 (&optional recompile? ...
    &aux (pathnames (fbi-pathnames))
	 (source-pathname (first pathnames))
	 (compiled-pathname (second pathnames)))
    (dolist (name fbi-files-in-use)
      (let ((source-pathname (merge-pathnames name source-pathname))
	    (compiled-pathname (merge-pathnames name compiled-pathname)))
	2(when (member name '("basics" "clos-utilities") :test #'string-equal)
	  (load source-pathname))
0	(if recompile?
	    (compile-file source-pathname :output-file compiled-pathname)
	    (compile-if-needed source-pathname compiled-pathname))
	(load compiled-pathname)))
    ... )

Good luck,
Bud Frawley