Go to the previous, next section.

The ILU Common Lisp Portable DEFSYSTEM Module

The ILU Common Lisp support uses files called `sysdcl's to describe the generated lisp files for a particular interface. A sysdcl is similar to a UNIX `Makefile', in that it describes the dependencies of the files of a module on each other. As part of ILU, we supply an implementation of a sysdcl interpreter, implemented in the DEFSYSTEM package (which is also nicknamed PDEFSYS). The notion is that to load a module, the user loads the sysdcl which describes it, then uses the DEFSYSTEM commands to compile and load the files of that module. The rest of this section describes this system in more detail. All symbols described here are in the pdefsys package unless otherwise specified.

Function: pdefsys:set-system-source-file (NAME string) (PATHNAME pathname)

Informs the defsystem utility that the definition of the system name can be found by loading the file pathname.

Function: pdefsys:load-system-def (NAME (or symbol string) &optional (RELOAD boolean t) => boolean

If there is a system named name and reload is false (the default), does nothing. Otherwise, loads the system defintion from a file. If pdefsys:set-system-source-file has been used to give an explicit source file for the system defintion, that file is used. Otherwise the file `NAME-sysdcl.lisp' is loaded from the directory specified in pdefsys:*sysdcl-pathname-defaults* if such a file exists. Returns false if the system was not loaded and is not already defined, true otherwise.

Variable: pdefsys:*sysdcl-pathname-defaults*

Specifies the location for system declaration files. *sysdcl-pathname-defaults* is a list of pathnames; each location is searched for the declaration file. The default value is (list #P"/import/commonlisp-library/sysdcl/").

Macro: pdefsys:defsystem (NAME string) (SYSTEM-OPTIONS plist) &rest (MODULE-DESCRIPTIONS module-list)

The name of the system (which is interned in the current package), is used by defsystem to allow dependencies between multiple systems.

The SYSTEM-OPTIONS is a plist which may contain each of the following keywords:

The module-descriptions is a list of modules which make up a system. A module is a list whose car is the module name and whose cdr is a list of keywords and values. The module keywords may contain each of the following:

Variable: pdefsys:*language-descriptions*

An alist describing how files written in different languages are compiled and loaded. Each entry in the list is of the form (language-name source-file-type binary-file-type compile-fn load-fn). The language-name is the (keyword) name of the language. Source-file-type and binary-file-type are lists of strings; they are the file-types for source and binary files for the language. The compile-fn is symbol that will be called with three arguments to compile the source file; the pathname of the source file, the pathname of the binary output file, and a list of the optimizations declared for the module. Load-fn is a symbol that will be called with two required argument to load the binary file: the pathname of the binary, and a list of object library files to use.

The initial value of *language-descriptions* contains a description of :lisp, :k&r-c and :ansi-c languages. The description of :lisp uses the second argument to the compile-fn as a list of compiler optimization settings. The description of :k&r-c and :ansi-c uses the list as a set of additional arguments to pass to the C compiler.

Macro: pdefsys:undefsystem (NAME (or symbol string))

This macro removes the named system description from the list of all systems.

Function: pdefsys:load-system (NAME (or symbol string)) &key (RELOAD boolean nil) (RECURSE boolean nil) (TRACE boolean nil) (SOURCE-IF-NEWER boolean nil)

This function loads the modules of the system with the specified name and is called recursively for all required systems. While the system is being loaded, the special variable pdefsys:*current-system* is bound to the name of the system.

The keyword args act as follows:

Function: pdefsys:compile-system (NAME (or string symbol)) &key (RECOMPILE boolean nil) (RELOAD boolean nil) (PROPAGATE boolean nil) (TRACE boolean nil) (INCLUDE-COMPONENTS boolean nil)

This function compiles the modules of the system with the specified name and is called recursively for all required systems. While the system is being compiled, the special variable pdefsys:*current-system* is bound to the name of the system.

The keyword args act as follows:

Function: pdefsys:show-system (NAME (or string symbol))

This function outputs a formatted description of the system with the specified NAME.

Pathname Support

Some lisps don't yet support the structured directories specified in CLtL2 (p. 620). To support those lisps, pdefsys contains two functions which do support some of that functionality.

Function: pdefsys:make-pathname &key host device directory name type version defaults

Function: pdefsys:pathname-directory pathname

These functions shadow the functions in the common-lisp package, and support the subdirectory list syntax described as follows (From the X3J13 PATHNAME-SUBDIRECTORY-LIST proposal):

It is impossible to write portable code that can produce a pathname in a subdirectory of a hierarchical file system. This defeats much of the purpose of the pathname abstraction.

According to CLtL, only a string is a portable value for the directory component of a pathname. Thus in order to denote a subdirectory, the use of punctuation characters (such as dots, slashes, or backslashes) would be necessary. The very fact that such syntax varies from host to host means that although the representation might be "portable", the code using that representation is not portable.

This problem is even worse for programs running on machines on a network that can retrieve files from multiple hosts, each using a different OS and thus different subdirectory punctuation.

Proposal:

Allow the value of a pathname's directory component to be a list. The car of the list is one of the symbols :ABSOLUTE or :RELATIVE. Each remaining element of the list is a string or a symbol (see below). Each string names a single level of directory structure. The strings should contain only the directory names themselves -- no punctuation characters.

A list whose car is the symbol :ABSOLUTE represents a directory path starting from the root directory. The list (:ABSOLUTE) represents the root directory. The list (:ABSOLUTE "foo" "bar" "baz") represents the directory called "/foo/bar/baz" in Unix [except possibly for alphabetic case -- that is the subject of a separate issue].

A list whose car is the symbol :RELATIVE represents a directory path starting from a default directory. The list (:RELATIVE) has the same meaning as nil and hence is not used. The list (:RELATIVE "foo" "bar") represents the directory named "bar" in the directory named "foo" in the default directory.

Here's an sample sysdcl file that shows how the DEFSYSTEM functions and these pathname functions work together.

  (in-package "DEFSYSTEM")
  
  (defvar *my-system-default-directory*
    (make-pathname :directory
                   '(:absolute "import" "my-system" "release-1.0")))
  
  (set-system-source-file :mysys-test
    (make-pathname :directory '(:relative "test")
                   :name "test-sysdcl"
                   :defaults *my-system-default-directory*))
  
  (defsystem :my-system (:default-pathname *my-system-default-directory*
                         :default-package "USER"
                         :load-before-compile ()
                         :needed-systems ())
    ...)

Go to the previous, next section.