1 ;;; -*- Mode: Lisp; Package: make -*-
2 ;;; -*- Mode: CLtL; Syntax: Common-Lisp -*-
4 ;;; DEFSYSTEM 3.4 Interim 3.
8 ;;; ****************************************************************
9 ;;; MAKE -- A Portable Defsystem Implementation ********************
10 ;;; ****************************************************************
12 ;;; This is a portable system definition facility for Common Lisp.
13 ;;; Though home-grown, the syntax was inspired by fond memories of the
14 ;;; defsystem facility on Symbolics 3600's. The exhaustive lists of
15 ;;; filename extensions for various lisps and the idea to have one
16 ;;; "operate-on-system" function instead of separate "compile-system"
17 ;;; and "load-system" functions were taken from Xerox Corp.'s PCL
20 ;;; This system improves on both PCL and Symbolics defsystem utilities
21 ;;; by performing a topological sort of the graph of file-dependency
22 ;;; constraints. Thus, the components of the system need not be listed
23 ;;; in any special order, because the defsystem command reorganizes them
24 ;;; based on their constraints. It includes all the standard bells and
25 ;;; whistles, such as not recompiling a binary file that is up to date
26 ;;; (unless the user specifies that all files should be recompiled).
28 ;;; Originally written by Mark Kantrowitz, School of Computer Science,
29 ;;; Carnegie Mellon University, October 1989.
31 ;;; MK:DEFSYSTEM 3.4 Interim 3
33 ;;; Copyright (c) 1989 - 1999 Mark Kantrowitz. All rights reserved.
34 ;;; 1999 - 2004 Mark Kantrowitz and Marco Antoniotti. All
37 ;;; Use, copying, modification, merging, publishing, distribution
38 ;;; and/or sale of this software, source and/or binary files and
39 ;;; associated documentation files (the "Software") and of derivative
40 ;;; works based upon this Software are permitted, as long as the
41 ;;; following conditions are met:
43 ;;; o this copyright notice is included intact and is prominently
44 ;;; visible in the Software
45 ;;; o if modifications have been made to the source code of the
46 ;;; this package that have not been adopted for inclusion in the
47 ;;; official version of the Software as maintained by the Copyright
48 ;;; holders, then the modified package MUST CLEARLY identify that
49 ;;; such package is a non-standard and non-official version of
50 ;;; the Software. Furthermore, it is strongly encouraged that any
51 ;;; modifications made to the Software be sent via e-mail to the
52 ;;; MK-DEFSYSTEM maintainers for consideration of inclusion in the
53 ;;; official MK-DEFSYSTEM package.
55 ;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
56 ;;; EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
57 ;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
58 ;;; IN NO EVENT SHALL M. KANTROWITZ AND M. ANTONIOTTI BE LIABLE FOR ANY
59 ;;; CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
60 ;;; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
61 ;;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
63 ;;; Except as contained in this notice, the names of M. Kantrowitz and
64 ;;; M. Antoniotti shall not be used in advertising or otherwise to promote
65 ;;; the sale, use or other dealings in this Software without prior written
66 ;;; authorization from M. Kantrowitz and M. Antoniotti.
69 ;;; Please send bug reports, comments and suggestions to <marcoxa@cons.org>.
71 ;;; ********************************
72 ;;; Change Log *********************
73 ;;; ********************************
75 ;;; Note: Several of the fixes from 30-JAN-91 and 31-JAN-91 were done in
76 ;;; September and October 1990, but not documented until January 1991.
78 ;;; akd = Abdel Kader Diagne <diagne@dfki.uni-sb.de>
79 ;;; as = Andreas Stolcke <stolcke@ICSI.Berkeley.EDU>
80 ;;; bha = Brian Anderson <bha@atc.boeing.com>
81 ;;; brad = Brad Miller <miller@cs.rochester.edu>
82 ;;; bw = Robert Wilhelm <wilhelm@rpal.rockwell.com>
83 ;;; djc = Daniel J. Clancy <clancy@cs.utexas.edu>
84 ;;; fdmm = Fernando D. Mato Mira <matomira@di.epfl.ch>
85 ;;; gc = Guillaume Cartier <cartier@math.uqam.ca>
86 ;;; gi = Gabriel Inaebnit <inaebnit@research.abb.ch>
87 ;;; gpw = George Williams <george@hsvaic.boeing.com>
88 ;;; hkt = Rick Taube <hkt@cm-next-8.stanford.edu>
89 ;;; ik = Ik Su Yoo <ik@ctt.bellcore.com>
90 ;;; jk = John_Kolojejchick@MORK.CIMDS.RI.CMU.EDU
91 ;;; kt = Kevin Thompson <kthompso@ptolemy.arc.nasa.gov>
92 ;;; kc = Kaelin Colclasure <kaelin@bridge.com>
93 ;;; kmr = Kevin M. Rosenberg <kevin@rosenberg.net>
94 ;;; lmh = Liam M. Healy <Liam.Healy@nrl.navy.mil>
95 ;;; mc = Matthew Cornell <cornell@unix1.cs.umass.edu>
96 ;;; oc = Oliver Christ <oli@adler.ims.uni-stuttgart.de>
97 ;;; rs = Ralph P. Sobek <ralph@vega.laas.fr>
98 ;;; rs2 = Richard Segal <segal@cs.washington.edu>
99 ;;; sb = Sean Boisen <sboisen@bbn.com>
100 ;;; ss = Steve Strassman <straz@cambridge.apple.com>
101 ;;; tar = Thomas A. Russ <tar@isi.edu>
102 ;;; toni = Anton Beschta <toni%l4@ztivax.siemens.com>
103 ;;; yc = Yang Chen <yangchen%iris.usc.edu@usc.edu>
105 ;;; Thanks to Steve Strassmann <straz@media-lab.media.mit.edu> and
106 ;;; Sean Boisen <sboisen@BBN.COM> for detailed bug reports and
107 ;;; miscellaneous assistance. Thanks also to Gabriel Inaebnit
108 ;;; <inaebnit@research.abb.ch> for help with VAXLisp bugs.
110 ;;; 05-NOV-90 hkt Changed canonicalize-system-name to make system
111 ;;; names package independent. Interns them in the
112 ;;; keyword package. Thus either strings or symbols may
113 ;;; be used to name systems from the user's point of view.
114 ;;; 05-NOV-90 hkt Added definition FIND-SYSTEM to allow OOS to
115 ;;; work on systems whose definition hasn't been loaded yet.
116 ;;; 05-NOV-90 hkt Added definitions COMPILE-SYSTEM and LOAD-SYSTEM
117 ;;; as alternates to OOS for naive users.
118 ;;; 05-NOV-90 hkt Shadowing-import of 'defsystem in Allegro CL 3.1 [NeXT]
119 ;;; into USER package instead of import.
120 ;;; 15-NOV-90 mk Changed package name to "MAKE", eliminating "DEFSYSTEM"
121 ;;; to avoid conflicts with allegro, symbolics packages
122 ;;; named "DEFSYSTEM".
123 ;;; 30-JAN-91 mk Modified append-directories to work with the
124 ;;; logical-pathnames system.
125 ;;; 30-JAN-91 mk Append-directories now works with Sun CL4.0. Also, fixed
126 ;;; bug wrt Lucid 4.0's pathnames (which changed from lcl3.0
127 ;;; -- 4.0 uses a list for the directory slot, whereas
128 ;;; 3.0 required a string). Possible fix to symbolics bug.
129 ;;; 30-JAN-91 mk Defined NEW-REQUIRE to make redefinition of REQUIRE
130 ;;; cleaner. Replaced all calls to REQUIRE in this file with
131 ;;; calls to NEW-REQUIRE, which should avoid compiler warnings.
132 ;;; 30-JAN-91 mk In VAXLisp, when we redefine lisp:require, the compiler
133 ;;; no longer automatically executes require forms when it
134 ;;; encounters them in a file. The user can always wrap an
135 ;;; (eval-when (compile load eval) ...) around the require
136 ;;; form. Alternately, see commented out code near the
137 ;;; redefinition of lisp:require which redefines it as a
139 ;;; 30-JAN-91 mk Added parameter :version to operate-on-system. If it is
140 ;;; a number, that number is used as part of the binary
141 ;;; directory name as the place to store and load files.
142 ;;; If NIL (the default), uses regular binary directory.
143 ;;; If T, tries to find the most recent version of the
144 ;;; binary directory.
145 ;;; 30-JAN-91 mk Added global variable *use-timeouts* (default: t), which
146 ;;; specifies whether timeouts should be used in
147 ;;; Y-OR-N-P-WAIT. This is provided for users whose lisps
148 ;;; don't handle read-char-no-hang properly, so that they
149 ;;; can set it to NIL to disable the timeouts. Usually the
150 ;;; reason for this is the lisp is run on top of UNIX,
151 ;;; which buffers input LINES (and provides input editing).
152 ;;; To get around this we could always turn CBREAK mode
153 ;;; on and off, but there's no way to do this in a portable
155 ;;; 30-JAN-91 mk Fixed bug where in :test t mode it was actually providing
156 ;;; the system, instead of faking it.
157 ;;; 30-JAN-91 mk Changed storage of system definitions to a hash table.
158 ;;; Changed canonicalize-system-name to coerce the system
159 ;;; names to uppercase strings. Since we're no longer using
160 ;;; get, there's no need to intern the names as symbols,
161 ;;; and strings don't have packages to cause problems.
162 ;;; Added UNDEFSYSTEM, DEFINED-SYSTEMS, and DESCRIBE-SYSTEM.
163 ;;; Added :delete-binaries command.
164 ;;; 31-JAN-91 mk Franz Allegro CL has a defsystem in the USER package,
165 ;;; so we need to do a shadowing import to avoid name
167 ;;; 31-JAN-91 mk Fixed bug in compile-and-load-operation where it was
168 ;;; only loading newly compiled files.
169 ;;; 31-JAN-91 mk Added :load-time slot to components to record the
170 ;;; file-write-date of the binary/source file that was loaded.
171 ;;; Now knows "when" (which date version) the file was loaded.
172 ;;; Added keyword :minimal-load and global *minimal-load*
173 ;;; to enable defsystem to avoid reloading unmodified files.
174 ;;; Note that if B depends on A, but A is up to date and
175 ;;; loaded and the user specified :minimal-load T, then A
176 ;;; will not be loaded even if B needs to be compiled. So
177 ;;; if A is an initializations file, say, then the user should
178 ;;; not specify :minimal-load T.
179 ;;; 31-JAN-91 mk Added :load-only slot to components. If this slot is
180 ;;; specified as non-NIL, skips over any attempts to compile
181 ;;; the files in the component. (Loading the file satisfies
182 ;;; the need to recompile.)
183 ;;; 31-JAN-91 mk Eliminated use of set-alist-lookup and alist-lookup,
184 ;;; replacing it with hash tables. It was too much bother,
185 ;;; and rather brittle too.
186 ;;; 31-JAN-91 mk Defined #@ macro character for use with AFS @sys
187 ;;; feature simulator. #@"directory" is then synonymous
188 ;;; with (afs-binary-directory "directory").
189 ;;; 31-JAN-91 mk Added :private-file type of module. It is similar to
190 ;;; :file, but has an absolute pathname. This allows you
191 ;;; to specify a different version of a file in a system
192 ;;; (e.g., if you're working on the file in your home
193 ;;; directory) without completely rewriting the system
195 ;;; 31-JAN-91 mk Operations on systems, such as :compile and :load,
196 ;;; now propagate to subsystems the system depends on
197 ;;; if *operations-propagate-to-subsystems* is T (the default)
198 ;;; and the systems were defined using either defsystem
199 ;;; or as a :system component of another system. Thus if
200 ;;; a system depends on another, it can now recompile the
202 ;;; 01-FEB-91 mk Added default definitions of PROVIDE/REQUIRE/*MODULES*
203 ;;; for lisps that have thrown away these definitions in
204 ;;; accordance with CLtL2.
205 ;;; 01-FEB-91 mk Added :compile-only slot to components. Analogous to
206 ;;; :load-only. If :compile-only is T, will not load the
207 ;;; file on operation :compile. Either compiles or loads
208 ;;; the file, but not both. In other words, compiling the
209 ;;; file satisfies the demand to load it. This is useful
210 ;;; for PCL defmethod and defclass definitions, which wrap
211 ;;; an (eval-when (compile load eval) ...) around the body
212 ;;; of the definition -- we save time by not loading the
213 ;;; compiled code, since the eval-when forces it to be
214 ;;; loaded. Note that this may not be entirely safe, since
215 ;;; CLtL2 has added a :load keyword to compile-file, and
216 ;;; some lisps may maintain a separate environment for
217 ;;; the compiler. This feature is for the person who asked
218 ;;; that a :COMPILE-SATISFIES-LOAD keyword be added to
219 ;;; modules. It's named :COMPILE-ONLY instead to match
221 ;;; 11-FEB-91 mk Now adds :mk-defsystem to features list, to allow
222 ;;; special cased loading of defsystem if not already
224 ;;; 19-FEB-91 duff Added filename extension for hp9000/300's running Lucid.
225 ;;; 26-FEB-91 mk Distinguish between toplevel systems (defined with
226 ;;; defsystem) and systems defined as a :system module
227 ;;; of a defsystem. The former can depend only on systems,
228 ;;; while the latter can depend on anything at the same
230 ;;; 12-MAR-91 mk Added :subsystem component type to be a system with
231 ;;; pathnames relative to its parent component.
232 ;;; 12-MAR-91 mk Uncommented :device :absolute for CMU pathnames, so
233 ;;; that the leading slash is included.
234 ;;; 12-MAR-91 brad Patches for Allegro 4.0.1 on Sparc.
235 ;;; 12-MAR-91 mk Changed definition of format-justified-string so that
236 ;;; it no longer depends on the ~<~> format directives,
237 ;;; because Allegro 4.0.1 has a bug which doesn't support
238 ;;; them. Anyway, the new definition is twice as fast
239 ;;; and conses half as much as FORMAT.
240 ;;; 12-MAR-91 toni Remove nils from list in expand-component-components.
241 ;;; 12-MAR-91 bw If the default-package and system have the same name,
242 ;;; and the package is not loaded, this could lead to
243 ;;; infinite loops, so we bomb out with an error.
244 ;;; Fixed bug in default packages.
245 ;;; 13-MAR-91 mk Added global *providing-blocks-load-propagation* to
246 ;;; control whether system dependencies are loaded if they
247 ;;; have already been provided.
248 ;;; 13-MAR-91 brad In-package is a macro in CLtL2 lisps, so we change
249 ;;; the package manually in operate-on-component.
250 ;;; 15-MAR-91 mk Modified *central-registry* to be either a single
251 ;;; directory pathname, or a list of directory pathnames
252 ;;; to be checked in order.
253 ;;; 15-MAR-91 rs Added afs-source-directory to handle versions when
254 ;;; compiling C code under lisp. Other minor changes to
255 ;;; translate-version and operate-on-system.
256 ;;; 21-MAR-91 gi Fixed bug in defined-systems.
257 ;;; 22-MAR-91 mk Replaced append-directories with new version that works
258 ;;; by actually appending the directories, after massaging
259 ;;; them into the proper format. This should work for all
260 ;;; CLtL2-compliant lisps.
261 ;;; 09-APR-91 djc Missing package prefix for lp:pathname-host-type.
262 ;;; Modified component-full-pathname to work for logical
264 ;;; 09-APR-91 mk Added *dont-redefine-require* to control whether
265 ;;; REQUIRE is redefined. Fixed minor bugs in redefinition
267 ;;; 12-APR-91 mk (pathname-host nil) causes an error in MCL 2.0b1
268 ;;; 12-APR-91 mc Ported to MCL2.0b1.
269 ;;; 16-APR-91 mk Fixed bug in needs-loading where load-time and
270 ;;; file-write-date got swapped.
271 ;;; 16-APR-91 mk If the component is load-only, defsystem shouldn't
272 ;;; tell you that there is no binary and ask you if you
273 ;;; want to load the source.
274 ;;; 17-APR-91 mc Two additional operations for MCL.
275 ;;; 21-APR-91 mk Added feature requested by ik. *files-missing-is-an-error*
276 ;;; new global variable which controls whether files (source
277 ;;; and binary) missing cause a continuable error or just a
279 ;;; 21-APR-91 mk Modified load-file-operation to allow compilation of source
280 ;;; files during load if the binary files are old or
281 ;;; non-existent. This adds a :compile-during-load keyword to
282 ;;; oos, and load-system. Global *compile-during-load* sets
283 ;;; the default (currently :query).
284 ;;; 21-APR-91 mk Modified find-system so that there is a preference for
285 ;;; loading system files from disk, even if the system is
286 ;;; already defined in the environment.
287 ;;; 25-APR-91 mk Removed load-time slot from component defstruct and added
288 ;;; function COMPONENT-LOAD-TIME to store the load times in a
289 ;;; hash table. This is safer than the old definition because
290 ;;; it doesn't wipe out load times every time the system is
292 ;;; 25-APR-91 mk Completely rewrote load-file-operation. Fixed some bugs
293 ;;; in :compile-during-load and in the behavior of defsystem
294 ;;; when multiple users are compiling and loading a system
295 ;;; instead of just a single user.
296 ;;; 16-MAY-91 mk Modified FIND-SYSTEM to do the right thing if the system
297 ;;; definition file cannot be found.
298 ;;; 16-MAY-91 mk Added globals *source-pathname-default* and
299 ;;; *binary-pathname-default* to contain default values for
300 ;;; :source-pathname and :binary-pathname. For example, set
301 ;;; *source-pathname-default* to "" to avoid having to type
302 ;;; :source-pathname "" all the time.
303 ;;; 27-MAY-91 mk Fixed bug in new-append-directories where directory
304 ;;; components of the form "foo4.0" would appear as "foo4",
305 ;;; since pathname-name truncates the type. Changed
306 ;;; pathname-name to file-namestring.
307 ;;; 3-JUN-91 gc Small bug in new-append-directories; replace (when
308 ;;; abs-name) with (when (not (null-string abs-name)))
309 ;;; 4-JUN-91 mk Additional small change to new-append-directories for
310 ;;; getting the device from the relative pname if the abs
311 ;;; pname is "". This is to fix a small behavior in CMU CL old
312 ;;; compiler. Also changed (when (not (null-string abs-name)))
313 ;;; to have an (and abs-name) in there.
314 ;;; 8-JAN-92 sb Added filename extension for defsystem under Lucid Common
316 ;;; 8-JAN-92 mk Changed the definition of prompt-string to work around an
317 ;;; AKCL bug. Essentially, AKCL doesn't default the colinc to
318 ;;; 1 if the colnum is provided, so we hard code it.
319 ;;; 8-JAN-92 rs (pathname-directory (pathname "")) returns '(:relative) in
320 ;;; Lucid, instead of NIL. Changed new-append-directories and
321 ;;; test-new-append-directories to reflect this.
322 ;;; 8-JAN-92 mk Fixed problem related to *load-source-if-no-binary*.
323 ;;; compile-and-load-source-if-no-binary wasn't checking for
324 ;;; the existence of the binary if this variable was true,
325 ;;; causing the file to not be compiled.
326 ;;; 8-JAN-92 mk Fixed problem with null-string being called on a pathname
327 ;;; by returning NIL if the argument isn't a string.
328 ;;; 3-NOV-93 mk In Allegro 4.2, pathname device is :unspecific by default.
329 ;;; 11-NOV-93 fdmm Fixed package definition lock problem when redefining
331 ;;; 11-NOV-93 fdmm Added machine and software types for SGI and IRIX. It is
332 ;;; important to distinguish the OS version and CPU type in
333 ;;; SGI+ACL, since ACL 4.1 on IRIX 4.x and ACL 4.2 on IRIX 5.x
334 ;;; have incompatible .fasl files.
335 ;;; 01-APR-94 fdmm Fixed warning problem when redefining REQUIRE on LispWorks.
336 ;;; 01-NOV-94 fdmm Replaced (software-type) call in ACL by code extracting
337 ;;; the interesting parts from (software-version) [deleted
338 ;;; machine name and id].
339 ;;; 03-NOV-94 fdmm Added a hook (*compile-file-function*), that is funcalled
340 ;;; by compile-file-operation, so as to support other languages
341 ;;; running on top of Common Lisp.
342 ;;; The default is to compile Common Lisp.
343 ;;; 03-NOV-94 fdmm Added SCHEME-COMPILE-FILE, so that defsystem can now
344 ;;; compile Pseudoscheme files.
345 ;;; 04-NOV-94 fdmm Added the exported generic function SET-LANGUAGE, to
346 ;;; have a clean, easy to extend interface for telling
347 ;;; defsystem which language to assume for compilation.
348 ;;; Currently supported arguments: :common-lisp, :scheme.
349 ;;; 11-NOV-94 kc Ported to Allegro CL for Windows 2.0 (ACLPC) and CLISP.
350 ;;; 18-NOV-94 fdmm Changed the entry *filename-extensions* for LispWorks
351 ;;; to support any platform.
352 ;;; Added entries for :mcl and :clisp too.
353 ;;; 16-DEC-94 fdmm Added and entry for CMU CL on SGI to *filename-extensions*.
354 ;;; 16-DEC-94 fdmm Added OS version identification for CMU CL on SGI.
355 ;;; 16-DEC-94 fdmm For CMU CL 17 : Bypassed make-pathnames call fix
356 ;;; in NEW-APPEND-DIRECTORIES.
357 ;;; 16-DEC-94 fdmm Added HOME-SUBDIRECTORY to fix CMU's ignorance about `~'
358 ;;; when specifying registries.
359 ;;; 16-DEC-94 fdmm For CMU CL 17 : Bypassed :device fix in make-pathnames call
360 ;;; in COMPONENT-FULL-PATHNAME. This fix was also reported
361 ;;; by kc on 12-NOV-94. CMU CL 17 now supports CLtL2 pathnames.
362 ;;; 16-DEC-94 fdmm Removed a quote before the call to read in the readmacro
363 ;;; #@. This fixes a really annoying misfeature (couldn't do
364 ;;; #@(concatenate 'string "foo/" "bar"), for example).
365 ;;; 03-JAN-95 fdmm Do not include :pcl in *features* if :clos is there.
366 ;;; 2-MAR-95 mk Modified fdmm's *central-registry* change to use
367 ;;; user-homedir-pathname and to be a bit more generic in the
369 ;;; 2-MAR-95 mk Modified fdmm's updates to *filename-extensions* to handle
370 ;;; any CMU CL binary extensions.
371 ;;; 2-MAR-95 mk Make kc's port to ACLPC a little more generic.
372 ;;; 2-MAR-95 mk djc reported a bug, in which GET-SYSTEM was not returning
373 ;;; a system despite the system's just having been loaded.
374 ;;; The system name specified in the :depends-on was a
375 ;;; lowercase string. I am assuming that the system name
376 ;;; in the defsystem form was a symbol (I haven't verified
377 ;;; that this was the case with djc, but it is the only
378 ;;; reasonable conclusion). So, CANONICALIZE-SYSTEM-NAME
379 ;;; was storing the system in the hash table as an
380 ;;; uppercase string, but attempting to retrieve it as a
381 ;;; lowercase string. This behavior actually isn't a bug,
382 ;;; but a user error. It was intended as a feature to
383 ;;; allow users to use strings for system names when
384 ;;; they wanted to distinguish between two different systems
385 ;;; named "foo.system" and "Foo.system". However, this
386 ;;; user error indicates that this was a bad design decision.
387 ;;; Accordingly, CANONICALIZE-SYSTEM-NAME now uppercases
388 ;;; even strings for retrieving systems, and the comparison
389 ;;; in *modules* is now case-insensitive. The result of
390 ;;; this change is if the user cannot have distinct
391 ;;; systems in "Foo.system" and "foo.system" named "Foo" and
392 ;;; "foo", because they will clobber each other. There is
393 ;;; still case-sensitivity on the filenames (i.e., if the
394 ;;; system file is named "Foo.system" and you use "foo" in
395 ;;; the :depends-on, it won't find it). We didn't take the
396 ;;; further step of requiring system filenames to be lowercase
397 ;;; because we actually find this kind of case-sensitivity
398 ;;; to be useful, when maintaining two different versions
399 ;;; of the same system.
400 ;;; 7-MAR-95 mk Added simplistic handling of logical pathnames. Also
401 ;;; modified new-append-directories so that it'll try to
402 ;;; split up pathname directories that are strings into a
403 ;;; list of the directory components. Such directories aren't
404 ;;; ANSI CL, but some non-conforming implementations do it.
405 ;;; 7-MAR-95 mk Added :proclamations to defsystem form, which can be used
406 ;;; to set the compiler optimization level before compilation.
408 ;;; :proclamations '(optimize (safety 3) (speed 3) (space 0))
409 ;;; 7-MAR-95 mk Defsystem now tells the user when it reloads the system
411 ;;; 7-MAR-95 mk Fixed problem pointed out by yc. If
412 ;;; *source-pathname-default* is "" and there is no explicit
413 ;;; :source-pathname specified for a file, the file could
414 ;;; wind up with an empty file name. In other words, this
415 ;;; global default shouldn't apply to :file components. Added
416 ;;; explicit test for null strings, and when present replaced
417 ;;; them with NIL (for binary as well as source, and also for
418 ;;; :private-file components).
419 ;;; 7-MAR-95 tar Fixed defsystem to work on TI Explorers (TI CL).
420 ;;; 7-MAR-95 jk Added machine-type-translation for Decstation 5000/200
421 ;;; under Allegro 3.1
422 ;;; 7-MAR-95 as Fixed bug in AKCL-1-615 in which defsystem added a
423 ;;; subdirectory "RELATIVE" to all filenames.
424 ;;; 7-MAR-95 mk Added new test to test-new-append-directories to catch the
425 ;;; error fixed by as. Essentially, this error occurs when the
426 ;;; absolute-pathname has no directory (i.e., it has a single
427 ;;; pathname component as in "foo" and not "foo/bar"). If
428 ;;; RELATIVE ever shows up in the Result, we now know to
429 ;;; add an extra conditionalization to prevent abs-keyword
430 ;;; from being set to :relative.
431 ;;; 7-MAR-95 ss Miscellaneous fixes for MCL 2.0 final.
432 ;;; *compile-file-verbose* not in MCL, *version variables
433 ;;; need to occur before AFS-SOURCE-DIRECTORY definition,
434 ;;; and certain code needed to be in the CCL: package.
435 ;;; 8-MAR-95 mk Y-OR-N-P-WAIT uses a busy-waiting. On Lisp systems where
436 ;;; the time functions cons, such as CMU CL, this can cause a
437 ;;; lot of ugly garbage collection messages. Modified the
438 ;;; waiting to include calls to SLEEP, which should reduce
439 ;;; some of the consing.
440 ;;; 8-MAR-95 mk Replaced fdmm's SET-LANGUAGE enhancement with a more
441 ;;; general extension, along the lines suggested by akd.
442 ;;; Defsystem now allows components to specify a :language
443 ;;; slot, such as :language :lisp, :language :scheme. This
444 ;;; slot is inherited (with the default being :lisp), and is
445 ;;; used to obtain compilation and loading functions for
446 ;;; components, as well as source and binary extensions. The
447 ;;; compilation and loading functions can be overridden by
448 ;;; specifying a :compiler or :loader in the system
449 ;;; definition. Also added :documentation slot to the system
451 ;;; Where this comes in real handy is if one has a
452 ;;; compiler-compiler implemented in Lisp, and wants the
453 ;;; system to use the compiler-compiler to create a parser
454 ;;; from a grammar and then compile parser. To do this one
455 ;;; would create a module with components that looked
456 ;;; something like this:
457 ;;; ((:module cc :components ("compiler-compiler"))
458 ;;; (:module gr :compiler 'cc :loader #'ignore
459 ;;; :source-extension "gra"
460 ;;; :binary-extension "lisp"
462 ;;; :components ("sample-grammar"))
463 ;;; (:module parser :depends-on (gr)
464 ;;; :components ("sample-grammar")))
465 ;;; Defsystem would then compile and load the compiler, use
466 ;;; it (the function cc) to compile the grammar into a parser,
467 ;;; and then compile the parser. The only tricky part is
468 ;;; cc is defined by the system, and one can't include #'cc
469 ;;; in the system definition. However, one could include
470 ;;; a call to mk:define-language in the compiler-compiler file,
471 ;;; and define :cc as a language. This is the prefered method.
472 ;;; 8-MAR-95 mk New definition of topological-sort suggested by rs2. This
473 ;;; version avoids the call to SORT, but in practice isn't
474 ;;; much faster. However, it avoids the need to maintain a
475 ;;; TIME slot in the topsort-node structure.
476 ;;; 8-MAR-95 mk rs2 also pointed out that the calls to MAKE-PATHNAME and
477 ;;; NAMESTRING in COMPONENT-FULL-PATHNAME are a major reason
478 ;;; why defsystem is slow. Accordingly, I've changed
479 ;;; COMPONENT-FULL-PATHNAME to include a call to NAMESTRING
480 ;;; (and removed all other calls to NAMESTRING), and also made
481 ;;; a few changes to minimize the number of calls to
482 ;;; COMPONENT-FULL-PATHNAME, such as memoizing it. See To Do
483 ;;; below for other related comments.
484 ;;; 8-MAR-95 mk Added special hack requested by Steve Strassman, which
485 ;;; allows one to specify absolute pathnames in the shorthand
486 ;;; for a list of components, and have defsystem recognize
487 ;;; which are absolute and which are relative.
488 ;;; I actually think this would be a good idea, but I haven't
489 ;;; tested it, so it is disabled by default. Search for
490 ;;; *enable-straz-absolute-string-hack* to enable it.
491 ;;; 8-MAR-95 kt Fixed problem with EXPORT in AKCL 1.603, in which it wasn't
492 ;;; properly exporting the value of the global export
494 ;;; 8-MAR-95 mk Added UNMUNGE-LUCID to fix nasty problem with COMPILE-FILE
495 ;;; in Lucid. Lucid apparently tries to merge the :output-file
496 ;;; with the source file when the :output-file is a relative
497 ;;; pathname. Wierd, and definitely non-standard.
498 ;;; 9-MAR-95 mk Changed ALLEGRO-MAKE-SYSTEM-FASL to also include the files
499 ;;; in any systems the system depends on, as per a
501 ;;; 9-MAR-95 mk Some version of CMU CL couldn't hack a call to
502 ;;; MAKE-PATHNAME with :host NIL. I'm not sure which version
503 ;;; it is, but the current version doesn't have this problem.
504 ;;; If given :host nil, it defaults the host to
505 ;;; COMMON-LISP::*UNIX-HOST*. So I haven't "fixed" this
507 ;;; 9-MAR-95 mk Integrated top-level commands for Allegro designed by bha
508 ;;; into the code, with slight modifications.
509 ;;; 9-MAR-95 mk Instead of having COMPUTE-SYSTEM-PATH check the current
510 ;;; directory in a hard-coded fashion, include the current
511 ;;; directory in the *central-registry*, as suggested by
513 ;;; 9-MAR-95 bha Support for Logical Pathnames in Allegro.
514 ;;; 9-MAR-95 mk Added modified version of bha's DEFSYSPATH idea.
515 ;;; 13-MAR-95 mk Added a macro for the simple serial case, where a system
516 ;;; (or module) is simple a list of files, each of which
517 ;;; depends on the previous one. If the value of :components
518 ;;; is a list beginning with :serial, it expands each
519 ;;; component and makes it depend on the previous component.
520 ;;; For example, (:serial "foo" "bar" "baz") would create a
521 ;;; set of components where "baz" depended on "bar" and "bar"
523 ;;; 13-MAR-95 mk *** Now version 3.0. This version is a interim bug-fix and
524 ;;; update, since I do not have the time right now to complete
525 ;;; the complete overhaul and redesign.
526 ;;; Major changes in 3.0 include CMU CL 17, CLISP, ACLPC, TI,
527 ;;; LispWorks and ACL(SGI) support, bug fixes for ACL 4.1/4.2.
528 ;;; 14-MAR-95 fdmm Finally added the bit of code to discriminate cleanly
529 ;;; among different lisps without relying on (software-version)
531 ;;; You can now customize COMPILER-TYPE-TRANSLATION so that
532 ;;; AFS-BINARY-DIRECTORY can return a different value for
533 ;;; different lisps on the same platform.
534 ;;; If you use only one compiler, do not care about supporting
535 ;;; code for multiple versions of it, and want less verbose
536 ;;; directory names, just set *MULTIPLE-LISP-SUPPORT* to nil.
537 ;;; 17-MAR-95 lmh Added EVAL-WHEN for one of the MAKE-PACKAGE calls.
538 ;;; CMU CL's RUN-PROGRAM is in the extensions package.
539 ;;; ABSOLUTE-FILE-NAMESTRING-P was missing :test keyword
540 ;;; Rearranged conditionalization in DIRECTORY-TO-LIST to
541 ;;; suppress compiler warnings in CMU CL.
542 ;;; 17-MAR-95 mk Added conditionalizations to avoid certain CMU CL compiler
543 ;;; warnings reported by lmh.
544 ;;; 19990610 ma Added shadowing of 'HARDCOPY-SYSTEM' for LW Personal Ed.
546 ;;; 19991211 ma NEW VERSION 4.0 started.
547 ;;; 19991211 ma Merged in changes requested by T. Russ of
548 ;;; ISI. Please refer to the special "ISI" comments to
549 ;;; understand these changes
550 ;;; 20000228 ma The symbols FIND-SYSTEM, LOAD-SYSTEM, DEFSYSTEM,
551 ;;; COMPILE-SYSTEM and HARDCOPY-SYSTEM are no longer
552 ;;; imported in the COMMON-LISP-USER package.
553 ;;; Cfr. the definitions of *EXPORTS* and
554 ;;; *SPECIAL-EXPORTS*.
555 ;;; 2000-07-21 rlt Add COMPILER-OPTIONS to defstruct to allow user to
556 ;;; specify special compiler options for a particular
558 ;;; 2002-01-08 kmr Changed allegro symbols to lowercase to support
559 ;;; case-sensitive images
561 ;;;---------------------------------------------------------------------------
564 ;;; 19991211 Marco Antoniotti
565 ;;; These comments come from the "ISI Branch". I believe I did
566 ;;; include the :load-always extension correctly. The other commets
567 ;;; seem superseded by other changes made to the system in the
568 ;;; following years. Some others are now useless with newer systems
569 ;;; (e.g. filename truncation for new Windows based CL
570 ;;; implementations.)
572 ;;; 1-OCT-92 tar Fixed problem with TI Lisp machines and append-directory.
573 ;;; 1-OCT-92 tar Made major modifications to compile-file-operation and
574 ;;; load-file-operation to reduce the number of probe-file
575 ;;; and write-date inquiries. This makes the system run much
576 ;;; faster through slow network connections.
577 ;;; 13-OCT-92 tar Added :load-always slot to components. If this slot is
578 ;;; specified as non-NIL, always loads the component.
579 ;;; This does not trigger dependent compilation.
580 ;;; (This can be useful when macro definitions needed
581 ;;; during compilation are changed by later files. In
582 ;;; this case, not reloading up-to-date files can
583 ;;; cause different results.)
584 ;;; 28-OCT-93 tar Allegro 4.2 causes an error on (pathname-device nil)
585 ;;; 14-SEP-94 tar Disable importing of symbols into (CL-)USER package
586 ;;; to minimize conflicts with other defsystem utilities.
587 ;;; 10-NOV-94 tar Added filename truncation code to support Franz Allegro
588 ;;; PC with it's 8 character filename limitation.
589 ;;; 15-MAY-98 tar Changed host attribute for pathnames to support LispWorks
590 ;;; (Windows) pathnames which reference other Drives. Also
591 ;;; updated file name convention.
592 ;;; 9-NOV-98 tar Updated new-append-directories for Lucid 5.0
596 ;;; ********************************
597 ;;; Ports **************************
598 ;;; ********************************
600 ;;; DEFSYSTEM has been tested (successfully) in the following lisps:
601 ;;; CMU Common Lisp (M2.9 15-Aug-90, Compiler M1.8 15-Aug-90)
602 ;;; CMU Common Lisp (14-Dec-90 beta, Python Compiler 0.0 PMAX/Mach)
603 ;;; CMU Common Lisp 17f (Python 1.0)
604 ;;; Franz Allegro Common Lisp 3.1.12 (ExCL 3/30/90)
605 ;;; Franz Allegro Common Lisp 4.0/4.1/4.2
606 ;;; Franz Allegro Common Lisp for Windows (2.0)
607 ;;; Lucid Common Lisp (Version 2.1 6-DEC-87)
608 ;;; Lucid Common Lisp (3.0 [SPARC,SUN3])
609 ;;; Lucid Common Lisp (4.0 [SPARC,SUN3])
610 ;;; VAXLisp (v2.2) [VAX/VMS]
612 ;;; Harlequin LispWorks
613 ;;; CLISP (CLISP3 [SPARC])
614 ;;; Symbolics XL12000 (Genera 8.3)
615 ;;; Scieneer Common Lisp (SCL) 1.1
616 ;;; Macintosh Common Lisp
619 ;;; DEFSYSTEM needs to be tested in the following lisps:
621 ;;; Symbolics Common Lisp (8.0)
622 ;;; KCL (June 3, 1987 or later)
623 ;;; AKCL (1.86, June 30, 1987 or later)
624 ;;; TI (Release 4.1 or later)
625 ;;; Ibuki Common Lisp (01/01, October 15, 1987)
626 ;;; Golden Common Lisp (3.1 IBM-PC)
627 ;;; HP Common Lisp (same as Lucid?)
628 ;;; Procyon Common Lisp
630 ;;; ********************************
631 ;;; To Do **************************
632 ;;; ********************************
634 ;;; COMPONENT-FULL-PATHNAME is a major source of slowness in the system
635 ;;; because of all the calls to the expensive operations MAKE-PATHNAME
636 ;;; and NAMESTRING. To improve performance, DEFSYSTEM should be reworked
637 ;;; to avoid any need to call MAKE-PATHNAME and NAMESTRING, as the logical
638 ;;; pathnames package does. Unfortunately, I don't have the time to do this
639 ;;; right now. Instead, I installed a temporary improvement by memoizing
640 ;;; COMPONENT-FULL-PATHNAME to cache previous calls to the function on
641 ;;; a component by component and type by type basis. The cache is
642 ;;; cleared before each call to OOS, in case filename extensions change.
643 ;;; But DEFSYSTEM should really be reworked to avoid this problem and
644 ;;; ensure greater portability and to also handle logical pathnames.
646 ;;; Also, PROBE-FILE and FILE-WRITE-DATE are other sources of slowness.
647 ;;; Perhaps by also memoizing FILE-WRITE-DATE and reimplementing PROBE-FILE
648 ;;; in terms of FILE-WRITE-DATE, can achieve a further speed-up. This was
649 ;;; suggested by Steven Feist (feist@ils.nwu.edu).
651 ;;; True CLtL2 logical pathnames support -- can't do it, because CLtL2
652 ;;; doesn't have all the necessary primitives, and even in Allegro CL 4.2
653 ;;; (namestring #l"foo:bar;baz.lisp")
654 ;;; does not work properly.
656 ;;; Create separate stand-alone documentation for defsystem, and also
659 ;;; Change SYSTEM to be a class instead of a struct, and make it a little
660 ;;; more generic, so that it permits alternate system definitions.
661 ;;; Replace OPERATE-ON-SYSTEM with MAP-SYSTEM (args: function, system-name,
664 ;;; Add a patch directory mechanism. Perhaps have several directories
665 ;;; with code in them, and the first one with the specified file wins?
666 ;;; LOAD-PATCHES function.
668 ;;; Need way to load old binaries even if source is newer.
670 ;;; Allow defpackage forms/package definitions in the defsystem? If
671 ;;; a package not defined, look for and load a file named package.pkg?
673 ;;; need to port for GNU CL (ala kcl)?
675 ;;; Someone asked whether one can have :file components at top-level. I believe
676 ;;; this is the case, but should double-check that it is possible (and if
677 ;;; not, make it so).
679 ;;; A common error/misconception seems to involve assuming that :system
680 ;;; components should include the name of the system file, and that
681 ;;; defsystem will automatically load the file containing the system
682 ;;; definition and propagate operations to it. Perhaps this would be a
683 ;;; nice feature to add.
685 ;;; If a module is :load-only t, then it should not execute its :finally-do
686 ;;; and :initially-do clauses during compilation operations, unless the
687 ;;; module's files happen to be loaded during the operation.
689 ;;; System Class. Customizable delimiters.
691 ;;; Load a system (while not loading anything already loaded)
692 ;;; and inform the user of out of date fasls with the choice
693 ;;; to load the old fasl or recompile and then load the new
696 ;;; modify compile-file-operation to handle a query keyword....
698 ;;; Perhaps systems should keep around the file-write-date of the system
699 ;;; definition file, to prevent excessive reloading of the system definition?
701 ;;; load-file-operation needs to be completely reworked to simplify the
702 ;;; logic of when files get loaded or not.
704 ;;; Need to revamp output: Nesting and indenting verbose output doesn't
705 ;;; seem cool, especially when output overflows the 80-column margins.
707 ;;; Document various ways of writing a system. simple (short) form
708 ;;; (where :components is just a list of filenames) in addition to verbose.
709 ;;; Put documentation strings in code.
711 ;;; :load-time for modules and systems -- maybe record the time the system
712 ;;; was loaded/compiled here and print it in describe-system?
714 ;;; Make it easy to define new functions that operate on a system. For
715 ;;; example, a function that prints out a list of files that have changed,
716 ;;; hardcopy-system, edit-system, etc.
718 ;;; If a user wants to have identical systems for different lisps, do we
719 ;;; force the user to use logical pathnames? Or maybe we should write a
720 ;;; generic-pathnames package that parses any pathname format into a
721 ;;; uniform underlying format (i.e., pull the relevant code out of
722 ;;; logical-pathnames.lisp and clean it up a bit).
724 ;;; Verify that Mac pathnames now work with append-directories.
726 ;;; A common human error is to violate the modularization by making a file
727 ;;; in one module depend on a file in another module, instead of making
728 ;;; one module depend on the other. This is caught because the dependency
729 ;;; isn't found. However, is there any way to provide a more informative
730 ;;; error message? Probably not, especially if the system has multiple
731 ;;; files of the same name.
733 ;;; For a module none of whose files needed to be compiled, have it print out
734 ;;; "no files need recompilation".
736 ;;; Write a system date/time to a file? (version information) I.e., if the
737 ;;; filesystem supports file version numbers, write an auxiliary file to
738 ;;; the system definition file that specifies versions of the system and
739 ;;; the version numbers of the associated files.
741 ;;; Add idea of a patch directory.
743 ;;; In verbose printout, have it log a date/time at start and end of
745 ;;; Compiling system "test" on 31-Jan-91 21:46:47
746 ;;; by Defsystem version v2.0 01-FEB-91.
748 ;;; Define other :force options:
749 ;;; :query allows user to specify that a file not normally compiled
751 ;;; :confirm allows user to specify that a file normally compiled
752 ;;; shouldn't be. AND
754 ;;; We currently assume that compilation-load dependencies and if-changed
755 ;;; dependencies are identical. However, in some cases this might not be
756 ;;; true. For example, if we change a macro we have to recompile functions
757 ;;; that depend on it (except in lisps that automatically do this, such
758 ;;; as the new CMU Common Lisp), but not if we change a function. Splitting
759 ;;; these apart (with appropriate defaulting) would be nice, but not worth
760 ;;; doing immediately since it may save only a couple of file recompilations,
761 ;;; while making defsystem much more complex than it already is.
763 ;;; Current dependencies are limited to siblings. Maybe we should allow
764 ;;; nephews and uncles? So long as it is still a DAG, we can sort it.
765 ;;; Answer: No. The current setup enforces a structure on the modularity.
766 ;;; Otherwise, why should we have modules if we're going to ignore it?
768 ;;; Currently a file is recompiled more or less if the source is newer
769 ;;; than the binary or if the file depends on a file that has changed
770 ;;; (i.e., was recompiled in this session of a system operation).
771 ;;; Neil Goldman <goldman@isi.edu> has pointed out that whether a file
772 ;;; needs recompilation is really independent of the current session of
773 ;;; a system operation, and depends only on the file-write-dates of the
774 ;;; source and binary files for a system. Thus a file should require
775 ;;; recompilation in the following circumstances:
776 ;;; 1. If a file's source is newer than its binary, or
777 ;;; 2. If a file's source is not newer than its binary, but the file
778 ;;; depends directly or indirectly on a module (or file) that is newer.
779 ;;; For a regular file use the file-write-date (FWD) of the source or
780 ;;; binary, whichever is more recent. For a load-only file, use the only
781 ;;; available FWD. For a module, use the most recent (max) FWD of any of
783 ;;; The impact of this is that instead of using a boolean CHANGED variable
784 ;;; throughout the code, we need to allow CHANGED to be NIL/T/<FWD> or
785 ;;; maybe just the FWD timestamp, and to use the value of CHANGED in
786 ;;; needs-compilation decisions. (Use of NIL/T as values is an optimization.
787 ;;; The FWD timestamp which indicates the most recent time of any changes
788 ;;; should be sufficient.) This will affect not just the
789 ;;; compile-file-operation, but also the load-file-operation because of
790 ;;; compilation during load. Also, since FWDs will be used more prevalently,
791 ;;; we probably should couple this change with the inclusion of load-times
792 ;;; in the component defstruct. This is a tricky and involved change, and
793 ;;; requires more thought, since there are subtle cases where it might not
794 ;;; be correct. For now, the change will have to wait until the DEFSYSTEM
797 ;;; ********************************************************************
798 ;;; How to Use this System *********************************************
799 ;;; ********************************************************************
801 ;;; To use this system,
802 ;;; 1. If you want to have a central registry of system definitions,
803 ;;; modify the value of the variable *central-registry* below.
804 ;;; 2. Load this file (defsystem.lisp) in either source or compiled form,
805 ;;; 3. Load the file containing the "defsystem" definition of your system,
806 ;;; 4. Use the function "operate-on-system" to do things to your system.
808 ;;; For more information, see the documentation and examples in
809 ;;; lisp-utilities.ps.
811 ;;; ********************************
812 ;;; Usage Comments *****************
813 ;;; ********************************
815 ;;; If you use symbols in the system definition file, they get interned in
816 ;;; the COMMON-LISP-USER package, which can lead to name conflicts when
817 ;;; the system itself seeks to export the same symbol to the COMMON-LISP-USER
818 ;;; package. The workaround is to use strings instead of symbols for the
819 ;;; names of components in the system definition file. In the major overhaul,
820 ;;; perhaps the user should be precluded from using symbols for such
823 ;;; If you include a tilde in the :source-pathname in Allegro, as in "~/lisp",
824 ;;; file name expansion is much slower than if you use the full pathname,
825 ;;; as in "/user/USERID/lisp".
829 ;;; ****************************************************************
830 ;;; Lisp Code ******************************************************
831 ;;; ****************************************************************
833 ;;; ********************************
834 ;;; Massage CLtL2 onto *features* **
835 ;;; ********************************
836 ;;; Let's be smart about CLtL2 compatible Lisps:
837 (eval-when (compile load eval
)
838 #+(or (and allegro-version
>= (version>= 4 0)) :mcl
:sbcl
)
839 (pushnew :cltl2
*features
*))
841 ;;; ********************************
842 ;;; Provide/Require/*modules* ******
843 ;;; ********************************
845 ;;; Since CLtL2 has dropped require and provide from the language, some
846 ;;; lisps may not have the functions PROVIDE and REQUIRE and the
847 ;;; global *MODULES*. So if lisp::provide and user::provide are not
848 ;;; defined, we define our own.
850 ;;; Hmmm. CMU CL old compiler gives bogus warnings here about functions
851 ;;; and variables not being declared or bound, apparently because it
852 ;;; sees that (or (fboundp 'lisp::require) (fboundp 'user::require)) returns
853 ;;; T, so it doesn't really bother when compiling the body of the unless.
854 ;;; The new compiler does this properly, so I'm not going to bother
855 ;;; working around this.
857 ;;; Some Lisp implementations return bogus warnings about assuming
858 ;;; *MODULE-FILES* and *LIBRARY* to be special, and CANONICALIZE-MODULE-NAME
859 ;;; and MODULE-FILES being undefined. Don't worry about them.
861 ;;; Now that ANSI CL includes PROVIDE and REQUIRE again, is this code
876 (and allegro-version
>= (version>= 4 1)))
877 (eval-when #-
(or :lucid
)
878 (:compile-toplevel
:load-toplevel
:execute
)
882 (unless (or (fboundp 'lisp
::require
)
883 (fboundp 'user
::require
)
885 #+(and :excl
(and allegro-version
>= (version>= 4 0)))
886 (fboundp 'cltl1
::require
)
889 (fboundp 'system
::require
))
896 (export '(*modules
* provide require
))
898 ;; Documentation strings taken almost literally from CLtL1.
901 "List of names of the modules that have been loaded into Lisp so far.
902 It is used by PROVIDE and REQUIRE.")
904 ;; We provide two different ways to define modules. The default way
905 ;; is to put either a source or binary file with the same name
906 ;; as the module in the library directory. The other way is to define
907 ;; the list of files in the module with defmodule.
909 ;; The directory listed in *library* is implementation dependent,
910 ;; and is intended to be used by Lisp manufacturers as a place to
911 ;; store their implementation dependent packages.
912 ;; Lisp users should use systems and *central-registry* to store
913 ;; their packages -- it is intended that *central-registry* is
914 ;; set by the user, while *library* is set by the lisp.
916 (defvar *library
* nil
; "/usr/local/lisp/Modules/"
917 "Directory within the file system containing files, where the name
918 of a file is the same as the name of the module it contains.")
920 (defvar *module-files
* (make-hash-table :test
#'equal
)
921 "Hash table mapping from module names to list of files for the
922 module. REQUIRE loads these files in order.")
924 (defun canonicalize-module-name (name)
925 ;; if symbol, string-downcase the printrep to make nicer filenames.
926 (if (stringp name
) name
(string-downcase (string name
))))
928 (defmacro defmodule
(name &rest files
)
929 "Defines a module NAME to load the specified FILES in order."
930 `(setf (gethash (canonicalize-module-name ,name
) *module-files
*)
932 (defun module-files (name)
933 (gethash name
*module-files
*))
935 (defun provide (name)
936 "Adds a new module name to the list of modules maintained in the
937 variable *modules*, thereby indicating that the module has been
938 loaded. Name may be a string or symbol -- strings are case-senstive,
939 while symbols are treated like lowercase strings. Returns T if
940 NAME was not already present, NIL otherwise."
941 (let ((module (canonicalize-module-name name
)))
942 (unless (find module
*modules
* :test
#'string
=)
943 ;; Module not present. Add it and return T to signify that it
945 (push module
*modules
*)
948 (defun require (name &optional pathname
)
949 "Tests whether a module is already present. If the module is not
950 present, loads the appropriate file or set of files. The pathname
951 argument, if present, is a single pathname or list of pathnames
952 whose files are to be loaded in order, left to right. If the
953 pathname is nil, the system first checks if a module was defined
954 using defmodule and uses the pathnames so defined. If that fails,
955 it looks in the library directory for a file with name the same
956 as that of the module. Returns T if it loads the module."
957 (let ((module (canonicalize-module-name name
)))
958 (unless (find module
*modules
* :test
#'string
=)
959 ;; Module is not already present.
960 (when (and pathname
(not (listp pathname
)))
961 ;; If there's a pathname or pathnames, ensure that it's a list.
962 (setf pathname
(list pathname
)))
964 ;; If there's no pathname, try for a defmodule definition.
965 (setf pathname
(module-files module
)))
967 ;; If there's still no pathname, try the library directory.
969 (setf pathname
(concatenate 'string
*library
* module
))
970 ;; Test if the file exists.
971 ;; We assume that the lisp will default the file type
972 ;; appropriately. If it doesn't, use #+".fasl" or some
973 ;; such in the concatenate form above.
974 (if (probe-file pathname
)
975 ;; If it exists, ensure we've got a list
976 (setf pathname
(list pathname
))
977 ;; If the library file doesn't exist, we don't want
979 (setf pathname nil
))))
980 ;; Now that we've got the list of pathnames, let's load them.
981 (dolist (pname pathname t
)
982 (load pname
:verbose nil
))))))
985 ;;; ********************************
986 ;;; Set up Package *****************
987 ;;; ********************************
990 ;;; Unfortunately, lots of lisps have their own defsystems, some more
991 ;;; primitive than others, all uncompatible, and all in the DEFSYSTEM
992 ;;; package. To avoid name conflicts, we've decided to name this the
993 ;;; MAKE package. A nice side-effect is that the short nickname
994 ;;; MK is my initials.
996 #+abcl
(defpackage make
(:use
"COMMON-LISP") (:nicknames
"MK"))
998 #+(or clisp cormanlisp ecl
(and gcl defpackage
) sbcl ccl
)
999 (defpackage "MAKE" (:use
"COMMON-LISP") (:nicknames
"MK"))
1001 #-
(or :sbcl
:cltl2
:lispworks
:ecl
:scl
:abcl
:ccl
)
1002 (in-package :make
:nicknames
'("MK"))
1004 ;;; For CLtL2 compatible lisps...
1005 #+(and :excl
:allegro-v4.0
:cltl2
)
1006 (defpackage "MAKE" (:nicknames
"MK" "make" "mk") (:use
:common-lisp
)
1007 (:import-from cltl1
*modules
* provide require
))
1009 ;;; *** Marco Antoniotti <marcoxa@icsi.berkeley.edu> 19970105
1010 ;;; In Allegro 4.1, 'provide' and 'require' are not external in
1011 ;;; 'CLTL1'. However they are in 'COMMON-LISP'. Hence the change.
1012 #+(and :excl
:allegro-v4.1
:cltl2
)
1013 (defpackage "MAKE" (:nicknames
"MK" "make" "mk") (:use
:common-lisp
) )
1015 #+(and :excl
:allegro-version
>= (version>= 4 2))
1016 (defpackage "MAKE" (:nicknames
"MK" "make" "mk") (:use
:common-lisp
))
1019 (defpackage "MAKE" (:nicknames
"MK") (:use
"COMMON-LISP")
1020 (:import-from system
*modules
* provide require
)
1021 (:export
"DEFSYSTEM" "COMPILE-SYSTEM" "LOAD-SYSTEM"
1022 "DEFINE-LANGUAGE" "*MULTIPLE-LISP-SUPPORT*"))
1025 (defpackage "MAKE" (:nicknames
"MK") (:use
"COMMON-LISP")
1026 (:import-from ccl
*modules
* provide require
))
1028 ;;; *** Marco Antoniotti <marcoxa@icsi.berkeley.edu> 19951012
1029 ;;; The code below, is originally executed also for CMUCL. However I
1030 ;;; believe this is wrong, since CMUCL comes with its own defpackage.
1031 ;;; I added the extra :CMU in the 'or'.
1032 #+(and :cltl2
(not (or :cmu
:scl
:clisp
:sbcl
:abcl
1033 (and :excl
(or :allegro-v4.0
:allegro-v4.1
))
1035 (eval-when (compile load eval
)
1036 (unless (find-package "MAKE")
1037 (make-package "MAKE" :nicknames
'("MK") :use
'("COMMON-LISP"))))
1039 ;;; *** Marco Antoniotti <marcoxa@icsi.berkeley.edu> 19951012
1040 ;;; Here I add the proper defpackage for CMU
1042 (defpackage "MAKE" (:use
"COMMON-LISP" "CONDITIONS")
1046 (defpackage "MAKE" (:use
"COMMON-LISP")
1050 (defpackage :make
(:use
:common-lisp
)
1053 #+(or :cltl2
:lispworks
:scl
)
1054 (eval-when (compile load eval
)
1060 ;;; *** Marco Antoniotti <marcoxa@icsi.berkeley.edu> 19970105
1061 ;;; 'provide' is not esternal in 'CLTL1' in Allegro v 4.1
1062 #+(and :excl
:allegro-v4.0
:cltl2
)
1063 (cltl1:provide
'make
)
1064 #+(and :excl
:allegro-v4.0
:cltl2
)
1070 #+(and :mcl
(not :openmcl
))
1073 #+(and :cltl2
(not (or (and :excl
(or :allegro-v4.0
:allegro-v4.1
)) :mcl
)))
1079 #-
(or :cltl2
:lispworks
)
1082 (pushnew :mk-defsystem
*features
*)
1084 ;;; Some compatibility issues. Mostly for CormanLisp.
1085 ;;; 2002-02-20 Marco Antoniotti
1088 (defun compile-file-pathname (pathname-designator)
1089 (merge-pathnames (make-pathname :type
"fasl")
1090 (etypecase pathname-designator
1091 (pathname pathname-designator
)
1092 (string (parse-namestring pathname-designator
))
1093 ;; We need FILE-STREAM here as well.
1097 (defun file-namestring (pathname-designator)
1098 (let ((p (etypecase pathname-designator
1099 (pathname pathname-designator
)
1100 (string (parse-namestring pathname-designator
))
1101 ;; We need FILE-STREAM here as well.
1103 (namestring (make-pathname :directory
()
1104 :name
(pathname-name p
)
1105 :type
(pathname-type p
)
1106 :version
(pathname-version p
)))))
1108 ;;; The external interface consists of *exports* and *other-exports*.
1110 ;;; AKCL (at least 1.603) grabs all the (export) forms and puts them up top in
1111 ;;; the compile form, so that you can't use a defvar with a default value and
1112 ;;; then a succeeding export as well.
1114 (eval-when (compile load eval
)
1115 (defvar *special-exports
* nil
)
1116 (defvar *exports
* nil
)
1117 (defvar *other-exports
* nil
)
1119 (export (setq *exports
*
1122 afs-binary-directory afs-source-directory
1124 (export (setq *special-exports
*
1126 (export (setq *other-exports
*
1127 '(*central-registry
*
1130 add-registry-location
1132 defsystem compile-system load-system hardcopy-system
1134 system-definition-pathname
1137 missing-component-name
1138 missing-component-component
1142 register-foreign-system
1144 machine-type-translation
1145 software-type-translation
1146 compiler-type-translation
1149 allegro-make-system-fasl
1150 files-which-need-compilation
1153 describe-system clean-system edit-system
;hardcopy-system
1154 system-source-size make-system-tag-table
1156 *compile-during-load
*
1158 *dont-redefine-require
*
1159 *files-missing-is-an-error
*
1160 *reload-systems-from-disk
*
1161 *source-pathname-default
*
1162 *binary-pathname-default
*
1163 *multiple-lisp-support
*
1167 ;;; We import these symbols into the USER package to make them
1168 ;;; easier to use. Since some lisps have already defined defsystem
1169 ;;; in the user package, we may have to shadowing-import it.
1171 #-
(or :sbcl
:cmu
:ccl
:allegro
:excl
:lispworks
:symbolics
)
1172 (eval-when (compile load eval
)
1173 (import *exports
* #-
(or :cltl2
:lispworks
) :user
1174 #+(or :cltl2
:lispworks
) :common-lisp-user
)
1175 (import *special-exports
* #-
(or :cltl2
:lispworks
) :user
1176 #+(or :cltl2
:lispworks
) :common-lisp-user
))
1177 #+(or :sbcl
:cmu
:ccl
:allegro
:excl
:lispworks
:symbolics
)
1178 (eval-when (compile load eval
)
1179 (import *exports
* #-
(or :cltl2
:lispworks
) :user
1180 #+(or :cltl2
:lispworks
) :common-lisp-user
)
1181 (shadowing-import *special-exports
*
1182 #-
(or :cltl2
:lispworks
) :user
1183 #+(or :cltl2
:lispworks
) :common-lisp-user
))
1186 #-
(or :pcl
:clos
:scl
)
1187 (when (find-package :pcl
)
1188 (pushnew :pcl
*modules
*)
1189 (pushnew :pcl
*features
*))
1191 ;;; ********************************
1192 ;;; Defsystem Version **************
1193 ;;; ********************************
1194 (defparameter *defsystem-version
* "3.4 Interim 3, 2004-06-10"
1195 "Current version number/date for MK:DEFSYSTEM.")
1197 ;;; ********************************
1198 ;;; Customizable System Parameters *
1199 ;;; ********************************
1201 (defvar *dont-redefine-require
*
1202 #+cmu
(if (find-symbol "*MODULE-PROVIDER-FUNCTIONS*" :ext
) t nil
)
1203 #+(or allegro ccl clisp sbcl
) t
1204 #-
(or allegro ccl clisp cmu sbcl
) nil
1205 "If T, prevents the redefinition of REQUIRE. This is useful for
1206 lisps that treat REQUIRE specially in the compiler.")
1208 (defvar *multiple-lisp-support
* t
1209 "If T, afs-binary-directory will try to return a name dependent
1210 on the particular lisp compiler version being used.")
1212 ;;; home-subdirectory --
1213 ;;; HOME-SUBDIRECTORY is used only in *central-registry* below.
1214 ;;; Note that CMU CL 17e does not understand the ~/ shorthand for home
1218 ;;; 20020220 Marco Antoniotti
1219 ;;; The #-cormanlisp version is the original one, which is broken anyway, since
1220 ;;; it is UNIX dependent.
1221 ;;; I added the kludgy #+cormalisp (v 1.5) one, since it is missing
1222 ;;; the ANSI USER-HOMEDIR-PATHNAME function.
1224 (defun home-subdirectory (directory)
1225 (concatenate 'string
1228 #+scl
"file://home/"
1229 #-
(or :sbcl
:cmu
:scl
)
1230 (let ((homedir (user-homedir-pathname)))
1231 (or (and homedir
(namestring homedir
))
1236 (defun home-subdirectory (directory)
1237 (declare (type string directory
))
1238 (concatenate 'string
"C:\\" directory
))
1240 ;;; The following function is available for users to add
1241 ;;; (setq mk:*central-registry* (defsys-env-search-path))
1242 ;;; to Lisp init files in order to use the value of the DEFSYSPATH
1243 ;;; instead of directly coding it in the file.
1245 (defun defsys-env-search-path ()
1246 "This function grabs the value of the DEFSYSPATH environment variable
1247 and breaks the search path into a list of paths."
1248 (remove-duplicates (split-string (sys:getenv
"DEFSYSPATH") :item
#\
:)
1249 :test
#'string-equal
))
1251 ;;; Change this variable to set up the location of a central
1252 ;;; repository for system definitions if you want one.
1253 ;;; This is a defvar to allow users to change the value in their
1254 ;;; lisp init files without worrying about it reverting if they
1255 ;;; reload defsystem for some reason.
1257 ;;; Note that if a form is included in the registry list, it will be evaluated
1258 ;;; in COMPUTE-SYSTEM-PATH to return the appropriate directory to check.
1260 (defvar *central-registry
*
1261 `(;; Current directory
1263 #+:LUCID
(working-directory)
1264 #+ACLPC
(current-directory)
1265 #+:allegro
(excl:current-directory
)
1266 #+:sbcl
(progn *default-pathname-defaults
*)
1267 #+(or :cmu
:scl
) (ext:default-directory
)
1268 ;; *** Marco Antoniotti <marcoxa@icsi.berkeley.edu>
1269 ;; Somehow it is better to qualify default-directory in CMU with
1270 ;; the appropriate package (i.e. "EXTENSIONS".)
1271 ;; Same for Allegro.
1272 #+(and :lispworks
(not :lispworks4
))
1273 ,(multiple-value-bind (major minor
)
1274 #-
:lispworks-personal-edition
1275 (values system
::*major-version-number
*
1276 system
::*minor-version-number
*)
1277 #+:lispworks-personal-edition
1278 (values system
::*major-version-number
*
1279 system
::*minor-version-number
*)
1281 (and (= major
3) (> minor
2))
1282 (and (= major
3) (= minor
2)
1283 (equal (lisp-implementation-version) "3.2.1")))
1284 `(make-pathname :directory
1285 ,(find-symbol "*CURRENT-WORKING-DIRECTORY*"
1286 (find-package "SYSTEM")))
1287 (find-symbol "*CURRENT-WORKING-DIRECTORY*"
1288 (find-package "LW"))))
1290 (hcl:get-working-directory
)
1293 (mk::home-subdirectory
"lisp/systems/")
1296 "/usr/local/lisp/Registry/")
1297 "Central directory of system definitions. May be either a single
1298 directory pathname, or a list of directory pathnames to be checked
1299 after the local directory.")
1302 (defun add-registry-location (pathname)
1303 "Adds a path to the central registry."
1304 (pushnew pathname
*central-registry
* :test
#'equal
))
1306 (defvar *bin-subdir
* ".bin/"
1307 "The subdirectory of an AFS directory where the binaries are really kept.")
1309 ;;; These variables set up defaults for operate-on-system, and are used
1310 ;;; for communication in lieu of parameter passing. Yes, this is bad,
1311 ;;; but it keeps the interface small. Also, in the case of the -if-no-binary
1312 ;;; variables, parameter passing would require multiple value returns
1313 ;;; from some functions. Why make life complicated?
1314 (defvar *tell-user-when-done
* nil
1315 "If T, system will print ...DONE at the end of an operation")
1316 (defvar *oos-verbose
* nil
1317 "Operate on System Verbose Mode")
1318 (defvar *oos-test
* nil
1319 "Operate on System Test Mode")
1320 (defvar *load-source-if-no-binary
* nil
1321 "If T, system will try loading the source if the binary is missing")
1322 (defvar *bother-user-if-no-binary
* t
1323 "If T, the system will ask the user whether to load the source if
1324 the binary is missing")
1325 (defvar *load-source-instead-of-binary
* nil
1326 "If T, the system will load the source file instead of the binary.")
1327 (defvar *compile-during-load
* :query
1328 "If T, the system will compile source files during load if the
1329 binary file is missing. If :query, it will ask the user for
1331 (defvar *minimal-load
* nil
1332 "If T, the system tries to avoid reloading files that were already loaded
1335 (defvar *files-missing-is-an-error
* t
1336 "If both the source and binary files are missing, signal a continuable
1337 error instead of just a warning.")
1339 (defvar *operations-propagate-to-subsystems
* t
1340 "If T, operations like :COMPILE and :LOAD propagate to subsystems
1341 of a system that are defined either using a component-type of :system
1342 or by another defsystem form.")
1344 ;;; Particular to CMULisp
1345 (defvar *compile-error-file-type
* "err"
1346 "File type of compilation error file in cmulisp")
1347 (defvar *cmu-errors-to-terminal
* t
1348 "Argument to :errors-to-terminal in compile-file in cmulisp")
1349 (defvar *cmu-errors-to-file
* t
1350 "If T, cmulisp will write an error file during compilation")
1352 ;;; ********************************
1353 ;;; Global Variables ***************
1354 ;;; ********************************
1356 ;;; Massage people's *features* into better shape.
1357 (eval-when (compile load eval
)
1358 (dolist (feature *features
*)
1359 (when (and (symbolp feature
) ; 3600
1360 (equal (symbol-name feature
) "CMU"))
1361 (pushnew :CMU
*features
*)))
1364 (when (search "IBM RT PC" (machine-type))
1365 (pushnew :ibm-rt-pc
*features
*))
1368 ;;; *filename-extensions* is a cons of the source and binary extensions.
1369 (defvar *filename-extensions
*
1370 (car `(#+(and Symbolics Lispm
) ("lisp" .
"bin")
1371 #+(and dec common vax
(not ultrix
)) ("LSP" .
"FAS")
1372 #+(and dec common vax ultrix
) ("lsp" .
"fas")
1373 #+ACLPC
("lsp" .
"fsl")
1374 #+CLISP
("lisp" .
"fas")
1376 #+ECL
("lsp" .
#+msvc
"obj" #-msvc
"fas")
1377 #+IBCL
("lsp" .
"o")
1378 #+Xerox
("lisp" .
"dfasl")
1379 ;; Lucid on Silicon Graphics
1380 #+(and Lucid MIPS
) ("lisp" .
"mbin")
1381 ;; the entry for (and lucid hp300) must precede
1382 ;; that of (and lucid mc68000) for hp9000/300's running lucid,
1383 ;; since *features* on hp9000/300's also include the :mc68000
1385 #+(and lucid hp300
) ("lisp" .
"6bin")
1386 #+(and Lucid MC68000
) ("lisp" .
"lbin")
1387 #+(and Lucid Vax
) ("lisp" .
"vbin")
1388 #+(and Lucid Prime
) ("lisp" .
"pbin")
1389 #+(and Lucid SUNRise
) ("lisp" .
"sbin")
1390 #+(and Lucid SPARC
) ("lisp" .
"sbin")
1391 #+(and Lucid
:IBM-RT-PC
) ("lisp" .
"bbin")
1392 ;; PA is Precision Architecture, HP's 9000/800 RISC cpu
1393 #+(and Lucid PA
) ("lisp" .
"hbin")
1394 #+excl
("cl" .
,(pathname-type (compile-file-pathname "foo.cl")))
1395 #+(or cmu scl
) ("lisp" .
,(or (c:backend-fasl-file-type c
:*backend
*) "fasl"))
1396 ; #+(and :CMU (not (or :sgi :sparc))) ("lisp" . "fasl")
1397 ; #+(and :CMU :sgi) ("lisp" . "sgif")
1398 ; #+(and :CMU :sparc) ("lisp" . "sparcf")
1399 #+PRIME
("lisp" .
"pbin")
1401 #+TI
("lisp" .
#.
(string (si::local-binary-file-type
)))
1402 #+:gclisp
("LSP" .
"F2S")
1403 #+pyramid
("clisp" .
"o")
1405 ;; Harlequin LispWorks
1406 #+:lispworks
("lisp" .
,COMPILER
:*FASL-EXTENSION-STRING
*)
1407 ; #+(and :sun4 :lispworks) ("lisp" . "wfasl")
1408 ; #+(and :mips :lispworks) ("lisp" . "mfasl")
1409 #+:mcl
("lisp" .
,(pathname-type (compile-file-pathname "foo.lisp")))
1410 #+:coral
("lisp" .
"fasl")
1413 ("lisp" .
,(pathname-type (compile-file-pathname "foo.lisp")))))
1414 "Filename extensions for Common Lisp. A cons of the form
1415 (Source-Extension . Binary-Extension). If the system is
1416 unknown (as in *features* not known), defaults to lisp and fasl.")
1418 (defvar *system-extension
*
1419 ;; MS-DOS systems can only handle three character extensions.
1422 "The filename extension to use with systems.")
1424 ;;; The above variables and code should be extended to allow a list of
1425 ;;; valid extensions for each lisp implementation, instead of a single
1426 ;;; extension. When writing a file, the first extension should be used.
1427 ;;; But when searching for a file, every extension in the list should
1428 ;;; be used. For example, CMU Common Lisp recognizes "lisp" "l" "cl" and
1429 ;;; "lsp" (*load-source-types*) as source code extensions, and
1430 ;;; (c:backend-fasl-file-type c:*backend*)
1431 ;;; (c:backend-byte-fasl-file-type c:*backend*)
1432 ;;; and "fasl" as binary (object) file extensions (*load-object-types*).
1434 ;;; Note that the above code is used below in the LANGUAGE defstruct.
1436 ;;; There is no real support for this variable being nil, so don't change it.
1437 ;;; Note that in any event, the toplevel system (defined with defsystem)
1438 ;;; will have its dependencies delayed. Not having dependencies delayed
1439 ;;; might be useful if we define several systems within one defsystem.
1440 (defvar *system-dependencies-delayed
* t
1441 "If T, system dependencies are expanded at run time")
1443 ;;; Replace this with consp, dammit!
1444 (defun non-empty-listp (list)
1445 (and list
(listp list
)))
1447 ;;; ********************************
1448 ;;; Component Operation Definition *
1449 ;;; ********************************
1450 (eval-when (:compile-toplevel
:load-toplevel
:execute
)
1451 (defvar *version-dir
* nil
1452 "The version subdir. bound in operate-on-system.")
1453 (defvar *version-replace
* nil
1454 "The version replace. bound in operate-on-system.")
1455 (defvar *version
* nil
1456 "Default version."))
1458 (defvar *component-operations
* (make-hash-table :test
#'equal
)
1459 "Hash table of (operation-name function) pairs.")
1460 (defun component-operation (name &optional operation
)
1462 (setf (gethash name
*component-operations
*) operation
)
1463 (gethash name
*component-operations
*)))
1465 ;;; ********************************
1466 ;;; AFS @sys immitator *************
1467 ;;; ********************************
1469 ;;; mc 11-Apr-91: Bashes MCL's point reader, so commented out.
1471 (eval-when (compile load eval
)
1472 ;; Define #@"foo" as a shorthand for (afs-binary-directory "foo").
1475 ;; "foo/.bin/rt_mach/"
1476 (set-dispatch-macro-character
1478 #'(lambda (stream char arg
)
1479 (declare (ignore char arg
))
1480 `(afs-binary-directory ,(read stream t nil t
)))))
1482 (defvar *find-irix-version-script
*
1484 s/^[^M]*IRIX Execution Environment 1, *[a-zA-Z]* *\\([^ ]*\\)/\\1/p\\
1488 (defun operating-system-version ()
1490 (let* ((full-version (software-version))
1491 (blank-pos (search " " full-version
))
1492 (os (subseq full-version
0 blank-pos
))
1493 (version-rest (subseq full-version
1496 (setq blank-pos
(search " " version-rest
))
1497 (setq version-rest
(subseq version-rest
1499 (setq blank-pos
(search " " version-rest
))
1500 (setq os-version
(subseq version-rest
0 blank-pos
))
1501 (setq version-rest
(subseq version-rest
1503 (setq blank-pos
(search " " version-rest
))
1504 (setq version-rest
(subseq version-rest
1506 (concatenate 'string
1507 os
" " os-version
)) ; " " version-rest
1508 #+(and :sgi
:cmu
:sbcl
)
1509 (concatenate 'string
1512 #+(and :lispworks
:irix
)
1513 (let ((soft-type (software-type)))
1514 (if (equalp soft-type
"IRIX5")
1516 (foreign:call-system
1517 (format nil
"versions ~A | sed -e ~A > ~A"
1519 *find-irix-version-script
*
1522 (with-open-file (s "irix-version")
1523 (format nil
"IRIX ~S"
1526 #-
(or (and :excl
:sgi
) (and :cmu
:sgi
) (and :lispworks
:irix
))
1529 (defun compiler-version ()
1530 #+:lispworks
(concatenate 'string
1531 "lispworks" " " (lisp-implementation-version))
1532 #+excl
(concatenate 'string
1533 "excl" " " excl
::*common-lisp-version-number
*)
1534 #+sbcl
(concatenate 'string
1535 "sbcl" " " (lisp-implementation-version))
1536 #+cmu
(concatenate 'string
1537 "cmu" " " (lisp-implementation-version))
1538 #+scl
(concatenate 'string
1539 "scl" " " (lisp-implementation-version))
1550 #+symbolics
"symbolics"
1556 (defun afs-binary-directory (root-directory)
1557 ;; Function for obtaining the directory AFS's @sys feature would have
1558 ;; chosen when we're not in AFS. This function is useful as the argument
1559 ;; to :binary-pathname in defsystem. For example,
1560 ;; :binary-pathname (afs-binary-directory "scanner/")
1561 (let ((machine (machine-type-translation
1562 #-
(and :sgi
:allegro-version
>= (version>= 4 2))
1564 #+(and :sgi
:allegro-version
>= (version>= 4 2))
1566 (software (software-type-translation
1567 #-
(and :sgi
(or :cmu
:sbcl
:scl
1568 (and :allegro-version
>= (version>= 4 2))))
1570 #+(and :sgi
(or :cmu
:sbcl
:scl
1571 (and :allegro-version
>= (version>= 4 2))))
1572 (operating-system-version)))
1573 (lisp (compiler-type-translation (compiler-version))))
1574 ;; pmax_mach rt_mach sun3_35 sun3_mach vax_mach
1575 (setq root-directory
(namestring root-directory
))
1576 (setq root-directory
(ensure-trailing-slash root-directory
))
1577 (format nil
"~A~@[~A~]~@[~A/~]"
1580 (if *multiple-lisp-support
*
1581 (afs-component machine software lisp
)
1582 (afs-component machine software
)))))
1584 (defun afs-source-directory (root-directory &optional version-flag
)
1585 ;; Function for obtaining the directory AFS's @sys feature would have
1586 ;; chosen when we're not in AFS. This function is useful as the argument
1587 ;; to :source-pathname in defsystem.
1588 (setq root-directory
(namestring root-directory
))
1589 (setq root-directory
(ensure-trailing-slash root-directory
))
1590 (format nil
"~A~@[~A/~]"
1592 (and version-flag
(translate-version *version
*))))
1594 (defun null-string (s)
1596 (string-equal s
"")))
1598 (defun ensure-trailing-slash (dir)
1600 (not (null-string dir
))
1601 (not (char= (char dir
1604 (not (char= (char dir
1608 (concatenate 'string dir
"/")
1611 (defun afs-component (machine software
&optional lisp
)
1612 (format nil
"~@[~A~]~@[_~A~]~@[_~A~]"
1614 (or software
"mach")
1617 (defvar *machine-type-alist
* (make-hash-table :test
#'equal
)
1618 "Hash table for retrieving the machine-type")
1619 (defun machine-type-translation (name &optional operation
)
1621 (setf (gethash (string-upcase name
) *machine-type-alist
*) operation
)
1622 (gethash (string-upcase name
) *machine-type-alist
*)))
1624 (machine-type-translation "IBM RT PC" "rt")
1625 (machine-type-translation "DEC 3100" "pmax")
1626 (machine-type-translation "DEC VAX-11" "vax")
1627 (machine-type-translation "DECstation" "pmax")
1628 (machine-type-translation "Sun3" "sun3")
1629 (machine-type-translation "Sun-4" "sun4")
1630 (machine-type-translation "MIPS Risc" "mips")
1631 (machine-type-translation "SGI" "sgi")
1632 (machine-type-translation "Silicon Graphics Iris 4D" "sgi")
1633 (machine-type-translation "Silicon Graphics Iris 4D (R3000)" "sgi")
1634 (machine-type-translation "Silicon Graphics Iris 4D (R4000)" "sgi")
1635 (machine-type-translation "Silicon Graphics Iris 4D (R4400)" "sgi")
1636 (machine-type-translation "IP22" "sgi")
1637 ;;; MIPS R4000 Processor Chip Revision: 3.0
1638 ;;; MIPS R4400 Processor Chip Revision: 5.0
1639 ;;; MIPS R4600 Processor Chip Revision: 1.0
1640 (machine-type-translation "IP20" "sgi")
1641 ;;; MIPS R4000 Processor Chip Revision: 3.0
1642 (machine-type-translation "IP17" "sgi")
1643 ;;; MIPS R4000 Processor Chip Revision: 2.2
1644 (machine-type-translation "IP12" "sgi")
1645 ;;; MIPS R2000A/R3000 Processor Chip Revision: 3.0
1646 (machine-type-translation "IP7" "sgi")
1647 ;;; MIPS R2000A/R3000 Processor Chip Revision: 3.0
1649 (machine-type-translation "x86" "x86")
1651 (machine-type-translation "IBM PC Compatible" "x86")
1653 (machine-type-translation "I686" "x86")
1655 (machine-type-translation "PC/386" "x86")
1659 (machine-type-translation "AMD64" "amd64")
1661 #+(and :lucid
:sun
:mc68000
)
1662 (machine-type-translation "unknown" "sun3")
1665 (defvar *software-type-alist
* (make-hash-table :test
#'equal
)
1666 "Hash table for retrieving the software-type")
1667 (defun software-type-translation (name &optional operation
)
1669 (setf (gethash (string-upcase name
) *software-type-alist
*) operation
)
1670 (gethash (string-upcase name
) *software-type-alist
*)))
1672 (software-type-translation "BSD UNIX" "mach") ; "unix"
1673 (software-type-translation "Ultrix" "mach") ; "ultrix"
1674 (software-type-translation "SunOS" "SunOS")
1675 (software-type-translation "MACH/4.3BSD" "mach")
1676 (software-type-translation "IRIX System V" "irix") ; (software-type)
1677 (software-type-translation "IRIX5" "irix5")
1678 ;;(software-type-translation "IRIX liasg5 5.2 02282016 IP22 mips" "irix5") ; (software-version)
1680 (software-type-translation "IRIX 5.2" "irix5")
1681 (software-type-translation "IRIX 5.3" "irix5")
1682 (software-type-translation "IRIX5.2" "irix5")
1683 (software-type-translation "IRIX5.3" "irix5")
1685 (software-type-translation "Linux" "linux") ; Lispworks for Linux
1686 (software-type-translation "Linux 2.x, Redhat 6.x and 7.x" "linux") ; ACL
1687 (software-type-translation "Microsoft Windows 9x/Me and NT/2000/XP" "win32")
1688 (software-type-translation "Windows NT" "win32") ; LW for Windows
1689 (software-type-translation "ANSI C program" "ansi-c") ; CLISP
1690 (software-type-translation "C compiler" "ansi-c") ; CLISP for Win32
1692 (software-type-translation nil
"")
1695 (software-type-translation "Unix"
1697 #+(and :lcl3.0
(not :lcl4.0
)) "3.0")
1699 (defvar *compiler-type-alist
* (make-hash-table :test
#'equal
)
1700 "Hash table for retrieving the Common Lisp type")
1701 (defun compiler-type-translation (name &optional operation
)
1703 (setf (gethash (string-upcase name
) *compiler-type-alist
*) operation
)
1704 (gethash (string-upcase name
) *compiler-type-alist
*)))
1706 (compiler-type-translation "lispworks 3.2.1" "lispworks")
1707 (compiler-type-translation "lispworks 3.2.60 beta 6" "lispworks")
1708 (compiler-type-translation "lispworks 4.2.0" "lispworks")
1711 (eval-when (:compile-toplevel
:load-toplevel
:execute
)
1712 (unless (or (find :case-sensitive common-lisp
:*features
*)
1713 (find :case-insensitive common-lisp
:*features
*))
1714 (if (or (eq excl
:*current-case-mode
* :case-sensitive-lower
)
1715 (eq excl
:*current-case-mode
* :case-sensitive-upper
))
1716 (push :case-sensitive common-lisp
:*features
*)
1717 (push :case-insensitive common-lisp
:*features
*))))
1720 #+(and allegro case-sensitive ics
)
1721 (compiler-type-translation "excl 6.1" "excl-m")
1722 #+(and allegro case-sensitive
(not ics
))
1723 (compiler-type-translation "excl 6.1" "excl-m8")
1725 #+(and allegro case-insensitive ics
)
1726 (compiler-type-translation "excl 6.1" "excl-a")
1727 #+(and allegro case-insensitive
(not ics
))
1728 (compiler-type-translation "excl 6.1" "excl-a8")
1730 (compiler-type-translation "excl 4.2" "excl")
1731 (compiler-type-translation "excl 4.1" "excl")
1732 (compiler-type-translation "cmu 17f" "cmu")
1733 (compiler-type-translation "cmu 17e" "cmu")
1734 (compiler-type-translation "cmu 17d" "cmu")
1736 (compiler-type-translation "scl 1.2.7" "scl")
1737 (compiler-type-translation "scl 1.2.8" "scl")
1738 (compiler-type-translation "scl 1.2.9" "scl")
1740 ;;; ********************************
1741 ;;; System Names *******************
1742 ;;; ********************************
1744 ;;; If you use strings for system names, be sure to use the same case
1745 ;;; as it appears on disk, if the filesystem is case sensitive.
1746 (defun canonicalize-system-name (name)
1747 ;; Originally we were storing systems using GET. This meant that the
1748 ;; name of a system had to be a symbol, so we interned the symbols
1749 ;; in the keyword package to avoid package dependencies. Now that we're
1750 ;; storing the systems in a hash table, we've switched to using strings.
1751 ;; Since the hash table is case sensitive, we use uppercase strings.
1752 ;; (Names of modules and files may be symbols or strings.)
1753 #||
(if (keywordp name
)
1755 (intern (string-upcase (string name
)) "KEYWORD"))||
#
1756 (if (stringp name
) (string-upcase name
) (string-upcase (string name
))))
1758 (defvar *defined-systems
* (make-hash-table :test
#'equal
)
1759 "Hash table containing the definitions of all known systems.")
1761 (defun get-system (name)
1762 "Returns the definition of the system named NAME."
1763 (gethash (canonicalize-system-name name
) *defined-systems
*))
1765 (defsetf get-system
(name) (value)
1766 `(setf (gethash (canonicalize-system-name ,name
) *defined-systems
*) ,value
))
1768 (defun undefsystem (name)
1769 "Removes the definition of the system named NAME."
1770 (setf (get-system name
) nil
))
1772 (defun defined-systems ()
1773 "Returns a list of defined systems."
1775 (maphash #'(lambda (key value
)
1776 (declare (ignore key
))
1777 (push value result
))
1781 ;;; ********************************
1782 ;;; Directory Pathname Hacking *****
1783 ;;; ********************************
1785 ;;; Unix example: An absolute directory starts with / while a
1786 ;;; relative directory doesn't. A directory ends with /, while
1787 ;;; a file's pathname doesn't. This is important 'cause
1788 ;;; (pathname-directory "foo/bar") will return "foo" and not "foo/".
1790 ;;; I haven't been able to test the fix to the problem with symbolics
1791 ;;; hosts. Essentially, append-directories seems to have been tacking
1792 ;;; the default host onto the front of the pathname (e.g., mk::source-pathname
1793 ;;; gets a "B:" on front) and this overrides the :host specified in the
1794 ;;; component. The value of :host should override that specified in
1795 ;;; the :source-pathname and the default file server. If this doesn't
1796 ;;; fix things, specifying the host in the root pathname "F:>root-dir>"
1797 ;;; may be a good workaround.
1799 ;;; Need to verify that merging of pathnames where modules are located
1800 ;;; on different devices (in VMS-based VAXLisp) now works.
1802 ;;; Merge-pathnames works for VMS systems. In VMS systems, the directory
1803 ;;; part is enclosed in square brackets, e.g.,
1804 ;;; "[root.child.child_child]" or "[root.][child.][child_child]"
1805 ;;; To concatenate directories merge-pathnames works as follows:
1806 ;;; (merge-pathnames "" "[root]") ==> "[root]"
1807 ;;; (merge-pathnames "[root.]" "[son]file.ext") ==> "[root.son]file.ext"
1808 ;;; (merge-pathnames "[root.]file.ext" "[son]") ==> "[root.son]file.ext"
1809 ;;; (merge-pathnames "[root]file.ext" "[son]") ==> "[root]file.ext"
1810 ;;; Thus the problem with the #-VMS code was that it was merging x y into
1811 ;;; [[x]][y] instead of [x][y] or [x]y.
1813 ;;; Miscellaneous notes:
1814 ;;; On GCLisp, the following are equivalent:
1815 ;;; "\\root\\subdir\\BAZ"
1816 ;;; "/root/subdir/BAZ"
1817 ;;; On VAXLisp, the following are equivalent:
1818 ;;; "[root.subdir]BAZ"
1819 ;;; "[root.][subdir]BAZ"
1820 ;;; Use #+:vaxlisp for VAXLisp 3.0, #+(and vms dec common vax) for v2.2
1822 (defun new-append-directories (absolute-dir relative-dir
)
1823 ;; Version of append-directories for CLtL2-compliant lisps. In particular,
1824 ;; they must conform to section 23.1.3 "Structured Directories". We are
1825 ;; willing to fix minor aberations in this function, but not major ones.
1826 ;; Tested in Allegro CL 4.0 (SPARC), Allegro CL 3.1.12 (DEC 3100),
1827 ;; CMU CL old and new compilers, Lucid 3.0, Lucid 4.0.
1828 (setf absolute-dir
(or absolute-dir
"")
1829 relative-dir
(or relative-dir
""))
1830 (let* ((abs-dir (pathname absolute-dir
))
1831 (rel-dir (pathname relative-dir
))
1832 (host (pathname-host abs-dir
))
1833 (device (if (null-string absolute-dir
) ; fix for CMU CL old compiler
1834 (pathname-device rel-dir
)
1835 (pathname-device abs-dir
)))
1836 (abs-directory (directory-to-list (pathname-directory abs-dir
)))
1837 (abs-keyword (when (keywordp (car abs-directory
))
1838 (pop abs-directory
)))
1839 ;; Stig (July 2001):
1840 ;; Somehow CLISP dies on the next line, but NIL is ok.
1841 (abs-name (ignore-errors (file-namestring abs-dir
))) ; was pathname-name
1842 (rel-directory (directory-to-list (pathname-directory rel-dir
)))
1843 (rel-keyword (when (keywordp (car rel-directory
))
1844 (pop rel-directory
)))
1845 #-
(or :MCL
:gcl
:sbcl
:clisp
:cmu
) (rel-file (file-namestring rel-dir
))
1846 ;; Stig (July 2001);
1847 ;; These values seems to help clisp as well
1848 #+(or :MCL
:gcl
:sbcl
:clisp
:cmu
) (rel-name (pathname-name rel-dir
))
1849 #+(or :MCL
:gcl
:sbcl
:clisp
:cmu
) (rel-type (pathname-type rel-dir
))
1852 ;; TI Common Lisp pathnames can return garbage for file names because
1853 ;; of bizarreness in the merging of defaults. The following code makes
1854 ;; sure that the name is a valid name by comparing it with the
1855 ;; pathname-name. It also strips TI specific extensions and handles
1856 ;; the necessary case conversion. TI maps upper back into lower case
1858 #+TI
(if (search (pathname-name abs-dir
) abs-name
:test
#'string-equal
)
1859 (setf abs-name
(string-right-trim ".\x17" (string-upcase abs-name
)))
1860 (setf abs-name nil
))
1861 #+TI
(if (search (pathname-name rel-dir
) rel-file
:test
#'string-equal
)
1862 (setf rel-file
(string-right-trim ".\x17" (string-upcase rel-file
)))
1863 (setf rel-file nil
))
1864 ;; Allegro v4.0/4.1 parses "/foo" into :directory '(:absolute :root)
1865 ;; and filename "foo". The namestring of a pathname with
1866 ;; directory '(:absolute :root "foo") ignores everything after the
1868 #+(and allegro-version
>= (version>= 4 0))
1869 (when (eq (car abs-directory
) :root
) (pop abs-directory
))
1870 #+(and allegro-version
>= (version>= 4 0))
1871 (when (eq (car rel-directory
) :root
) (pop rel-directory
))
1873 (when (and abs-name
(not (null-string abs-name
))) ; was abs-name
1874 (cond ((and (null abs-directory
) (null abs-keyword
))
1875 #-
(or :lucid TI
) (setf abs-keyword
(car (pathname-directory "./")))
1876 (setf abs-directory
(list abs-name
)))
1878 (setf abs-directory
(append abs-directory
(list abs-name
))))))
1879 (when (and (null abs-directory
)
1880 (or (null abs-keyword
)
1881 ;; In Lucid, an abs-dir of nil gets a keyword of
1882 ;; :relative since (pathname-directory (pathname ""))
1883 ;; returns (:relative) instead of nil.
1884 #+:lucid
(eq abs-keyword
:relative
))
1886 ;; The following feature switches seem necessary in CMUCL
1887 ;; Marco Antoniotti 19990707
1888 #+(or :gcl
:sbcl
:CMU
)
1889 (if (typep abs-dir
'logical-pathname
)
1890 (setf abs-keyword
:absolute
)
1891 (setf abs-keyword rel-keyword
))
1892 #-
(or :gcl
:sbcl
:CMU
)
1893 (setf abs-keyword rel-keyword
))
1894 (setf directory
(append abs-directory rel-directory
))
1895 (when abs-keyword
(setf directory
(cons abs-keyword directory
)))
1896 #+lispworks
(when (and directory
(not (symbolp (first directory
)))) (setq directory
(cons :relative directory
)))
1898 (make-pathname :host host
1903 #-
(or :gcl
:sbcl
:MCL
:clisp
:cmu
) rel-file
1904 #+(or :gcl
:sbcl
:MCL
:clisp
:cmu
) rel-name
1906 #+(or :gcl
:sbcl
:MCL
:clisp
:cmu
) :type
1907 #+(or :gcl
:sbcl
:MCL
:clisp
:cmu
) rel-type
1909 ;(trace new-append-directories)
1912 (defun directory-to-list (directory)
1913 ;; The directory should be a list, but nonstandard implementations have
1914 ;; been known to use a vector or even a string.
1915 (cond ((listp directory
)
1917 ((stringp directory
)
1918 (cond ((find #\
; directory)
1919 ;; It's probably a logical pathname, so split at the
1921 (split-string directory
:item
#\
;))
1923 ((and (find #\
: directory
)
1924 (not (find #\
/ directory
)))
1925 ;; It's probably a MCL pathname, so split at the colons.
1926 (split-string directory
:item
#\
:))
1928 ;; It's probably a unix pathname, so split at the slash.
1929 (split-string directory
:item
#\
/))))
1931 (coerce directory
'list
))))
1932 ;(trace directory-to-list)
1935 (defparameter *append-dirs-tests
*
1936 '("~/foo/" "baz/bar.lisp"
1937 "~/foo" "baz/bar.lisp"
1938 "/foo/bar/" "baz/barf.lisp"
1939 "/foo/bar/" "/baz/barf.lisp"
1940 "foo/bar/" "baz/barf.lisp"
1941 "foo/bar" "baz/barf.lisp"
1942 "foo/bar" "/baz/barf.lisp"
1943 "foo/bar/" "/baz/barf.lisp"
1950 nil
"/baz/barf.lisp"
1953 (defun test-new-append-directories (&optional
(test-dirs *append-dirs-tests
*))
1954 (do* ((dir-list test-dirs
(cddr dir-list
))
1955 (abs-dir (car dir-list
) (car dir-list
))
1956 (rel-dir (cadr dir-list
) (cadr dir-list
)))
1957 ((null dir-list
) (values))
1958 (format t
"~&ABS: ~S ~18TREL: ~S ~41TResult: ~S"
1959 abs-dir rel-dir
(new-append-directories abs-dir rel-dir
))))
1962 <cl
> (test-new-append-directories)
1964 ABS
: "~/foo/" REL
: "baz/bar.lisp" Result
: "/usr0/mkant/foo/baz/bar.lisp"
1965 ABS
: "~/foo" REL
: "baz/bar.lisp" Result
: "/usr0/mkant/foo/baz/bar.lisp"
1966 ABS
: "/foo/bar/" REL
: "baz/barf.lisp" Result
: "/foo/bar/baz/barf.lisp"
1967 ABS
: "/foo/bar/" REL
: "/baz/barf.lisp" Result
: "/foo/bar/baz/barf.lisp"
1968 ABS
: "foo/bar/" REL
: "baz/barf.lisp" Result
: "foo/bar/baz/barf.lisp"
1969 ABS
: "foo/bar" REL
: "baz/barf.lisp" Result
: "foo/bar/baz/barf.lisp"
1970 ABS
: "foo/bar" REL
: "/baz/barf.lisp" Result
: "foo/bar/baz/barf.lisp"
1971 ABS
: "foo/bar/" REL
: "/baz/barf.lisp" Result
: "foo/bar/baz/barf.lisp"
1972 ABS
: "/foo/bar/" REL
: NIL Result
: "/foo/bar/"
1973 ABS
: "foo/bar/" REL
: NIL Result
: "foo/bar/"
1974 ABS
: "foo/bar" REL
: NIL Result
: "foo/bar/"
1975 ABS
: "foo" REL
: NIL Result
: "foo/"
1976 ABS
: "foo" REL
: "" Result
: "foo/"
1977 ABS
: NIL REL
: "baz/barf.lisp" Result
: "baz/barf.lisp"
1978 ABS
: NIL REL
: "/baz/barf.lisp" Result
: "/baz/barf.lisp"
1979 ABS
: NIL REL
: NIL Result
: ""
1983 (defun append-directories (absolute-directory relative-directory
)
1984 "There is no CL primitive for tacking a subdirectory onto a directory.
1985 We need such a function because defsystem has both absolute and
1986 relative pathnames in the modules. This is a somewhat ugly hack which
1987 seems to work most of the time. We assume that ABSOLUTE-DIRECTORY
1988 is a directory, with no filename stuck on the end. Relative-directory,
1989 however, may have a filename stuck on the end."
1990 (when (or absolute-directory relative-directory
)
1992 ;; KMR commented out because: when appending two logical pathnames,
1993 ;; using this code translates the first logical pathname then appends
1994 ;; the second logical pathname -- an error.
1996 ;; We need a reliable way to determine if a pathname is logical.
1997 ;; Allegro 4.1 does not recognize the syntax of a logical pathname
1998 ;; as being logical unless its logical host is already defined.
2000 #+(or (and allegro-version
>= (version>= 4 1))
2001 :logical-pathnames-mk
)
2002 ((and absolute-directory
2003 (logical-pathname-p absolute-directory
)
2005 ;; For use with logical pathnames package.
2006 (append-logical-directories-mk absolute-directory relative-directory
))
2009 ((namestring-probably-logical absolute-directory
)
2010 ;; A simplistic stab at handling logical pathnames
2011 (append-logical-pnames absolute-directory relative-directory
))
2014 ;; In VMS, merge-pathnames actually does what we want!!!
2016 (namestring (merge-pathnames (or absolute-directory
"")
2017 (or relative-directory
"")))
2019 (namestring (make-pathname :directory absolute-directory
2020 :name relative-directory
))
2021 ;; Cross your fingers and pray.
2022 #-
(or :VMS
:macl1.3
.2)
2023 (new-append-directories absolute-directory relative-directory
))
2026 (let ((absolute (pathname (or absolute-directory
""))))
2027 (when (or (pathname-name absolute
) (pathname-type absolute
))
2028 (let* ((directory (or (pathname-directory absolute
) '(:relative
)))
2029 (directory (append directory
(list (file-namestring absolute
)))))
2030 (setf absolute
(make-pathname :directory directory
2034 :defaults absolute
))))
2035 (ext:resolve-pathname
(or relative-directory
"")
2039 #+:logical-pathnames-mk
2040 (defun append-logical-directories-mk (absolute-dir relative-dir
)
2041 (lp:append-logical-directories absolute-dir relative-dir
))
2044 ;;; append-logical-pathnames-mk --
2045 ;;; The following is probably still bogus and it does not solve the
2046 ;;; problem of appending two logical pathnames.
2047 ;;; Anyway, as per suggetsion by KMR, the function is not called
2049 ;;; Hopefully this will not cause problems for ACL.
2051 #+(and (and allegro-version
>= (version>= 4 1))
2052 (not :logical-pathnames-mk
))
2053 (defun append-logical-directories-mk (absolute-dir relative-dir
)
2054 ;; We know absolute-dir and relative-dir are non nil. Moreover
2055 ;; absolute-dir is a logical pathname.
2056 (setq absolute-dir
(logical-pathname absolute-dir
))
2057 (etypecase relative-dir
2058 (string (setq relative-dir
(parse-namestring relative-dir
)))
2059 (pathname #| do nothing |
#))
2061 (translate-logical-pathname
2062 (merge-pathnames relative-dir absolute-dir
)))
2064 #| Old version
2002-
03-
02
2065 #+(and (and allegro-version
>= (version>= 4 1))
2066 (not :logical-pathnames-mk
))
2067 (defun append-logical-directories-mk (absolute-dir relative-dir
)
2068 ;; We know absolute-dir and relative-dir are non nil. Moreover
2069 ;; absolute-dir is a logical pathname.
2070 (setq absolute-dir
(logical-pathname absolute-dir
))
2071 (etypecase relative-dir
2072 (string (setq relative-dir
(parse-namestring relative-dir
)))
2073 (pathname #| do nothing |
#))
2075 (translate-logical-pathname
2077 :host
(or (pathname-host absolute-dir
)
2078 (pathname-host relative-dir
))
2079 :directory
(append (pathname-directory absolute-dir
)
2080 (cdr (pathname-directory relative-dir
)))
2081 :name
(or (pathname-name absolute-dir
)
2082 (pathname-name relative-dir
))
2083 :type
(or (pathname-type absolute-dir
)
2084 (pathname-type relative-dir
))
2085 :version
(or (pathname-version absolute-dir
)
2086 (pathname-version relative-dir
)))))
2089 #+(and (and allegro-version
>= (version>= 4 1))
2090 (not :logical-pathnames-mk
))
2091 (defun append-logical-directories-mk (absolute-dir relative-dir
)
2092 (when (or absolute-dir relative-dir
)
2093 (setq absolute-dir
(logical-pathname (or absolute-dir
""))
2094 relative-dir
(logical-pathname (or relative-dir
"")))
2095 (translate-logical-pathname
2097 :host
(or (pathname-host absolute-dir
)
2098 (pathname-host relative-dir
))
2099 :directory
(append (pathname-directory absolute-dir
)
2100 (cdr (pathname-directory relative-dir
)))
2101 :name
(or (pathname-name absolute-dir
)
2102 (pathname-name relative-dir
))
2103 :type
(or (pathname-type absolute-dir
)
2104 (pathname-type relative-dir
))
2105 :version
(or (pathname-version absolute-dir
)
2106 (pathname-version relative-dir
))))))
2109 ;;; determines if string or pathname object is logical
2110 #+:logical-pathnames-mk
2111 (defun logical-pathname-p (thing)
2112 (eq (lp:pathname-host-type thing
) :logical
))
2114 ;;; From Kevin Layer for 4.1final.
2115 #+(and (and allegro-version
>= (version>= 4 1))
2116 (not :logical-pathnames-mk
))
2117 (defun logical-pathname-p (thing)
2118 (typep (parse-namestring thing
) 'logical-pathname
))
2121 (defun pathname-logical-p (thing)
2123 (logical-pathname t
)
2124 #+clisp
; CLisp has non conformant Logical Pathnames.
2125 (pathname (pathname-logical-p (namestring thing
)))
2126 (string (and (= 1 (count #\
: thing
)) ; Shortcut.
2127 (ignore-errors (translate-logical-pathname thing
))
2131 ;;; This affects only one thing.
2132 ;;; 19990707 Marco Antoniotti
2136 (defun namestring-probably-logical (namestring)
2137 (and (stringp namestring
)
2138 ;; unix pathnames don't have embedded semicolons
2139 (find #\
; namestring)))
2142 (defun namestring-probably-logical (namestring)
2143 (and (stringp namestring
)
2144 (typep (parse-namestring namestring
) 'logical-pathname
)))
2148 ;;; 20000321 Marco Antoniotti
2149 (defun namestring-probably-logical (namestring)
2150 (pathname-logical-p namestring
))
2154 #|| This is incorrect
, as it strives to keep strings around
, when it
2155 shouldn
't. MERGE-PATHNAMES already DTRT.
2156 (defun append-logical-pnames (absolute relative
)
2157 (declare (type (or null string pathname
) absolute relative
))
2158 (let ((abs (if absolute
2159 #-clisp
(namestring absolute
)
2160 #+clisp absolute
;; Stig (July 2001): hack to avoid CLISP from translating the whole string
2162 (rel (if relative
(namestring relative
) ""))
2164 ;; Make sure the absolute directory ends with a semicolon unless
2165 ;; the pieces are null strings
2166 (unless (or (null-string abs
) (null-string rel
)
2167 (char= (char abs
(1- (length abs
)))
2169 (setq abs
(concatenate 'string abs
";")))
2170 ;; Return the concatenate pathnames
2171 (concatenate 'string abs rel
)))
2176 (defun append-logical-pnames (absolute relative
)
2177 (declare (type (or null string pathname
) absolute relative
))
2178 (let ((abs (if absolute
2180 (make-pathname :directory
(list :absolute
)
2186 (make-pathname :directory
(list :relative
)
2191 ;; The following is messed up because CMUCL and LW use different
2192 ;; defaults for host (in particular LW uses NIL). Thus
2193 ;; MERGE-PATHNAMES has legitimate different behaviors on both
2194 ;; implementations. Of course this is disgusting, but that is the
2195 ;; way it is and the rest tries to circumvent this crap.
2200 (namestring (merge-pathnames rel abs
)))
2202 ;; The following potentially translates the logical pathname
2203 ;; very early, but we cannot avoid it.
2204 (namestring (merge-pathnames rel
(translate-logical-pathname abs
))))
2207 (namestring (merge-pathnames rel abs
)))
2211 ;;; This was a try at appending a subdirectory onto a directory.
2212 ;;; It failed. We're keeping this around to prevent future mistakes
2213 ;;; of a similar sort.
2214 (defun merge-directories (absolute-directory relative-directory
)
2215 ;; replace concatenate with something more intelligent
2216 ;; i.e., concatenation won't work with some directories.
2217 ;; it should also behave well if the parent directory
2218 ;; has a filename at the end, or if the relative-directory ain't relative
2219 (when absolute-directory
2220 (setq absolute-directory
(pathname-directory absolute-directory
)))
2221 (concatenate 'string
2222 (or absolute-directory
"")
2223 (or relative-directory
"")))
2227 <cl
> (defun d (d n
) (namestring (make-pathname :directory d
:name n
)))
2230 <cl
> (d "~/foo/" "baz/bar.lisp")
2231 "/usr0/mkant/foo/baz/bar.lisp"
2233 <cl
> (d "~/foo" "baz/bar.lisp")
2234 "/usr0/mkant/foo/baz/bar.lisp"
2236 <cl
> (d "/foo/bar/" "baz/barf.lisp")
2237 "/foo/bar/baz/barf.lisp"
2239 <cl
> (d "foo/bar/" "baz/barf.lisp")
2240 "foo/bar/baz/barf.lisp"
2242 <cl
> (d "foo/bar" "baz/barf.lisp")
2243 "foo/bar/baz/barf.lisp"
2245 <cl
> (d "foo/bar" "/baz/barf.lisp")
2246 "foo/bar//baz/barf.lisp"
2248 <cl
> (d "foo/bar" nil
)
2251 <cl
> (d nil
"baz/barf.lisp")
2259 (defun new-file-type (pathname type
)
2260 (make-pathname :type type
:defaults pathname
))
2263 ;;; ********************************
2264 ;;; Component Defstruct ************
2265 ;;; ********************************
2266 (defvar *source-pathname-default
* nil
2267 "Default value of :source-pathname keyword in DEFSYSTEM. Set this to
2268 \"\" to avoid having to type :source-pathname \"\" all the time.")
2270 (defvar *binary-pathname-default
* nil
2271 "Default value of :binary-pathname keyword in DEFSYSTEM.")
2273 ;;; Removed TIME slot, which has been made unnecessary by the new definition
2274 ;;; of topological-sort.
2276 (defstruct (topological-sort-node (:conc-name topsort-
))
2277 (color :white
:type
(member :gray
:black
:white
))
2281 (defstruct (component (:include topological-sort-node
)
2282 (:print-function print-component
))
2283 (type :file
; to pacify the CMUCL compiler (:type is alway supplied)
2284 :type
(member :defsystem
2291 (name nil
:type
(or symbol string
))
2292 (indent 0 :type
(mod 1024)) ; Number of characters of indent in
2293 ; verbose output to the user.
2294 host
; The pathname host (i.e., "/../a").
2295 device
; The pathname device.
2296 source-root-dir
; Relative or absolute (starts
2297 ; with "/"), directory or file
2299 (source-pathname *source-pathname-default
*)
2300 source-extension
; A string, e.g., "lisp"
2302 (binary-pathname *binary-pathname-default
*)
2304 binary-extension
; A string, e.g., "fasl". If
2305 ; NIL, uses default for
2307 package
; Package for use-package.
2309 ;; The following three slots are used to provide for alternate compilation
2310 ;; and loading functions for the files contained within a component. If
2311 ;; a component has a compiler or a loader specified, those functions are
2312 ;; used. Otherwise the functions are derived from the language. If no
2313 ;; language is specified, it defaults to Common Lisp (:lisp). Other current
2314 ;; possible languages include :scheme (PseudoScheme) and :c, but the user
2315 ;; can define additional language mappings. Compilation functions should
2316 ;; accept a pathname argument and a :output-file keyword; loading functions
2317 ;; just a pathname argument. The default functions are #'compile-file and
2318 ;; #'load. Unlike fdmm's SET-LANGUAGE macro, this allows a defsystem to
2320 (language nil
:type
(or null symbol
))
2321 (compiler nil
:type
(or null symbol function
))
2322 (loader nil
:type
(or null symbol function
))
2323 (compiler-options nil
:type list
) ; A list of compiler options to
2324 ; use for compiling this
2325 ; component. These must be
2326 ; keyword options supported by
2329 (components () :type list
) ; A list of components
2330 ; comprising this component's
2332 (depends-on () :type list
) ; A list of the components
2333 ; this one depends on. may
2334 ; refer only to the components
2335 ; at the same level as this
2337 proclamations
; Compiler options, such as
2338 ; '(optimize (safety 3)).
2339 initially-do
; Form to evaluate before the
2341 finally-do
; Form to evaluate after the operation.
2342 compile-form
; For foreign libraries.
2343 load-form
; For foreign libraries.
2345 ;; load-time ; The file-write-date of the
2346 ; binary/source file loaded.
2348 ;; If load-only is T, will not compile the file on operation :compile.
2349 ;; In other words, for files which are :load-only T, loading the file
2350 ;; satisfies any demand to recompile.
2351 load-only
; If T, will not compile this
2352 ; file on operation :compile.
2353 ;; If compile-only is T, will not load the file on operation :compile.
2354 ;; Either compiles or loads the file, but not both. In other words,
2355 ;; compiling the file satisfies the demand to load it. This is useful
2356 ;; for PCL defmethod and defclass definitions, which wrap a
2357 ;; (eval-when (compile load eval) ...) around the body of the definition.
2358 ;; This saves time in some lisps.
2359 compile-only
; If T, will not load this
2360 ; file on operation :compile.
2361 #|| ISI Extension ||
#
2362 load-always
; If T, will force loading
2363 ; even if file has not
2366 (banner nil
:type
(or null string
))
2368 (documentation nil
:type
(or null string
)) ; Optional documentation slot
2372 ;;; To allow dependencies from "foreign systems" like ASDF or one of
2373 ;;; the proprietary ones like ACL or LW.
2375 (defstruct (foreign-system (:include component
(type :system
)))
2376 kind
; This is a keyword: (member :asdf :pcl :lispworks-common-defsystem ...)
2377 object
; The actual foreign system object.
2381 (defun register-foreign-system (name &key representation kind
)
2382 (declare (type (or symbol string
) name
))
2383 (let ((fs (make-foreign-system :name name
2385 :object representation
)))
2386 (setf (get-system name
) fs
)))
2390 (define-condition missing-component
(simple-condition)
2391 ((name :reader missing-component-name
2393 (component :reader missing-component-component
2394 :initarg
:component
)
2396 #-gcl
(:default-initargs
:component nil
)
2397 (:report
(lambda (mmc stream
)
2398 (format stream
"MK:DEFSYSTEM: missing component ~S for ~S."
2399 (missing-component-name mmc
)
2400 (missing-component-component mmc
))))
2403 (define-condition missing-module
(missing-component)
2405 (:report
(lambda (mmc stream
)
2406 (format stream
"MK:DEFSYSTEM: missing module ~S for ~S."
2407 (missing-component-name mmc
)
2408 (missing-component-component mmc
))))
2411 (define-condition missing-system
(missing-module)
2413 (:report
(lambda (msc stream
)
2414 (format stream
"MK:DEFSYSTEM: missing system ~S~@[ for S~]."
2415 (missing-component-name msc
)
2416 (missing-component-component msc
))))
2421 (defvar *file-load-time-table
* (make-hash-table :test
#'equal
)
2422 "Hash table of file-write-dates for the system definitions and
2423 files in the system definitions.")
2424 (defun component-load-time (component)
2426 (etypecase component
2427 (string (gethash component
*file-load-time-table
*))
2428 (pathname (gethash (namestring component
) *file-load-time-table
*))
2430 (ecase (component-type component
)
2432 (let* ((name (component-name component
))
2433 (path (when name
(compute-system-path name nil
))))
2434 (declare (type (or string pathname null
) path
))
2436 (gethash (namestring path
) *file-load-time-table
*))))
2437 ((:file
:private-file
)
2438 ;; Use only :source pathname to identify component's
2440 (let ((path (component-full-pathname component
:source
)))
2442 (gethash path
*file-load-time-table
*)))))))))
2445 (defsetf component-load-time
(component) (value)
2447 (etypecase ,component
2448 (string (setf (gethash ,component
*file-load-time-table
*) ,value
))
2449 (pathname (setf (gethash (namestring (the pathname
,component
))
2450 *file-load-time-table
*)
2453 (ecase (component-type ,component
)
2455 (let* ((name (component-name ,component
))
2456 (path (when name
(compute-system-path name nil
))))
2457 (declare (type (or string pathname null
) path
))
2459 (setf (gethash (namestring path
) *file-load-time-table
*)
2461 ((:file
:private-file
)
2462 ;; Use only :source pathname to identify file.
2463 (let ((path (component-full-pathname ,component
:source
)))
2465 (setf (gethash path
*file-load-time-table
*)
2470 (defun (setf component-load-time
) (value component
)
2472 (type (or null string pathname component
) component
)
2473 (type (or unsigned-byte null
) value
))
2475 (etypecase component
2476 (string (setf (gethash component
*file-load-time-table
*) value
))
2477 (pathname (setf (gethash (namestring (the pathname component
))
2478 *file-load-time-table
*)
2481 (ecase (component-type component
)
2483 (let* ((name (component-name component
))
2484 (path (when name
(compute-system-path name nil
))))
2485 (declare (type (or string pathname null
) path
))
2487 (setf (gethash (namestring path
) *file-load-time-table
*)
2489 ((:file
:private-file
)
2490 ;; Use only :source pathname to identify file.
2491 (let ((path (component-full-pathname component
:source
)))
2493 (setf (gethash path
*file-load-time-table
*)
2498 ;;; compute-system-path --
2500 (defun compute-system-path (module-name definition-pname
)
2501 (let* ((module-string-name
2502 (etypecase module-name
2503 (symbol (string-downcase
2504 (string module-name
)))
2505 (string module-name
)))
2508 (make-pathname :name module-string-name
2509 :type
*system-extension
*))
2512 (make-pathname ;:directory (list :relative module-string-name)
2513 :name module-string-name
2514 :type
*system-extension
*))
2516 (or (when definition-pname
; given pathname for system def
2517 (probe-file definition-pname
))
2518 ;; Then the central registry. Note that we also check the current
2519 ;; directory in the registry, but the above check is hard-coded.
2520 (cond (*central-registry
*
2521 (if (listp *central-registry
*)
2522 (dolist (registry *central-registry
*)
2523 (let ((file (or (probe-file
2524 (append-directories (if (consp registry
)
2529 (append-directories (if (consp registry
)
2535 (when file
(return file
))))
2536 (or (probe-file (append-directories *central-registry
*
2538 (probe-file (append-directories *central-registry
*
2543 ;; No central registry. Assume current working directory.
2544 ;; Maybe this should be an error?
2545 (or (probe-file file-pathname
)
2546 (probe-file lib-file-pathname
)))))
2550 (defun system-definition-pathname (system-name)
2551 (let ((system (ignore-errors (find-system system-name
:error
))))
2553 (let ((system-def-pathname
2554 (make-pathname :type
"system"
2555 :defaults
(pathname (component-full-pathname system
:source
))))
2557 (values system-def-pathname
2558 (probe-file system-def-pathname
)))
2566 (defun compute-system-path (module-name definition-pname
)
2567 (let* ((filename (format nil
"~A.~A"
2568 (if (symbolp module-name
)
2569 (string-downcase (string module-name
))
2571 *system-extension
*)))
2572 (or (when definition-pname
; given pathname for system def
2573 (probe-file definition-pname
))
2574 ;; Then the central registry. Note that we also check the current
2575 ;; directory in the registry, but the above check is hard-coded.
2576 (cond (*central-registry
*
2577 (if (listp *central-registry
*)
2578 (dolist (registry *central-registry
*)
2579 (let ((file (probe-file
2580 (append-directories (if (consp registry
)
2584 (when file
(return file
))))
2585 (probe-file (append-directories *central-registry
*
2588 ;; No central registry. Assume current working directory.
2589 ;; Maybe this should be an error?
2590 (probe-file filename
))))))
2594 (defvar *reload-systems-from-disk
* t
2595 "If T, always tries to reload newer system definitions from disk.
2596 Otherwise first tries to find the system definition in the current
2599 (defun find-system (system-name &optional
(mode :ask
) definition-pname
)
2600 "Returns the system named SYSTEM-NAME.
2601 If not already loaded, loads it, depending on the value of
2602 *RELOAD-SYSTEMS-FROM-DISK* and of the value of MODE. MODE can be :ASK,
2603 :ERROR, :LOAD-OR-NIL, or :LOAD. :ASK is the default.
2604 This allows OPERATE-ON-SYSTEM to work on non-loaded as well as
2605 loaded system definitions. DEFINITION-PNAME is the pathname for
2606 the system definition, if provided."
2609 (or (get-system system-name
)
2610 (when (y-or-n-p-wait
2612 "System ~A not loaded. Shall I try loading it? "
2614 (find-system system-name
:load definition-pname
))))
2616 (or (get-system system-name
)
2617 (error 'missing-system
:name system-name
)))
2619 (let ((system (get-system system-name
)))
2620 (or (unless *reload-systems-from-disk
* system
)
2621 ;; If SYSTEM-NAME is a symbol, it will lowercase the
2623 ;; If SYSTEM-NAME is a string, it doesn't change the case of the
2624 ;; string. So if case matters in the filename, use strings, not
2625 ;; symbols, wherever the system is named.
2626 (when (foreign-system-p system
)
2627 (warn "Foreing system ~S cannot be reloaded by MK:DEFSYSTEM." system
)
2628 (return-from find-system nil
))
2629 (let ((path (compute-system-path system-name definition-pname
)))
2632 (null (component-load-time path
))
2633 (< (component-load-time path
)
2634 (file-write-date path
))))
2636 (format nil
"Loading system ~A from file ~A"
2640 (setf system
(get-system system-name
))
2642 (setf (component-load-time path
)
2643 (file-write-date path
))))
2647 (or (unless *reload-systems-from-disk
* (get-system system-name
))
2648 (when (foreign-system-p (get-system system-name
))
2649 (warn "Foreign system ~S cannot be reloaded by MK:DEFSYSTEM." system-name
)
2650 (return-from find-system nil
))
2651 (or (find-system system-name
:load-or-nil definition-pname
)
2652 (error "Can't find system named ~s." system-name
))))))
2655 (defun print-component (component stream depth
)
2656 (declare (ignore depth
))
2657 (format stream
"#<~:@(~A~): ~A>"
2658 (component-type component
)
2659 (component-name component
)))
2662 (defun describe-system (name &optional
(stream *standard-output
*))
2663 "Prints a description of the system to the stream. If NAME is the
2664 name of a system, gets it and prints a description of the system.
2665 If NAME is a component, prints a description of the component."
2666 (let ((system (if (typep name
'component
) name
(find-system name
:load
))))
2667 (format stream
"~&~A ~A: ~
2670 ~@[~& Package: ~A~]~
2671 ~& Source: ~@[~A~] ~@[~A~] ~@[~A~]~
2672 ~& Binary: ~@[~A~] ~@[~A~] ~@[~A~]~
2673 ~@[~& Depends On: ~A ~]~& Components:~{~15T~A~&~}"
2674 (component-type system
)
2675 (component-name system
)
2676 (component-host system
)
2677 (component-device system
)
2678 (component-package system
)
2679 (component-root-dir system
:source
)
2680 (component-pathname system
:source
)
2681 (component-extension system
:source
)
2682 (component-root-dir system
:binary
)
2683 (component-pathname system
:binary
)
2684 (component-extension system
:binary
)
2685 (component-depends-on system
)
2686 (component-components system
))
2688 (dolist (component (component-components system
))
2689 (describe-system component stream recursive
)))||
#
2692 (defun canonicalize-component-name (component)
2693 ;; Within the component, the name is a string.
2694 (if (typep (component-name component
) 'string
)
2695 ;; Unnecessary to change it, so just return it, same case
2696 (component-name component
)
2697 ;; Otherwise, make it a downcase string -- important since file
2698 ;; names are often constructed from component names, and unix
2699 ;; prefers lowercase as a default.
2700 (setf (component-name component
)
2701 (string-downcase (string (component-name component
))))))
2703 (defun component-pathname (component type
)
2706 (:source
(component-source-pathname component
))
2707 (:binary
(component-binary-pathname component
))
2708 (:error
(component-error-pathname component
)))))
2709 (defun component-error-pathname (component)
2710 (let ((binary (component-pathname component
:binary
)))
2711 (new-file-type binary
*compile-error-file-type
*)))
2712 (defsetf component-pathname
(component type
) (value)
2715 (:source
(setf (component-source-pathname ,component
) ,value
))
2716 (:binary
(setf (component-binary-pathname ,component
) ,value
)))))
2718 (defun component-root-dir (component type
)
2721 (:source
(component-source-root-dir component
))
2722 ((:binary
:error
) (component-binary-root-dir component
))
2724 (defsetf component-root-dir
(component type
) (value)
2727 (:source
(setf (component-source-root-dir ,component
) ,value
))
2728 (:binary
(setf (component-binary-root-dir ,component
) ,value
)))))
2730 (defvar *source-pathnames-table
* (make-hash-table :test
#'equal
)
2731 "Table which maps from components to full source pathnames.")
2732 (defvar *binary-pathnames-table
* (make-hash-table :test
#'equal
)
2733 "Table which maps from cosmponents to full binary pathnames.")
2734 (defparameter *reset-full-pathname-table
* t
2735 "If T, clears the full-pathname tables before each call to
2736 OPERATE-ON-SYSTEM. Setting this to NIL may yield faster performance
2737 after multiple calls to LOAD-SYSTEM and COMPILE-SYSTEM, but could
2738 result in changes to system and language definitions to not take
2739 effect, and so should be used with caution.")
2740 (defun clear-full-pathname-tables ()
2741 (clrhash *source-pathnames-table
*)
2742 (clrhash *binary-pathnames-table
*))
2744 (defun component-full-pathname (component type
&optional
(version *version
*))
2748 (let ((old (gethash component
*source-pathnames-table
*)))
2750 (let ((new (component-full-pathname-i component type version
)))
2751 (setf (gethash component
*source-pathnames-table
*) new
)
2754 (let ((old (gethash component
*binary-pathnames-table
*)))
2756 (let ((new (component-full-pathname-i component type version
)))
2757 (setf (gethash component
*binary-pathnames-table
*) new
)
2760 (component-full-pathname-i component type version
)))))
2762 (defun component-full-pathname-i (component type
2763 &optional
(version *version
*)
2764 &aux version-dir version-replace
)
2765 ;; If the pathname-type is :binary and the root pathname is null,
2766 ;; distribute the binaries among the sources (= use :source pathname).
2767 ;; This assumes that the component's :source pathname has been set
2768 ;; before the :binary one.
2770 (multiple-value-setq (version-dir version-replace
)
2771 (translate-version version
))
2772 (setq version-dir
*version-dir
* version-replace
*version-replace
*))
2773 ;; (format *trace-output* "~&>>>> VERSION COMPUTED ~S ~S~%" version-dir version-replace)
2778 (append-directories (component-root-dir component type
)
2780 (component-pathname component type
))))
2782 ;; When a logical pathname is used, it must first be translated to
2783 ;; a physical pathname. This isn't strictly correct. What should happen
2784 ;; is we fill in the appropriate slots of the logical pathname, and
2785 ;; then return the logical pathname for use by compile-file & friends.
2786 ;; But calling translate-logical-pathname to return the actual pathname
2787 ;; should do for now.
2789 ;; (format t "pathname = ~A~%" pathname)
2790 ;; (format t "type = ~S~%" (component-extension component type))
2792 ;; 20000303 Marco Antoniotti
2793 ;; Changed the following according to suggestion by Ray Toy. I
2794 ;; just collapsed the tests for "logical-pathname-ness" into a
2795 ;; single test (heavy, but probably very portable) and added the
2796 ;; :name argument to the MAKE-PATHNAME in the MERGE-PATHNAMES
2797 ;; beacuse of possible null names (e.g. :defsystem components)
2798 ;; causing problems with the subsequenct call to NAMESTRING.
2799 ;; (format *trace-output* "~&>>>> PATHNAME is ~S~%" pathname)
2801 ((pathname-logical-p pathname
) ; See definition of test above.
2803 (merge-pathnames pathname
2805 :name
(component-name component
)
2806 :type
(component-extension component
2808 ;;(format t "new path = ~A~%" pathname)
2809 (namestring (translate-logical-pathname pathname
)))
2813 (make-pathname :host
(when (component-host component
)
2814 ;; MCL2.0b1 and ACLPC cause an error on
2815 ;; (pathname-host nil)
2817 (component-host component
)
2819 (component-host (if (eq component
:unspecific
) "" component
))
2820 #-
(or :sbcl
:openmcl
)
2821 (pathname-host (component-host component
)))
2822 :directory
(pathname-directory pathname
)
2823 ;; Use :directory instead of :defaults
2824 :name
(pathname-name pathname
)
2825 :type
(component-extension component type
)
2830 (let ((dev (component-device component
)))
2832 (pathname-device dev
2833 #+scl
:case
#+scl
:common
2835 (pathname-device pathname
2836 #+scl
:case
#+scl
:common
2843 :name
(component-name component
)
2844 :type
(component-extension component type
)
2848 ;;; What about CMU17 :device :unspecific in the above?
2851 (defun translate-version (version)
2852 ;; Value returns the version directory and whether it replaces
2853 ;; the entire root (t) or is a subdirectory.
2854 ;; Version may be nil to signify no subdirectory,
2855 ;; a symbol, such as alpha, beta, omega, :alpha, mark, which
2856 ;; specifies a subdirectory of the root, or
2857 ;; a string, which replaces the root.
2858 (cond ((null version
)
2861 (values (let ((sversion (string version
)))
2862 (if (find-if #'lower-case-p sversion
)
2864 (string-downcase sversion
)))
2868 (t (error "~&; Illegal version ~S" version
))))
2871 ;;; Looks like LW has a bug in MERGE-PATHNAMES.
2873 ;;; (merge-pathnames "" "LP:foo;bar;") ==> "LP:"
2875 ;;; Which is incorrect.
2876 ;;; The change here ensures that the result of TRANSLATE-VERSION is
2880 (defun translate-version (version)
2881 ;; Value returns the version directory and whether it replaces
2882 ;; the entire root (t) or is a subdirectory.
2883 ;; Version may be nil to signify no subdirectory,
2884 ;; a symbol, such as alpha, beta, omega, :alpha, mark, which
2885 ;; specifies a subdirectory of the root, or
2886 ;; a string, which replaces the root.
2887 (cond ((null version
)
2888 (values (pathname "") nil
))
2890 (values (let ((sversion (string version
)))
2891 (if (find-if #'lower-case-p sversion
)
2893 (pathname (string-downcase sversion
))))
2896 (values (pathname version
) t
))
2897 (t (error "~&; Illegal version ~S" version
))))
2902 (defun component-extension (component type
&key local
)
2904 (:source
(or (component-source-extension component
)
2906 (default-source-extension component
)) ; system default
2907 ;; (and (component-language component))
2909 (:binary
(or (component-binary-extension component
)
2911 (default-binary-extension component
)) ; system default
2912 ;; (and (component-language component))
2914 (:error
*compile-error-file-type
*)))
2917 (defsetf component-extension
(component type
) (value)
2919 (:source
(setf (component-source-extension ,component
) ,value
))
2920 (:binary
(setf (component-binary-extension ,component
) ,value
))
2921 (:error
(setf *compile-error-file-type
* ,value
))))
2923 ;;; ********************************
2924 ;;; System Definition **************
2925 ;;; ********************************
2926 (defun create-component (type name definition-body
&optional parent
(indent 0))
2927 (let ((component (apply #'make-component
2932 ;; Set up :load-only attribute
2933 (unless (find :load-only definition-body
)
2934 ;; If the :load-only attribute wasn't specified,
2935 ;; inherit it from the parent. If no parent, default it to nil.
2936 (setf (component-load-only component
)
2938 (component-load-only parent
))))
2939 ;; Set up :compile-only attribute
2940 (unless (find :compile-only definition-body
)
2941 ;; If the :compile-only attribute wasn't specified,
2942 ;; inherit it from the parent. If no parent, default it to nil.
2943 (setf (component-compile-only component
)
2945 (component-compile-only parent
))))
2947 ;; Set up :compiler-options attribute
2948 (unless (find :compiler-options definition-body
)
2949 ;; If the :compiler-option attribute wasn't specified,
2950 ;; inherit it from the parent. If no parent, default it to NIL.
2951 (setf (component-compiler-options component
)
2953 (component-compiler-options parent
))))
2955 #|| ISI Extension ||
#
2956 ;; Set up :load-always attribute
2957 (unless (find :load-always definition-body
)
2958 ;; If the :load-always attribute wasn't specified,
2959 ;; inherit it from the parent. If no parent, default it to nil.
2960 (setf (component-load-always component
)
2962 (component-load-always parent
))))
2964 ;; Initializations/after makes
2965 (canonicalize-component-name component
)
2967 ;; Inherit package from parent if not specified.
2968 (setf (component-package component
)
2969 (or (component-package component
)
2970 (when parent
(component-package parent
))))
2972 ;; Type specific setup:
2973 (when (or (eq type
:defsystem
) (eq type
:system
) (eq type
:subsystem
))
2974 (setf (get-system name
) component
)
2975 #|
(unless (component-language component
)
2976 (setf (component-language component
) :lisp
))|
#)
2978 ;; Set up the component's pathname
2979 (create-component-pathnames component parent
)
2981 ;; If there are any components of the component, expand them too.
2982 (expand-component-components component
(+ indent
2))
2984 ;; Make depends-on refer to structs instead of names.
2985 (link-component-depends-on (component-components component
))
2987 ;; Design Decision: Topologically sort the dependency graph at
2988 ;; time of definition instead of at time of use. Probably saves a
2989 ;; little bit of time for the user.
2991 ;; Topological Sort the components at this level.
2992 (setf (component-components component
)
2993 (topological-sort (component-components component
)))
2995 ;; Return the component.
3002 ;;; 2002-11-22 Marco Antoniotti
3003 ;;; Added code to achieve a first cut "pathname less" operation,
3004 ;;; following the ideas in ASDF. If the DEFSYSTEM form is loaded from
3005 ;;; a file, then the location of the file (intended as a directory) is
3006 ;;; computed from *LOAD-PATHNAME* and stored as the :SOURCE-PATHNAME
3009 (defmacro defsystem
(name &rest definition-body
)
3010 (unless (find :source-pathname definition-body
)
3011 (setf definition-body
3012 (list* :source-pathname
3013 '(when #-gcl
*load-pathname
* #+gcl si
::*load-pathname
*
3014 (make-pathname :name nil
3016 :defaults
#-gcl
*load-pathname
*
3017 #+gcl si
::*load-pathname
*))
3019 `(create-component :defsystem
',name
',definition-body nil
0))
3021 (defun create-component-pathnames (component parent
)
3022 ;; Set up language-specific defaults
3024 (setf (component-language component
)
3025 (or (component-language component
) ; for local defaulting
3026 (when parent
; parent's default
3027 (component-language parent
))))
3029 (setf (component-compiler component
)
3030 (or (component-compiler component
) ; for local defaulting
3031 (when parent
; parent's default
3032 (component-compiler parent
))))
3033 (setf (component-loader component
)
3034 (or (component-loader component
) ; for local defaulting
3035 (when parent
; parent's default
3036 (component-loader parent
))))
3038 ;; Evaluate the root dir arg
3039 (setf (component-root-dir component
:source
)
3040 (eval (component-root-dir component
:source
)))
3041 (setf (component-root-dir component
:binary
)
3042 (eval (component-root-dir component
:binary
)))
3044 ;; Evaluate the pathname arg
3045 (setf (component-pathname component
:source
)
3046 (eval (component-pathname component
:source
)))
3047 (setf (component-pathname component
:binary
)
3048 (eval (component-pathname component
:binary
)))
3050 ;; Pass along the host and devices
3051 (setf (component-host component
)
3052 (or (component-host component
)
3053 (when parent
(component-host parent
))
3054 (pathname-host *default-pathname-defaults
*)))
3055 (setf (component-device component
)
3056 (or (component-device component
)
3057 (when parent
(component-device parent
))))
3059 ;; Set up extension defaults
3060 (setf (component-extension component
:source
)
3061 (or (component-extension component
:source
3062 :local
#|
(component-language component
) |
#
3065 (when (component-language component
)
3066 (default-source-extension component
))
3067 (when parent
; parent's default
3068 (component-extension parent
:source
))))
3069 (setf (component-extension component
:binary
)
3070 (or (component-extension component
:binary
3071 :local
#|
(component-language component
) |
#
3074 (when (component-language component
)
3075 (default-binary-extension component
))
3076 (when parent
; parent's default
3077 (component-extension parent
:binary
))))
3079 ;; Set up pathname defaults -- expand with parent
3080 ;; We must set up the source pathname before the binary pathname
3081 ;; to allow distribution of binaries among the sources to work.
3082 (generate-component-pathname component parent
:source
)
3083 (generate-component-pathname component parent
:binary
))
3086 ;; maybe file's inheriting of pathnames should be moved elsewhere?
3087 (defun generate-component-pathname (component parent pathname-type
)
3088 ;; Pieces together a pathname for the component based on its component-type.
3089 ;; Assumes source defined first.
3090 ;; Null binary pathnames inherit from source instead of the component's
3091 ;; name. This allows binaries to be distributed among the source if
3092 ;; binary pathnames are not specified. Or if the root directory is
3093 ;; specified for binaries, but no module directories, it inherits
3094 ;; parallel directory structure.
3095 (case (component-type component
)
3096 ((:defsystem
:system
) ; Absolute Pathname
3097 ;; Set the root-dir to be the absolute pathname
3098 (setf (component-root-dir component pathname-type
)
3099 (or (component-pathname component pathname-type
)
3100 (when (eq pathname-type
:binary
)
3101 ;; When the binary root is nil, use source.
3102 (component-root-dir component
:source
))) )
3103 ;; Set the relative pathname to be nil
3104 (setf (component-pathname component pathname-type
)
3105 nil
));; should this be "" instead?
3106 ;; If the name of the component-pathname is nil, it
3107 ;; defaults to the name of the component. Use "" to
3108 ;; avoid this defaulting.
3109 (:private-file
; Absolute Pathname
3110 ;; Root-dir is the directory part of the pathname
3111 (setf (component-root-dir component pathname-type
)
3113 #+ignore
(or (when (component-pathname component pathname-type
)
3115 (component-pathname component pathname-type
)))
3116 (when (eq pathname-type
:binary
)
3117 ;; When the binary root is nil, use source.
3118 (component-root-dir component
:source
)))
3120 ;; If *SOURCE-PATHNAME-DEFAULT* or *BINARY-PATHNAME-DEFAULT* is "",
3121 ;; then COMPONENT-SOURCE-PATHNAME or COMPONENT-BINARY-PATHNAME could
3122 ;; wind up being "", which is wrong for :file components. So replace
3124 (when (null-string (component-pathname component pathname-type
))
3125 (setf (component-pathname component pathname-type
) nil
))
3126 ;; The relative pathname is the name part
3127 (setf (component-pathname component pathname-type
)
3128 (or (when (and (eq pathname-type
:binary
)
3129 (null (component-pathname component
:binary
)))
3130 ;; When the binary-pathname is nil use source.
3131 (component-pathname component
:source
))
3132 (or (when (component-pathname component pathname-type
)
3134 (component-pathname component pathname-type
))
3135 (component-name component
)))))
3136 ((:module
:subsystem
) ; Pathname relative to parent.
3137 ;; Inherit root-dir from parent
3138 (setf (component-root-dir component pathname-type
)
3139 (component-root-dir parent pathname-type
))
3140 ;; Tack the relative-dir onto the pathname
3141 (setf (component-pathname component pathname-type
)
3142 (or (when (and (eq pathname-type
:binary
)
3143 (null (component-pathname component
:binary
)))
3144 ;; When the binary-pathname is nil use source.
3145 (component-pathname component
:source
))
3147 (component-pathname parent pathname-type
)
3148 (or (component-pathname component pathname-type
)
3149 (component-name component
))))))
3150 (:file
; Pathname relative to parent.
3151 ;; Inherit root-dir from parent
3152 (setf (component-root-dir component pathname-type
)
3153 (component-root-dir parent pathname-type
))
3154 ;; If *SOURCE-PATHNAME-DEFAULT* or *BINARY-PATHNAME-DEFAULT* is "",
3155 ;; then COMPONENT-SOURCE-PATHNAME or COMPONENT-BINARY-PATHNAME could
3156 ;; wind up being "", which is wrong for :file components. So replace
3158 (when (null-string (component-pathname component pathname-type
))
3159 (setf (component-pathname component pathname-type
) nil
))
3160 ;; Tack the relative-dir onto the pathname
3161 (setf (component-pathname component pathname-type
)
3162 (or (append-directories
3163 (component-pathname parent pathname-type
)
3164 (or (component-pathname component pathname-type
)
3165 (component-name component
)
3166 (when (eq pathname-type
:binary
)
3167 ;; When the binary-pathname is nil use source.
3168 (component-pathname component
:source
)))))))
3172 (defun expand-component-components (component &optional
(indent 0))
3173 (let ((definitions (component-components component
)))
3174 (setf (component-components component
)
3176 (mapcar #'(lambda (definition)
3177 (expand-component-definition definition
3183 (defun expand-component-components (component &optional
(indent 0))
3184 (let ((definitions (component-components component
)))
3185 (if (eq (car definitions
) :serial
)
3186 (setf (component-components component
)
3187 (expand-serial-component-chain (cdr definitions
)
3189 (setf (component-components component
)
3190 (expand-component-definitions definitions component indent
)))))
3192 (defun expand-component-definitions (definitions parent
&optional
(indent 0))
3193 (let ((components nil
))
3194 (dolist (definition definitions
)
3195 (let ((new (expand-component-definition definition parent indent
)))
3196 (when new
(push new components
))))
3197 (nreverse components
)))
3199 (defun expand-serial-component-chain (definitions parent
&optional
(indent 0))
3200 (let ((previous nil
)
3202 (dolist (definition definitions
)
3203 (let ((new (expand-component-definition definition parent indent
)))
3205 ;; Make this component depend on the previous one. Since
3206 ;; we don't know the form of the definition, we have to
3208 (when previous
(pushnew previous
(component-depends-on new
)))
3209 ;; The dependencies will be linked later, so we use the name
3210 ;; instead of the actual component.
3211 (setq previous
(component-name new
))
3212 ;; Save the new component.
3213 (push new components
))))
3214 ;; Return the list of expanded components, in appropriate order.
3215 (nreverse components
)))
3218 (defparameter *enable-straz-absolute-string-hack
* nil
3219 "Special hack requested by Steve Strassman, where the shorthand
3220 that specifies a list of components as a list of strings also
3221 recognizes absolute pathnames and treats them as files of type
3222 :private-file instead of type :file. Defaults to NIL, because I
3223 haven't tested this.")
3224 (defun absolute-file-namestring-p (string)
3225 ;; If a FILE namestring starts with a slash, or is a logical pathname
3226 ;; as implied by the existence of a colon in the filename, assume it
3227 ;; represents an absolute pathname.
3228 (or (find #\
: string
:test
#'char
=)
3229 (and (not (null-string string
))
3230 (char= (char string
0) #\
/))))
3232 (defun expand-component-definition (definition parent
&optional
(indent 0))
3233 ;; Should do some checking for malformed definitions here.
3234 (cond ((null definition
) nil
)
3235 ((stringp definition
)
3236 ;; Strings are assumed to be of type :file
3237 (if (and *enable-straz-absolute-string-hack
*
3238 (absolute-file-namestring-p definition
))
3239 ;; Special hack for Straz
3240 (create-component :private-file definition nil parent indent
)
3242 (create-component :file definition nil parent indent
)))
3243 ((and (listp definition
)
3244 (not (member (car definition
)
3245 '(:defsystem
:system
:subsystem
3246 :module
:file
:private-file
))))
3247 ;; Lists whose first element is not a component type
3248 ;; are assumed to be of type :file
3249 (create-component :file
3255 ;; Otherwise, it is (we hope) a normal form definition
3256 (create-component (car definition
) ; type
3257 (cadr definition
) ; name
3258 (cddr definition
) ; definition body
3263 (defun link-component-depends-on (components)
3264 (dolist (component components
)
3265 (unless (and *system-dependencies-delayed
*
3266 (eq (component-type component
) :defsystem
))
3267 (setf (component-depends-on component
)
3268 (mapcar #'(lambda (dependency)
3269 (let ((parent (find (string dependency
) components
3270 :key
#'component-name
3271 :test
#'string-equal
)))
3272 (cond (parent parent
)
3273 ;; make it more intelligent about the following
3274 (t (warn "Dependency ~S of component ~S not found."
3275 dependency component
)))))
3277 (component-depends-on component
))))))
3279 ;;; ********************************
3280 ;;; Topological Sort the Graph *****
3281 ;;; ********************************
3283 ;;; New version of topological sort suggested by rs2. Even though
3284 ;;; this version avoids the call to sort, in practice it isn't faster. It
3285 ;;; does, however, eliminate the need to have a TIME slot in the
3286 ;;; topological-sort-node defstruct.
3287 (defun topological-sort (list &aux
(sorted-list nil
))
3288 (labels ((dfs-visit (znode)
3289 (setf (topsort-color znode
) :gray
)
3290 (unless (and *system-dependencies-delayed
*
3291 (eq (component-type znode
) :system
))
3292 (dolist (child (component-depends-on znode
))
3293 (cond ((eq (topsort-color child
) :white
)
3295 ((eq (topsort-color child
) :gray
)
3296 (format t
"~&Detected cycle containing ~A" child
)))))
3297 (setf (topsort-color znode
) :black
)
3298 (push znode sorted-list
)))
3299 (dolist (znode list
)
3300 (setf (topsort-color znode
) :white
))
3301 (dolist (znode list
)
3302 (when (eq (topsort-color znode
) :white
)
3304 (nreverse sorted-list
)))
3307 ;;; Older version of topological sort.
3308 (defun topological-sort (list &aux
(time 0))
3309 ;; The algorithm works by calling depth-first-search to compute the
3310 ;; blackening times for each vertex, and then sorts the vertices into
3311 ;; reverse order by blackening time.
3312 (labels ((dfs-visit (node)
3313 (setf (topsort-color node
) 'gray
)
3314 (unless (and *system-dependencies-delayed
*
3315 (eq (component-type node
) :defsystem
))
3316 (dolist (child (component-depends-on node
))
3317 (cond ((eq (topsort-color child
) 'white
)
3319 ((eq (topsort-color child
) 'gray
)
3320 (format t
"~&Detected cycle containing ~A" child
)))))
3321 (setf (topsort-color node
) 'black
)
3322 (setf (topsort-time node
) time
)
3325 (setf (topsort-color node
) 'white
))
3327 (when (eq (topsort-color node
) 'white
)
3329 (sort list
#'< :key
#'topsort-time
)))
3332 ;;; ********************************
3333 ;;; Output to User *****************
3334 ;;; ********************************
3335 ;;; All output to the user is via the tell-user functions.
3337 (defun split-string (string &key
(item #\space
) (test #'char
=))
3338 ;; Splits the string into substrings at spaces.
3339 (let ((len (length string
))
3342 (progn (unless (= index len
)
3343 (push (subseq string index
) result
))
3345 (when (funcall test
(char string i
) item
)
3346 (unless (= index i
);; two spaces in a row
3347 (push (subseq string index i
) result
))
3348 (setf index
(1+ i
))))))
3350 ;; probably should remove the ",1" entirely. But AKCL 1.243 dies on it
3351 ;; because of an AKCL bug.
3352 ;; KGK suggests using an 8 instead, but 1 does nicely.
3353 (defun prompt-string (component)
3354 (format nil
"; ~:[~;TEST:~]~V,1@T "
3356 (component-indent component
)))
3359 (defun format-justified-string (prompt contents
)
3360 (format t
(concatenate 'string
3363 "-~{~<~%" prompt
" ~1,80:; ~A~>~^~}")
3364 (split-string contents
))
3365 (finish-output *standard-output
*))
3368 (defun format-justified-string (prompt contents
&optional
(width 80)
3369 (stream *standard-output
*))
3370 (let ((prompt-length (+ 2 (length prompt
))))
3371 (cond ((< (+ prompt-length
(length contents
)) width
)
3372 (format stream
"~%~A- ~A" prompt contents
))
3374 (format stream
"~%~A-" prompt
)
3375 (do* ((cursor prompt-length
)
3376 (contents (split-string contents
) (cdr contents
))
3377 (content (car contents
) (car contents
))
3378 (content-length (1+ (length content
)) (1+ (length content
))))
3380 (cond ((< (+ cursor content-length
) width
)
3381 (incf cursor content-length
)
3382 (format stream
" ~A" content
))
3384 (setf cursor
(+ prompt-length content-length
))
3385 (format stream
"~%~A ~A" prompt content
)))))))
3386 (finish-output stream
))
3388 (defun tell-user (what component
&optional type no-dots force
)
3389 (when (or *oos-verbose
* force
)
3390 (format-justified-string (prompt-string component
)
3391 (format nil
"~A ~(~A~) ~@[\"~A\"~] ~:[~;...~]"
3392 ;; To have better messages, wrap the following around the
3394 ;;(if (find (component-type component)
3395 ;; '(:defsystem :system :subsystem :module))
3398 ;; This gets around the problem of DEFSYSTEM reporting
3399 ;; that it's loading a module, when it eventually never
3400 ;; loads any of the files of the module.
3403 (if (component-load-only component
)
3404 ;; If it is :load-only t, we're loading.
3406 ;; Otherwise we're compiling.
3408 ((load :load
) "Loading")
3410 (component-type component
)
3412 (component-full-pathname component type
))
3413 (component-name component
))
3414 (and *tell-user-when-done
*
3417 (defun tell-user-done (component &optional force no-dots
)
3418 ;; test is no longer really used, but we're leaving it in.
3419 (when (and *tell-user-when-done
*
3420 (or *oos-verbose
* force
))
3421 (format t
"~&~A~:[~;...~] Done."
3422 (prompt-string component
) (not no-dots
))
3423 (finish-output *standard-output
*)))
3425 (defmacro with-tell-user
((what component
&optional type no-dots force
) &body body
)
3427 (tell-user ,what
,component
,type
,no-dots
,force
)
3429 (tell-user-done ,component
,force
,no-dots
)))
3431 (defun tell-user-no-files (component &optional force
)
3432 (when (or *oos-verbose
* force
)
3433 (format-justified-string (prompt-string component
)
3434 (format nil
"Source file ~A ~
3435 ~:[and binary file ~A ~;~]not found, not loading."
3436 (component-full-pathname component
:source
)
3437 (or *load-source-if-no-binary
* *load-source-instead-of-binary
*)
3438 (component-full-pathname component
:binary
)))))
3440 (defun tell-user-require-system (name parent
)
3442 (format t
"~&; ~:[~;TEST:~] - System ~A requires ~S"
3443 *oos-test
* (component-name parent
) name
)
3444 (finish-output *standard-output
*)))
3446 (defun tell-user-generic (string)
3448 (format t
"~&; ~:[~;TEST:~] - ~A"
3450 (finish-output *standard-output
*)))
3452 ;;; ********************************
3453 ;;; Y-OR-N-P-WAIT ******************
3454 ;;; ********************************
3455 ;;; Y-OR-N-P-WAIT is like Y-OR-N-P, but will timeout after a specified
3456 ;;; number of seconds. I should really replace this with a call to
3457 ;;; the Y-OR-N-P-WAIT defined in the query.cl package and include that
3460 (defparameter *use-timeouts
* t
3461 "If T, timeouts in Y-OR-N-P-WAIT are enabled. Otherwise it behaves
3462 like Y-OR-N-P. This is provided for users whose lisps don't handle
3463 read-char-no-hang properly.")
3465 (defparameter *clear-input-before-query
* t
3466 "If T, y-or-n-p-wait will clear the input before printing the prompt
3467 and asking the user for input.")
3469 ;;; The higher *sleep-amount* is, the less consing, but the lower the
3471 (defparameter *sleep-amount
* #-CMU
0.1 #+CMU
1.0
3472 "Amount of time to sleep between checking query-io. In multiprocessing
3473 Lisps, this allows other processes to continue while we busy-wait. If
3474 0, skips call to SLEEP.")
3476 (defun internal-real-time-in-seconds ()
3477 (get-universal-time))
3479 (defun read-char-wait (&optional
(timeout 20) input-stream
3480 (eof-error-p t
) eof-value
3482 (do ((start (internal-real-time-in-seconds)))
3483 ((or (setq peek
(listen input-stream
))
3484 (< (+ start timeout
) (internal-real-time-in-seconds)))
3486 ;; was read-char-no-hang
3487 (read-char input-stream eof-error-p eof-value
)))
3488 (unless (zerop *sleep-amount
*)
3489 (sleep *sleep-amount
*))))
3491 ;;; Lots of lisps, especially those that run on top of UNIX, do not get
3492 ;;; their input one character at a time, but a whole line at a time because
3493 ;;; of the buffering done by the UNIX system. This causes y-or-n-p-wait
3494 ;;; to not always work as expected.
3496 ;;; I wish lisp did all its own buffering (turning off UNIX input line
3497 ;;; buffering by putting the UNIX into CBREAK mode). Of course, this means
3498 ;;; that we lose input editing, but why can't the lisp implement this?
3500 (defun y-or-n-p-wait (&optional
(default #\y
) (timeout 20)
3501 format-string
&rest args
)
3502 "Y-OR-N-P-WAIT prints the message, if any, and reads characters from
3503 *QUERY-IO* until the user enters y, Y or space as an affirmative, or either
3504 n or N as a negative answer, or the timeout occurs. It asks again if
3505 you enter any other characters."
3506 (when *clear-input-before-query
* (clear-input *query-io
*))
3508 (fresh-line *query-io
*)
3509 (apply #'format
*query-io
* format-string args
)
3510 ;; FINISH-OUTPUT needed for CMU and other places which don't handle
3511 ;; output streams nicely. This prevents it from continuing and
3512 ;; reading the query until the prompt has been printed.
3513 (finish-output *query-io
*))
3515 (let* ((read-char (if *use-timeouts
*
3516 (read-char-wait timeout
*query-io
* nil nil
)
3517 (read-char *query-io
*)))
3518 (char (or read-char default
)))
3519 ;; We need to ignore #\newline because otherwise the bugs in
3520 ;; clear-input will cause y-or-n-p-wait to print the "Type ..."
3521 ;; message every time... *sigh*
3522 ;; Anyway, we might want to use this to ignore whitespace once
3523 ;; clear-input is fixed.
3524 (unless (find char
'(#\tab
#\newline
#\return
))
3525 (when (null read-char
)
3526 (format *query-io
* "~@[~A~]" default
)
3527 (finish-output *query-io
*))
3528 (cond ((null char
) (return t
))
3529 ((find char
'(#\y
#\Y
#\space
) :test
#'char
=) (return t
))
3530 ((find char
'(#\n #\N
) :test
#'char
=) (return nil
))
3532 (when *clear-input-before-query
* (clear-input *query-io
*))
3533 (format *query-io
* "~&Type \"y\" for yes or \"n\" for no. ")
3535 (fresh-line *query-io
*)
3536 (apply #'format
*query-io
* format-string args
))
3537 (finish-output *query-io
*)))))))
3540 (y-or-n-p-wait #\y
20 "What? ")
3541 (progn (format t
"~&hi") (finish-output)
3542 (y-or-n-p-wait #\y
10 "1? ")
3543 (y-or-n-p-wait #\n 10 "2? "))
3545 ;;; ********************************
3546 ;;; Operate on System **************
3547 ;;; ********************************
3548 ;;; Operate-on-system
3549 ;;; Operation is :compile, 'compile, :load or 'load
3550 ;;; Force is :all or :new-source or :new-source-and-dependents or a list of
3551 ;;; specific modules.
3552 ;;; :all (or T) forces a recompilation of every file in the system
3553 ;;; :new-source-and-dependents compiles only those files whose
3554 ;;; sources have changed or who depend on recompiled files.
3555 ;;; :new-source compiles only those files whose sources have changed
3556 ;;; A list of modules means that only those modules and their
3557 ;;; dependents are recompiled.
3558 ;;; Test is T to print out what it would do without actually doing it.
3559 ;;; Note: it automatically sets verbose to T if test is T.
3560 ;;; Verbose is T to print out what it is doing (compiling, loading of
3561 ;;; modules and files) as it does it.
3562 ;;; Dribble should be the pathname of the dribble file if you want to
3563 ;;; dribble the compilation.
3564 ;;; Load-source-instead-of-binary is T to load .lisp instead of binary files.
3565 ;;; Version may be nil to signify no subdirectory,
3566 ;;; a symbol, such as alpha, beta, omega, :alpha, mark, which
3567 ;;; specifies a subdirectory of the root, or
3568 ;;; a string, which replaces the root.
3570 (defun operate-on-system (name operation
3574 (test *oos-test
*) (verbose *oos-verbose
*)
3575 (load-source-instead-of-binary
3576 *load-source-instead-of-binary
*)
3577 (load-source-if-no-binary
3578 *load-source-if-no-binary
*)
3579 (bother-user-if-no-binary
3580 *bother-user-if-no-binary
*)
3581 (compile-during-load *compile-during-load
*)
3583 (minimal-load *minimal-load
*)
3584 (override-compilation-unit t
)
3586 (declare #-
(or :cltl2
:ansi-cl
) (ignore override-compilation-unit
))
3588 ;; Protect the undribble.
3589 (#+(and (or :cltl2
:ansi-cl
) (not :gcl
)) with-compilation-unit
3590 #+(and (or :cltl2
:ansi-cl
) (not :gcl
)) (:override override-compilation-unit
)
3591 #-
(and (or :cltl2
:ansi-cl
) (not :gcl
)) progn
3592 (when *reset-full-pathname-table
* (clear-full-pathname-tables))
3593 (when dribble
(dribble dribble
))
3594 (when test
(setq verbose t
))
3595 (when (null force
) ; defaults
3597 ((load :load
) (setq force
:all
))
3598 ((compile :compile
) (setq force
:new-source-and-dependents
))
3599 (t (setq force
:all
))))
3600 ;; Some CL implementations have a variable called *compile-verbose*
3601 ;; or *compile-file-verbose*.
3602 (multiple-value-bind (*version-dir
* *version-replace
*)
3603 (translate-version version
)
3604 ;; CL implementations may uniformly default this to nil
3606 #-
(or MCL CMU CLISP ECL
:sbcl lispworks scl
)
3607 (*compile-file-verbose
* t
) ; nil
3608 #+common-lisp-controller
3609 (*compile-print
* nil
)
3610 #+(and common-lisp-controller cmu
)
3611 (ext:*compile-progress
* nil
)
3612 #+(and common-lisp-controller cmu
)
3613 (ext:*require-verbose
* nil
)
3614 #+(and common-lisp-controller cmu
)
3615 (ext:*gc-verbose
* nil
)
3618 (*oos-verbose
* verbose
)
3620 (*load-source-if-no-binary
* load-source-if-no-binary
)
3621 (*compile-during-load
* compile-during-load
)
3622 (*bother-user-if-no-binary
* bother-user-if-no-binary
)
3623 (*load-source-instead-of-binary
* load-source-instead-of-binary
)
3624 (*minimal-load
* minimal-load
)
3625 (system (if (and (component-p name
)
3626 (member (component-type name
)
3627 '(:system
:defsystem
:subsystem
)))
3629 (find-system name
:load
))))
3630 #-
(or CMU CLISP
:sbcl
:lispworks
:cormanlisp scl
)
3631 (declare (special *compile-verbose
* #-MCL
*compile-file-verbose
*)
3632 #-openmcl
(ignore *compile-verbose
*
3633 #-MCL
*compile-file-verbose
*)
3634 #-openmcl
(optimize (inhibit-warnings 3)))
3635 (unless (component-operation operation
)
3636 (error "Operation ~A undefined." operation
))
3637 (operate-on-component system operation force
))))
3638 (when dribble
(dribble))))
3641 (defun compile-system (name &key force
3643 (test *oos-test
*) (verbose *oos-verbose
*)
3644 (load-source-instead-of-binary
3645 *load-source-instead-of-binary
*)
3646 (load-source-if-no-binary
3647 *load-source-if-no-binary
*)
3648 (bother-user-if-no-binary
3649 *bother-user-if-no-binary
*)
3650 (compile-during-load *compile-during-load
*)
3652 (minimal-load *minimal-load
*))
3653 ;; For users who are confused by OOS.
3660 :load-source-instead-of-binary load-source-instead-of-binary
3661 :load-source-if-no-binary load-source-if-no-binary
3662 :bother-user-if-no-binary bother-user-if-no-binary
3663 :compile-during-load compile-during-load
3665 :minimal-load minimal-load
))
3667 (defun load-system (name &key force
3669 (test *oos-test
*) (verbose *oos-verbose
*)
3670 (load-source-instead-of-binary
3671 *load-source-instead-of-binary
*)
3672 (load-source-if-no-binary *load-source-if-no-binary
*)
3673 (bother-user-if-no-binary *bother-user-if-no-binary
*)
3674 (compile-during-load *compile-during-load
*)
3676 (minimal-load *minimal-load
*))
3677 ;; For users who are confused by OOS.
3684 :load-source-instead-of-binary load-source-instead-of-binary
3685 :load-source-if-no-binary load-source-if-no-binary
3686 :bother-user-if-no-binary bother-user-if-no-binary
3687 :compile-during-load compile-during-load
3689 :minimal-load minimal-load
))
3691 (defun clean-system (name &key
(force :all
)
3693 (test *oos-test
*) (verbose *oos-verbose
*)
3695 "Deletes all the binaries in the system."
3696 ;; For users who are confused by OOS.
3698 name
:delete-binaries
3709 (verbose *oos-verbose
*)
3720 (defun hardcopy-system
3724 (verbose *oos-verbose
*)
3736 ;;; ensure-external-system-def-loaded component --
3737 ;;; Let's treat definition clauses of the form
3739 ;;; (:system "name")
3742 ;;; (:system "name" :components nil)
3744 ;;; in a special way.
3745 ;;; When encountered, MK:DEFSYSTEM tries to FIND-SYSTEM
3746 ;;; the system named "name" (by forcing a reload from disk).
3747 ;;; This may be more "natural".
3749 (defun ensure-external-system-def-loaded (component)
3750 (assert (member (component-type component
)
3751 '(:subsystem
:system
)))
3752 (when (null (component-components component
))
3753 (let ((cname (component-name component
)))
3754 ;; First we ensure that we reload the system definition.
3756 (let* ((*reload-systems-from-disk
* t
)
3758 (find-system (component-name component
)
3761 ;; Let's not supply the def-pname
3765 (make-pathname :name cname
3768 (component-full-pathname component
3774 ;; Now we have a problem.
3775 ;; We have just ensured that a system definition is
3776 ;; loaded, however, the COMPONENT at hand is different
3777 ;; from SYSTEM-COMPONENT.
3778 ;; To fix this problem we just use the following
3779 ;; kludge. This should prevent re-entering in this
3780 ;; code branch, while actually preparing the COMPONENT
3782 (setf (component-components component
)
3783 (list system-component
))
3787 (defun operate-on-component (component operation force
&aux changed
)
3788 ;; Returns T if something changed and had to be compiled.
3789 (let ((type (component-type component
))
3790 (old-package (package-name *package
*)))
3793 ;; Protect old-package.
3795 ;; Use the correct package.
3796 (when (component-package component
)
3797 (tell-user-generic (format nil
"Using package ~A"
3798 (component-package component
)))
3800 (unless (find-package (component-package component
))
3801 ;; If the package name is the same as the name of the system,
3802 ;; and the package is not defined, this would lead to an
3803 ;; infinite loop, so bomb out with an error.
3804 (when (string-equal (string (component-package component
))
3805 (component-name component
))
3806 (format t
"~%Component ~A not loaded:~%"
3807 (component-name component
))
3808 (error " Package ~A is not defined"
3809 (component-package component
)))
3810 ;; If package not found, try using REQUIRE to load it.
3811 (new-require (component-package component
)))
3812 ;; This was USE-PACKAGE, but should be IN-PACKAGE.
3813 ;; Actually, CLtL2 lisps define in-package as a macro,
3814 ;; so we'll set the package manually.
3815 ;; (in-package (component-package component))
3816 (let ((package (find-package (component-package component
))))
3818 (setf *package
* package
)))))
3820 ;; Marco Antoniotti 20040609
3821 ;; New feature. Try to FIND-SYSTEM :system components if
3822 ;; they have no local :components definition.
3823 ;; OPERATE-ON-SYSTEM-DEPENDENCIES should still work as
3824 ;; advertised, given the small change made there.
3826 (when (or (eq type
:system
) (eq type
:subsystem
))
3827 (ensure-external-system-def-loaded component
))
3829 (when (or (eq type
:defsystem
) (eq type
:system
))
3830 (operate-on-system-dependencies component operation force
))
3832 ;; Do any compiler proclamations
3833 (when (component-proclamations component
)
3834 (tell-user-generic (format nil
"Doing proclamations for ~A"
3835 (component-name component
)))
3837 (proclaim (component-proclamations component
))))
3839 ;; Do any initial actions
3840 (when (component-initially-do component
)
3841 (tell-user-generic (format nil
"Doing initializations for ~A"
3842 (component-name component
)))
3844 (eval (component-initially-do component
))))
3846 ;; If operation is :compile and load-only is T, this would change
3847 ;; the operation to load. Only, this would mean that a module would
3848 ;; be considered to have changed if it was :load-only and had to be
3849 ;; loaded, and then dependents would be recompiled -- this doesn't
3850 ;; seem right. So instead, we propagate the :load-only attribute
3851 ;; to the components, and modify compile-file-operation so that
3852 ;; it won't compile the files (and modify tell-user to say "Loading"
3853 ;; instead of "Compiling" for load-only modules).
3855 (when (and (find operation
'(:compile compile
))
3856 (component-load-only component
))
3857 (setf operation
:load
))
3860 ;; Do operation and set changed flag if necessary.
3863 ((:file
:private-file
)
3864 (funcall (component-operation operation
) component force
))
3865 ((:module
:system
:subsystem
:defsystem
)
3866 (operate-on-components component operation force changed
))))
3868 ;; Do any final actions
3869 (when (component-finally-do component
)
3870 (tell-user-generic (format nil
"Doing finalizations for ~A"
3871 (component-name component
)))
3873 (eval (component-finally-do component
))))
3875 ;; add the banner if needed
3877 (when (component-banner component
)
3878 (unless (stringp (component-banner component
))
3879 (error "The banner should be a string, it is: ~S"
3880 (component-banner component
)))
3881 (setf (getf ext
:*herald-items
*
3882 (intern (string-upcase (component-name component
))
3883 (find-package :keyword
)))
3885 (component-banner component
)))))
3887 ;; Reset the package. (Cleanup form of unwind-protect.)
3888 ;;(in-package old-package)
3889 (setf *package
* (find-package old-package
)))
3891 ;; Provide the loaded system
3892 (when (or (eq type
:defsystem
) (eq type
:system
) (eq type
:subsystem
))
3893 (tell-user-generic (format nil
"Providing system ~A~%"
3894 (component-name component
)))
3896 (provide (canonicalize-system-name (component-name component
))))))
3898 ;; Return non-NIL if something changed in this component and hence had
3899 ;; to be recompiled. This is only used as a boolean.
3902 (defvar *force
* nil
)
3903 (defvar *providing-blocks-load-propagation
* t
3904 "If T, if a system dependency exists on *modules*, it is not loaded.")
3906 (defun operate-on-system-dependencies (component operation
&optional force
)
3907 (when *system-dependencies-delayed
*
3908 (let ((*force
* force
))
3909 (dolist (system (component-depends-on component
))
3910 ;; For each system that this system depends on, if it is a
3911 ;; defined system (either via defsystem or component type :system),
3912 ;; and propagation is turned on, propagates the operation to the
3913 ;; subsystem. Otherwise runs require (my version) on that system
3914 ;; to load it (needed since we may be depending on a lisp
3915 ;; dependent package).
3916 ;; Explores the system tree in a DFS manner.
3918 ;; Do not try to do anything with non system components.
3919 (cond ((and *operations-propagate-to-subsystems
*
3920 (not (listp system
))
3921 (or (stringp system
) (symbolp system
))
3922 ;; The subsystem is a defined system.
3923 (find-system system
:load-or-nil
))
3924 ;; Call OOS on it. Since *system-dependencies-delayed* is
3925 ;; T, the :depends-on slot is filled with the names of
3926 ;; systems, not defstructs.
3927 ;; Aside from system, operation, force, for everything else
3928 ;; we rely on the globals.
3929 (unless (and *providing-blocks-load-propagation
*
3930 ;; If *providing-blocks-load-propagation* is T,
3931 ;; the system dependency must not exist in the
3932 ;; *modules* for it to be loaded. Note that
3933 ;; the dependencies are implicitly systems.
3934 (find operation
'(load :load
))
3935 ;; (or (eq force :all) (eq force t))
3936 (find (canonicalize-system-name system
)
3937 *modules
* :test
#'string-equal
))
3939 (operate-on-system system operation
:force force
)))
3942 ;; If the SYSTEM is a list then its contents are as follows.
3944 ;; (<name> <definition-pathname> <action> &optional <version>)
3947 (destructuring-bind (system-name definition-pathname action
3950 (tell-user-require-system
3951 (if (and (null system-name
)
3952 (null definition-pathname
))
3956 (or *oos-test
* (new-require system-name
3958 (eval definition-pathname
)
3960 (or version
*version
*)))))
3961 ((and (component-p system
)
3962 (not (member (component-type system
)
3963 '(:defsystem
:subsystem
:system
))))
3964 ;; Do nothing for non system components.
3967 (tell-user-require-system system component
)
3968 (or *oos-test
* (new-require system
))))
3971 ;;; Modules can depend only on siblings. If a module should depend
3972 ;;; on an uncle, then the parent module should depend on that uncle
3973 ;;; instead. Likewise a module should depend on a sibling, not a niece
3974 ;;; or nephew. Modules also cannot depend on cousins. Modules cannot
3975 ;;; depend on parents, since that is circular.
3977 (defun module-depends-on-changed (module changed
)
3978 (dolist (dependent (component-depends-on module
))
3979 (when (member dependent changed
)
3982 (defun operate-on-components (component operation force changed
)
3983 (with-tell-user (operation component
)
3984 (if (component-components component
)
3985 (dolist (module (component-components component
))
3986 (when (operate-on-component module operation
3987 (cond ((and (module-depends-on-changed module changed
)
3988 #||
(some #'(lambda (dependent)
3989 (member dependent changed
))
3990 (component-depends-on module
))||
#
3991 (or (non-empty-listp force
)
3992 (eq force
:new-source-and-dependents
)))
3993 ;; The component depends on a changed file
3994 ;; and force agrees.
3995 (if (eq force
:new-source-and-dependents
)
3998 ((and (non-empty-listp force
)
3999 (member (component-name module
) force
4000 :test
#'string-equal
:key
#'string
))
4001 ;; Force is a list of modules
4002 ;; and the component is one of them.
4005 (push module changed
)))
4008 (eval (component-compile-form component
)))
4010 (eval (component-load-form component
))))))
4011 ;; This is only used as a boolean.
4014 ;;; ********************************
4015 ;;; New Require ********************
4016 ;;; ********************************
4018 ;;; This needs cleaning. Obviously the code is a left over from the
4019 ;;; time people did not know how to use packages in a proper way or
4020 ;;; CLs were shaky in their implementation.
4022 ;;; First of all we need this. (Commented out for the time being)
4023 ;;; (shadow '(cl:require))
4026 (defvar *old-require
* nil
)
4028 ;;; All calls to require in this file have been replaced with calls
4029 ;;; to new-require to avoid compiler warnings and make this less of
4032 (defun new-require (module-name
4037 (version *version
*))
4038 ;; If the pathname is present, this behaves like the old require.
4039 (unless (and module-name
4040 (find (string module-name
)
4041 *modules
* :test
#'string
=))
4044 (funcall *old-require
* module-name pathname
))
4045 ;; If the system is defined, load it.
4046 ((find-system module-name
:load-or-nil definition-pname
)
4052 :verbose
*oos-verbose
*
4053 :load-source-if-no-binary
*load-source-if-no-binary
*
4054 :bother-user-if-no-binary
*bother-user-if-no-binary
*
4055 :compile-during-load
*compile-during-load
*
4056 :load-source-instead-of-binary
*load-source-instead-of-binary
*
4057 :minimal-load
*minimal-load
*))
4058 ;; If there's a default action, do it. This could be a progn which
4059 ;; loads a file that does everything.
4060 ((and default-action
4061 (eval default-action
)))
4062 ;; If no system definition file, try regular require.
4063 ;; had last arg PATHNAME, but this wasn't really necessary.
4064 ((funcall *old-require
* module-name
))
4065 ;; If no default action, print a warning or error message.
4068 (format t
"~&Warning: System ~A doesn't seem to be defined..."
4071 (error 'missing-system
:name module-name
)))
4072 (missing-module (mmc) (signal mmc
)) ; Resignal.
4074 (declare (ignore e
))
4075 ;; Signal a (maybe wrong) MISSING-SYSTEM.
4076 (error 'missing-system
:name module-name
)))
4080 ;;; Note that in some lisps, when the compiler sees a REQUIRE form at
4081 ;;; top level it immediately executes it. This is as if an
4082 ;;; (eval-when (compile load eval) ...) were wrapped around the REQUIRE
4083 ;;; form. I don't see any easy way to do this without making REQUIRE
4086 ;;; For example, in VAXLisp, if a (require 'streams) form is at the top of
4087 ;;; a file in the system, compiling the system doesn't wind up loading the
4088 ;;; streams module. If the (require 'streams) form is included within an
4089 ;;; (eval-when (compile load eval) ...) then everything is OK.
4091 ;;; So perhaps we should replace the redefinition of lisp:require
4092 ;;; with the following macro definition:
4094 (unless *old-require
*
4096 (symbol-function #-
(or :lispworks
4098 (and :excl
:allegro-v4.0
)) 'lisp
:require
4100 #+:lispworks
'system
:::require
4101 #+(and :excl
:allegro-v4.0
) 'cltl1
:require
))
4103 (let (#+:CCL
(ccl:*warn-if-redefine-kernel
* nil
))
4104 ;; Note that lots of lisps barf if we redefine a function from
4105 ;; the LISP package. So what we do is define a macro with an
4106 ;; unused name, and use (setf macro-function) to redefine
4107 ;; lisp:require without compiler warnings. If the lisp doesn't
4108 ;; do the right thing, try just replacing require-as-macro
4109 ;; with lisp:require.
4110 (defmacro require-as-macro
(module-name
4111 &optional pathname definition-pname
4112 default-action
(version '*version
*))
4113 `(eval-when (compile load eval
)
4114 (new-require ,module-name
,pathname
,definition-pname
4115 ,default-action
,version
)))
4116 (setf (macro-function #-
(and :excl
:sbcl
:allegro-v4.0
) 'lisp
:require
4118 #+(and :excl
:allegro-v4.0
) 'cltl1
:require
)
4119 (macro-function 'require-as-macro
))))
4121 ;;; This will almost certainly fix the problem, but will cause problems
4122 ;;; if anybody does a funcall on #'require.
4124 ;;; Redefine old require to call the new require.
4125 (eval-when #-
(or :lucid
) (:load-toplevel
:execute
)
4126 #+(or :lucid
) (load eval
)
4127 (unless *old-require
*
4130 #-
(or (and :excl
:allegro-v4.0
) :ecl
:mcl
:sbcl
:scl
:lispworks
:abcl
:openmcl
) 'lisp
:require
4131 #+(and :excl
:allegro-v4.0
) 'cltl1
:require
4132 #+(or :ecl
:sbcl
:scl
) 'cl
:require
4133 #+(or :lispworks3.1
:abcl
) 'common-lisp
::require
4134 #+(and :lispworks
(not :lispworks3.1
)) 'system
::require
4135 #+:openmcl
'cl
:require
4136 #+(and :mcl
(not :openmcl
)) 'ccl
:require
4139 (unless *dont-redefine-require
*
4140 (let (#+(or :mcl
(and :CCL
(not :lispworks
)))
4141 (ccl:*warn-if-redefine-kernel
* nil
))
4142 #-
(or :ecl
(and allegro-version
>= (version>= 4 1)) :lispworks
)
4143 (setf (symbol-function
4144 #-
(or (and :excl
:allegro-v4.0
) :mcl
:sbcl
:scl
:lispworks
:abcl
:openmcl
) 'lisp
:require
4145 #+(and :excl
:allegro-v4.0
) 'cltl1
:require
4146 #+(or :lispworks3.1
:abcl
) 'common-lisp
::require
4147 #+(or :sbcl
:scl
) 'cl
:require
4148 #+(and :lispworks
(not :lispworks3.1
)) 'system
::require
4149 #+:openmcl
'cl
:require
4150 #+(and :mcl
(not :openmcl
)) 'ccl
:require
4152 (symbol-function 'new-require
))
4155 (ext:package-lock
"CL" nil
)
4156 (setf (symbol-function 'cl
:require
)
4157 (symbol-function 'new-require
))
4158 (ext:package-lock
"CL" t
))
4160 (let ((warn-packs system
::*packages-for-warn-on-redefinition
*))
4161 (declare (special system
::*packages-for-warn-on-redefinition
*))
4162 (setq system
::*packages-for-warn-on-redefinition
* nil
)
4163 (setf (symbol-function
4164 #+:lispworks3.1
'common-lisp
::require
4165 #-
:lispworks3.1
'system
::require
4167 (symbol-function 'new-require
))
4168 (setq system
::*packages-for-warn-on-redefinition
* warn-packs
))
4169 #+(and allegro-version
>= (version>= 4 1))
4170 (excl:without-package-locks
4171 (setf (symbol-function 'lisp
:require
)
4172 (symbol-function 'new-require
))))))
4176 ;;; Well, let's add some more REQUIRE hacking; specifically for SBCL,
4177 ;;; and, eventually, for CMUCL.
4180 (eval-when (:compile-toplevel
:load-toplevel
:execute
)
4182 (defun sbcl-mk-defsystem-module-provider (name)
4183 ;; Let's hope things go smoothly.
4184 (let ((module-name (string-downcase (string name
))))
4185 (when (mk:find-system module-name
:load-or-nil
)
4186 (mk:load-system module-name
4187 :compile-during-load t
4190 (pushnew 'sbcl-mk-defsystem-module-provider sb-ext
:*module-provider-functions
*)
4193 #+#.
(cl:if
(cl:and
(cl:find-package
:ext
) (cl:find-symbol
"*MODULE-PROVIDER-FUNCTIONS*" :ext
)) '(and) '(or))
4195 (defun cmucl-mk-defsystem-module-provider (name)
4196 (let ((module-name (string-downcase (string name
))))
4197 (when (mk:find-system module-name
:load-or-nil
)
4198 (mk:load-system module-name
4199 :compile-during-load t
4202 (pushnew 'cmucl-mk-defsystem-module-provider ext
:*module-provider-functions
*)
4208 ;;; ********************************
4209 ;;; Language-Dependent Characteristics
4210 ;;; ********************************
4211 ;;; This section is used for defining language-specific behavior of
4212 ;;; defsystem. If the user changes a language definition, it should
4213 ;;; take effect immediately -- they shouldn't have to reload the
4214 ;;; system definition file for the changes to take effect.
4216 (defvar *language-table
* (make-hash-table :test
#'equal
)
4217 "Hash table that maps from languages to language structures.")
4218 (defun find-language (name)
4219 (gethash name
*language-table
*))
4221 (defstruct (language (:print-function print-language
))
4222 name
; The name of the language (a keyword)
4223 compiler
; The function used to compile files in the language
4224 loader
; The function used to load files in the language
4225 source-extension
; Filename extensions for source files
4226 binary-extension
; Filename extensions for binary files
4229 (defun print-language (language stream depth
)
4230 (declare (ignore depth
))
4231 (format stream
"#<~:@(~A~): ~A ~A>"
4232 (language-name language
)
4233 (language-source-extension language
)
4234 (language-binary-extension language
)))
4236 (defun compile-function (component)
4237 (or (component-compiler component
)
4238 (let ((language (find-language (or (component-language component
)
4240 (when language
(language-compiler language
)))
4243 (defun load-function (component)
4244 (or (component-loader component
)
4245 (let ((language (find-language (or (component-language component
)
4247 (when language
(language-loader language
)))
4250 (defun default-source-extension (component)
4251 (let ((language (find-language (or (component-language component
)
4253 (or (when language
(language-source-extension language
))
4254 (car *filename-extensions
*))))
4256 (defun default-binary-extension (component)
4257 (let ((language (find-language (or (component-language component
)
4259 (or (when language
(language-binary-extension language
))
4260 (cdr *filename-extensions
*))))
4262 (defmacro define-language
(name &key compiler loader
4263 source-extension binary-extension
)
4264 (let ((language (gensym (symbol-name '#:language
))))
4265 `(let ((,language
(make-language :name
,name
4268 :source-extension
,source-extension
4269 :binary-extension
,binary-extension
)))
4270 (setf (gethash ,name
*language-table
*) ,language
)
4274 ;;; Test System for verifying multi-language capabilities.
4277 :components
((:module c
:language
:c
:components
("foo" "bar"))
4278 (:module lisp
:components
("baz" "barf"))))
4282 ;;; *** Lisp Language Definition
4283 (define-language :lisp
4284 :compiler
#'compile-file
4286 :source-extension
(car *filename-extensions
*)
4287 :binary-extension
(cdr *filename-extensions
*))
4289 ;;; *** PseudoScheme Language Definition
4290 (defun scheme-compile-file (filename &rest args
)
4291 (let ((scheme-package (find-package '#:scheme
)))
4292 (apply (symbol-function (find-symbol (symbol-name 'compile-file
)
4295 (funcall (symbol-function
4296 (find-symbol (symbol-name '#:interaction-environment
)
4300 (define-language :scheme
4301 :compiler
#'scheme-compile-file
4303 :source-extension
"scm"
4304 :binary-extension
"bin")
4306 ;;; *** C Language Definition
4308 ;;; This is very basic. Somebody else who needs it can add in support
4309 ;;; for header files, libraries, different C compilers, etc. For example,
4310 ;;; we might add a COMPILER-OPTIONS slot to the component defstruct.
4312 (defparameter *c-compiler
* "gcc")
4313 #-
(or symbolics
(and :lispworks
:harlequin-pc-lisp
))
4315 (defun run-unix-program (program arguments
)
4316 ;; arguments should be a list of strings, where each element is a
4317 ;; command-line option to send to the program.
4318 #+:lucid
(run-program program
:arguments arguments
)
4319 #+:allegro
(excl:run-shell-command
4320 (format nil
"~A~@[ ~{~A~^ ~}~]"
4322 #+(or :kcl
:ecl
) (system (format nil
"~A~@[ ~{~A~^ ~}~]" program arguments
))
4323 #+(or :cmu
:scl
) (extensions:run-program program arguments
)
4324 #+:openmcl
(ccl:run-program program arguments
)
4325 #+:sbcl
(sb-ext:run-program program arguments
)
4326 #+:lispworks
(sys:call-system-showing-output
4327 (format nil
"~A~@[ ~{~A~^ ~}~]" program arguments
))
4328 #+clisp
(#+lisp
=cl ext
:run-program
#-lisp
=cl lisp
:run-program
4329 program
:arguments arguments
)
4332 #+(or symbolics
(and :lispworks
:harlequin-pc-lisp
))
4333 (defun run-unix-program (program arguments
)
4334 (declare (ignore program arguments
))
4335 (error "MK::RUN-UNIX-PROGRAM: this does not seem to be a UN*X system.")
4339 (defun c-compile-file (filename &rest args
&key output-file error-file
)
4340 ;; gcc -c foo.c -o foo.o
4341 (declare (ignore args
))
4342 (run-unix-program *c-compiler
*
4343 (format nil
"-c ~A~@[ -o ~A~]"
4349 (defun c-compile-file (filename &rest args
&key output-file error-file
)
4350 ;; gcc -c foo.c -o foo.o
4351 (declare (ignore args error-file
))
4352 (run-unix-program *c-compiler
*
4353 `("-c" ,filename
,@(if output-file
`("-o" ,output-file
)))))
4357 ;;; The following code was inserted to improve C compiler support (at
4358 ;;; least under Linux/GCC).
4359 ;;; Thanks to Espen S Johnsen.
4361 ;;; 20001118 Marco Antoniotti.
4363 (defun default-output-pathname (path1 path2 type
)
4365 (translate-logical-pathname
4366 (merge-pathnames (make-pathname :type type
) (pathname path2
)))
4367 (translate-logical-pathname (pathname path1
))))
4370 (defun run-compiler (program
4376 #-
(or cmu scl
) (declare (ignore error-file error-output
))
4378 (flet ((make-useable-stream (&rest streams
)
4379 (apply #'make-broadcast-stream
(delete nil streams
)))
4381 (let (#+(or cmu scl
) (error-file error-file
)
4382 #+(or cmu scl
) (error-file-stream nil
)
4383 (verbose-stream nil
)
4384 (old-timestamp (file-write-date output-file
))
4386 (output-file-written nil
)
4393 (default-output-pathname error-file
4395 *compile-error-file-type
*))
4401 :if-exists
:supersede
)))
4403 (setf verbose-stream
4404 (make-useable-stream
4405 #+(or cmu scl
) error-file-stream
4406 (and verbose
*trace-output
*)))
4408 (format verbose-stream
"Running ~A~@[ ~{~A~^ ~}~]~%"
4414 (and (run-unix-program program arguments
) nil
) ; Incomplete.
4416 (let* ((error-output
4417 (make-useable-stream error-file-stream
4418 (if (eq error-output t
)
4422 (ext:run-program program arguments
4423 :error error-output
)))
4424 (not (zerop (ext:process-exit-code process
)))))
4426 (setf output-file-written
4427 (and (probe-file output-file
)
4428 (not (eql old-timestamp
4429 (file-write-date output-file
)))))
4432 (when output-file-written
4433 (format verbose-stream
"~A written~%" output-file
))
4434 (format verbose-stream
"Running of ~A finished~%"
4436 (values (and output-file-written output-file
)
4442 (close error-file-stream
)
4443 (unless (or fatal-error
(not output-file-written
))
4444 (delete-file error-file
)))
4446 (values (and output-file-written output-file
)
4451 ;;; C Language definitions.
4453 (defun c-compile-file (filename &rest args
4458 (verbose *compile-verbose
*)
4468 (declare (ignore args
))
4470 (flet ((map-options (flag options
&optional
(func #'identity
))
4471 (mapcar #'(lambda (option)
4472 (format nil
"~A~A" flag
(funcall func option
)))
4475 (let* ((output-file (default-output-pathname output-file filename
"o"))
4477 `(,@(when (not link
) '("-c"))
4478 ,@(when debug
'("-g"))
4479 ,@(when optimize
(list (format nil
"-O~D" optimize
)))
4483 #'(lambda (definition)
4484 (if (atom definition
)
4486 (apply #'format nil
"~A=~A" definition
))))
4487 ,@(map-options "-I" include-paths
#'truename
)
4488 ,(namestring (truename filename
))
4490 ,(namestring (translate-logical-pathname output-file
))
4491 ,@(map-options "-L" library-paths
#'truename
)
4492 ,@(map-options "-l" libraries
))))
4494 (multiple-value-bind (output-file warnings fatal-errors
)
4495 (run-compiler *c-compiler
*
4501 (if (and error
(or (not output-file
) fatal-errors
))
4502 (error "Compilation failed")
4503 (values output-file warnings fatal-errors
))))))
4507 :compiler
#'c-compile-file
4508 :loader
#+:lucid
#'load-foreign-files
4510 #+(or :cmu
:scl
) #'alien
:load-foreign
4511 #+:sbcl
#'sb-alien
:load-foreign
4512 #+(and :lispworks
:unix
(not :linux
) (not :macosx
)) #'link-load
:read-foreign-modules
4513 #+(and :lispworks
:unix
(or :linux
:macosx
)) #'fli
:register-module
4514 #+(and :lispworks
:win32
) #'fli
:register-module
4515 #+(or :ecl
:gcl
:kcl
) #'load
; should be enough.
4523 (lambda (&rest args
)
4524 (declare (ignore args
))
4525 (cerror "Continue returning NIL."
4526 "Loader not defined for C foreign libraries in ~A ~A."
4527 (lisp-implementation-type)
4528 (lisp-implementation-version)))
4529 :source-extension
"c"
4530 :binary-extension
"o")
4533 ;;; Fortran Language definitions.
4536 (export '(*fortran-compiler
* *fortran-options
*))
4538 (defparameter *fortran-compiler
* "g77")
4539 (defparameter *fortran-options
* '("-O"))
4541 (defun fortran-compile-file (filename &rest args
4542 &key output-file error-file
4544 (declare (ignore error-file args
))
4546 (append *fortran-options
*
4547 `("-c" ,filename
,@(if output-file
`("-o" ,output-file
))))))
4548 (run-unix-program *fortran-compiler
* arg-list
)))
4551 (mk:define-language
:fortran
4552 :compiler
#'fortran-compile-file
4554 :source-extension
"f"
4555 :binary-extension
"o")
4559 ;; How to create a library (archive) of object files
4561 (export '(*ar-program
* build-lib
))
4563 (defparameter *ar-program
* "ar")
4565 (defun build-lib (libname directory
)
4566 (let ((args (list "rv" (truename libname
))))
4567 (format t
";;; Building archive ~A~%" libname
)
4568 (run-unix-program *ar-program
*
4570 (mapcar #'truename
(directory directory
))))))
4573 ;;; ********************************
4574 ;;; Component Operations ***********
4575 ;;; ********************************
4576 ;;; Define :compile/compile and :load/load operations
4577 (eval-when (load eval
)
4578 (component-operation :compile
'compile-and-load-operation
)
4579 (component-operation 'compile
'compile-and-load-operation
)
4580 (component-operation :load
'load-file-operation
)
4581 (component-operation 'load
'load-file-operation
)
4584 (defun compile-and-load-operation (component force
)
4585 ;; FORCE was CHANGED. this caused defsystem during compilation to only
4586 ;; load files that it immediately compiled.
4587 (let ((changed (compile-file-operation component force
)))
4588 ;; Return T if the file had to be recompiled and reloaded.
4589 (if (and changed
(component-compile-only component
))
4590 ;; For files which are :compile-only T, compiling the file
4591 ;; satisfies the need to load.
4593 ;; If the file wasn't compiled, or :compile-only is nil,
4594 ;; check to see if it needs to be loaded.
4595 (and (load-file-operation component force
) ; FORCE was CHANGED ???
4598 (defun unmunge-lucid (namestring)
4599 ;; Lucid's implementation of COMPILE-FILE is non-standard, in that
4600 ;; when the :output-file is a relative pathname, it tries to munge
4601 ;; it with the directory of the source file. For example,
4602 ;; (compile-file "src/globals.lisp" :output-file "bin/globals.sbin")
4603 ;; tries to stick the file in "./src/bin/globals.sbin" instead of
4604 ;; "./bin/globals.sbin" like any normal lisp. This hack seems to fix the
4605 ;; problem. I wouldn't have expected this problem to occur with any
4606 ;; use of defsystem, but some defsystem users are depending on
4607 ;; using relative pathnames (at least three folks reported the problem).
4608 (cond ((null-string namestring
) namestring
)
4609 ((char= (char namestring
0) #\
/)
4610 ;; It's an absolute namestring
4613 ;; Ugly, but seems to fix the problem.
4614 (concatenate 'string
"./" namestring
))))
4616 ;; Define our own version of ensure-directories-exist for gcl, if gcl
4617 ;; doesn't have it. (gcl 2.6.10 has ensure-directories-exist).
4618 #+#.
(cl:if
(cl:and
(cl:member
:gcl cl
:*features
*) (cl:not
(cl:fboundp
(cl:find-symbol
"ENSURE-DIRECTORIES-EXIST" "COMMON-LISP")))) '(and) '(or))
4619 (defun ensure-directories-exist (pathspec &key verbose
)
4620 (declare (ignore verbose
))
4621 ;; A very gross implementation of ensure-directories-exist. Just
4622 ;; call /bin/mkdir with our desired path.
4623 (let* ((dir (make-pathname :host
(pathname-host pathspec
)
4624 :device
(pathname-device pathspec
)
4625 :directory
(pathname-directory pathspec
)))
4626 (cmd (if (member :win32
*features
*)
4627 (format nil
"mkdir \"~a\""
4628 (coerce (subst #\\ #\
/ (coerce (namestring dir
) 'list
)) 'string
))
4629 (format nil
"/bin/mkdir -p ~S" (namestring dir
)))))
4630 (unless (directory dir
)
4632 ;; The second return value is supposed to be T if directories were
4633 ;; created. I don't know how to tell that, so we just return T.
4634 ;; (Would NIL be better?)
4635 (values pathspec t
)))
4637 (defun compile-file-operation (component force
)
4638 ;; Returns T if the file had to be compiled.
4640 ;; For files which are :load-only T, loading the file
4641 ;; satisfies the demand to recompile.
4642 (and (null (component-load-only component
)) ; not load-only
4643 (or (find force
'(:all
:new-source-all t
) :test
#'eq
)
4644 (and (find force
'(:new-source
:new-source-and-dependents
)
4646 (needs-compilation component nil
)))))
4647 (source-pname (component-full-pathname component
:source
)))
4649 (cond ((and must-compile
(probe-file source-pname
))
4650 (with-tell-user ("Compiling source" component
:source
)
4653 (unmunge-lucid (component-full-pathname component
4656 (component-full-pathname component
:binary
)))
4658 ;; make certain the directory we need to write to
4659 ;; exists [pvaneynd@debian.org 20001114]
4660 ;; Added PATHNAME-HOST following suggestion by John
4661 ;; DeSoi [marcoxa@sourceforge.net 20020529]
4663 (ensure-directories-exist
4664 (make-pathname :name nil
4667 :defaults output-file
))
4670 (apply (compile-function component
)
4674 #+(or :cmu
:scl
) :error-file
4675 #+(or :cmu
:scl
) (and *cmu-errors-to-file
*
4676 (component-full-pathname component
4681 *cmu-errors-to-terminal
*
4682 (component-compiler-options component
)
4686 (tell-user "Source file not found. Not compiling"
4687 component
:source
:no-dots
:force
)
4691 ;; see CLOCC/PORT/sys.lisp:compiled-file-p
4692 (eval-when (load eval compile
)
4693 (when (find-package :port
)
4694 (import (find-symbol (symbol-name '#:compiled-file-p
) :port
))))
4695 (unless (fboundp 'compiled-file-p
)
4696 (defun compiled-file-p (file-name)
4697 "Return T if the FILE-NAME is a filename designator for a valid compiled.
4698 Signal an error when it is not a filename designator.
4699 Return NIL when the file does not exist, or is not readable,
4700 or does not contain valid compiled code."
4701 (declare (ignorable file-name
))
4703 (with-open-file (in file-name
:direction
:input
:if-does-not-exist nil
)
4704 (and in
(char= #\
( (peek-char nil in
))
4705 (let ((form (ignore-errors (read in nil nil
))))
4707 (eq (car form
) 'SYSTEM
::VERSION
)
4708 (null (nth-value 1 (ignore-errors (eval form
))))))))
4711 (defun needs-compilation (component force
)
4712 ;; If there is no binary, or it is older than the source
4713 ;; file, then the component needs to be compiled.
4714 ;; Otherwise we only need to recompile if it depends on a file that changed.
4715 (declare (ignore force
))
4716 (let ((source-pname (component-full-pathname component
:source
))
4717 (binary-pname (component-full-pathname component
:binary
)))
4719 ;; source must exist
4720 (probe-file source-pname
)
4722 ;; We force recompilation.
4723 #|
(find force
'(:all
:new-source-all
) :test
#'eq
)|
#
4725 (null (probe-file binary-pname
))
4727 (< (file-write-date binary-pname
)
4728 (file-write-date source-pname
))
4730 #+clisp
(not (compiled-file-p binary-pname
))))))
4733 (defun needs-loading (component &optional
(check-source t
) (check-binary t
))
4734 ;; Compares the component's load-time against the file-write-date of
4735 ;; the files on disk.
4736 (let ((load-time (component-load-time component
))
4737 (source-pname (component-full-pathname component
:source
))
4738 (binary-pname (component-full-pathname component
:binary
)))
4740 #|| ISI Extension ||
#
4741 (component-load-always component
)
4743 ;; File never loaded.
4746 (when (and check-binary
4747 (probe-file binary-pname
))
4749 (file-write-date binary-pname
)))
4751 (when (and check-source
4752 (probe-file source-pname
))
4754 (file-write-date source-pname
))))))
4756 ;;; Need to completely rework this function...
4757 (defun load-file-operation (component force
)
4758 ;; Returns T if the file had to be loaded
4759 (let* ((binary-pname (component-full-pathname component
:binary
))
4760 (source-pname (component-full-pathname component
:source
))
4761 (binary-exists (probe-file binary-pname
))
4762 (source-exists (probe-file source-pname
))
4763 (source-needs-loading (needs-loading component t nil
))
4764 (binary-needs-loading (needs-loading component nil t
))
4765 ;; needs-compilation has an implicit source-exists in it.
4766 (needs-compilation (if (component-load-only component
)
4767 source-needs-loading
4768 (needs-compilation component force
)))
4769 (check-for-new-source
4770 ;; If force is :new-source*, we're checking for files
4771 ;; whose source is newer than the compiled versions.
4772 (find force
'(:new-source
:new-source-and-dependents
:new-source-all
)
4774 (load-binary (or (find force
'(:all
:new-source-all t
) :test
#'eq
)
4775 binary-needs-loading
))
4777 (or *load-source-instead-of-binary
*
4778 (and load-binary
(component-load-only component
))
4779 (and check-for-new-source needs-compilation
)))
4781 (and needs-compilation
4782 (or load-binary check-for-new-source
)
4783 (compile-and-load-source-if-no-binary component
)))
4785 ;; When we're trying to minimize the files loaded to only those
4786 ;; that need be, restrict the values of load-source and load-binary
4787 ;; so that we only load the component if the files are newer than
4789 (when (and *minimal-load
*
4790 (not (find force
'(:all
:new-source-all
)
4792 (when load-source
(setf load-source source-needs-loading
))
4793 (when load-binary
(setf load-binary binary-needs-loading
)))
4795 (when (or load-source load-binary compile-and-load
)
4796 (cond (compile-and-load
4797 ;; If we're loading the binary and it is old or nonexistent,
4798 ;; and the user says yes, compile and load the source.
4799 (compile-file-operation component t
)
4800 (with-tell-user ("Loading binary" component
:binary
)
4803 (funcall (load-function component
) binary-pname
)
4804 (setf (component-load-time component
)
4805 (file-write-date binary-pname
)))))
4808 (or (and load-source
; implicit needs-comp...
4809 (or *load-source-instead-of-binary
*
4810 (component-load-only component
)
4811 (not *compile-during-load
*)))
4814 (load-source-if-no-binary component
))))
4815 ;; Load the source if the source exists and:
4816 ;; o we're loading binary and it doesn't exist
4817 ;; o we're forcing it
4818 ;; o we're loading new source and user wasn't asked to compile
4819 (with-tell-user ("Loading source" component
:source
)
4822 (funcall (load-function component
) source-pname
)
4823 (setf (component-load-time component
)
4824 (file-write-date source-pname
)))))
4826 ((and binary-exists load-binary
)
4827 (with-tell-user ("Loading binary" component
:binary
)
4830 (funcall (load-function component
) binary-pname
)
4831 (setf (component-load-time component
)
4832 (file-write-date binary-pname
)))))
4834 ((and (not binary-exists
) (not source-exists
))
4835 (tell-user-no-files component
:force
)
4836 (when *files-missing-is-an-error
*
4837 (cerror "Continue, ignoring missing files."
4838 "~&Source file ~S ~:[and binary file ~S ~;~]do not exist."
4840 (or *load-source-if-no-binary
*
4841 *load-source-instead-of-binary
*)
4847 (eval-when (load eval
)
4848 (component-operation :clean
'delete-binaries-operation
)
4849 (component-operation 'clean
'delete-binaries-operation
)
4850 (component-operation :delete-binaries
'delete-binaries-operation
)
4851 (component-operation 'delete-binaries
'delete-binaries-operation
)
4853 (defun delete-binaries-operation (component force
)
4854 (when (or (eq force
:all
)
4856 (and (find force
'(:new-source
:new-source-and-dependents
4859 (needs-compilation component nil
)))
4860 (let ((binary-pname (component-full-pathname component
:binary
)))
4861 (when (probe-file binary-pname
)
4862 (with-tell-user ("Deleting binary" component
:binary
)
4864 (delete-file binary-pname
)))))))
4867 ;; when the operation = :compile, we can assume the binary exists in test mode.
4869 ;; (eq operation :compile)
4870 ;; (probe-file (component-full-pathname component :source)))
4871 ;; (with-tell-user ("Loading binary" component :binary)))
4873 (defun binary-exists (component)
4874 (probe-file (component-full-pathname component
:binary
)))
4877 (defun compile-and-load-source-if-no-binary (component)
4878 (when (not (or *load-source-instead-of-binary
*
4879 (and *load-source-if-no-binary
*
4880 (not (binary-exists component
)))))
4881 (cond ((component-load-only component
)
4883 (let ((prompt (prompt-string component
)))
4884 (format t
"~A- File ~A is load-only, ~
4885 ~&~A not compiling."
4887 (component-full-pathname component
:source
)
4891 ((eq *compile-during-load
* :query
)
4892 (let* ((prompt (prompt-string component
))
4896 "~A- Binary file ~A is old or does not exist. ~
4897 ~&~A Compile (and load) source file ~A instead? "
4899 (component-full-pathname component
:binary
)
4901 (component-full-pathname component
:source
))))
4902 (unless (y-or-n-p-wait
4904 "~A- Should I bother you if this happens again? "
4906 (setq *compile-during-load
*
4909 "~A- Should I compile while loading the system? "
4910 prompt
))) ; was compile-source, then t
4912 (*compile-during-load
*)
4915 (defun load-source-if-no-binary (component)
4916 (and (not *load-source-instead-of-binary
*)
4917 (or (and *load-source-if-no-binary
*
4918 (not (binary-exists component
)))
4919 (component-load-only component
)
4920 (when *bother-user-if-no-binary
*
4921 (let* ((prompt (prompt-string component
))
4923 (y-or-n-p-wait #\y
30
4924 "~A- Binary file ~A does not exist. ~
4925 ~&~A Load source file ~A instead? "
4927 (component-full-pathname component
:binary
)
4929 (component-full-pathname component
:source
))))
4930 (setq *bother-user-if-no-binary
*
4931 (y-or-n-p-wait #\n 30
4932 "~A- Should I bother you if this happens again? "
4934 (unless *bother-user-if-no-binary
*
4935 (setq *load-source-if-no-binary
* load-source
))
4938 ;;; ********************************
4939 ;;; Allegro Toplevel Commands ******
4940 ;;; ********************************
4941 ;;; Creates toplevel command aliases for Allegro CL.
4943 (top-level:alias
("compile-system" 8)
4944 (system &key force
(minimal-load mk
:*minimal-load
*)
4945 test verbose version
)
4946 "Compile the specified system"
4948 (mk:compile-system system
:force force
4949 :minimal-load minimal-load
4950 :test test
:verbose verbose
4954 (top-level:alias
("load-system" 5)
4955 (system &key force
(minimal-load mk
:*minimal-load
*)
4956 (compile-during-load mk
:*compile-during-load
*)
4957 test verbose version
)
4958 "Compile the specified system"
4960 (mk:load-system system
:force force
4961 :minimal-load minimal-load
4962 :compile-during-load compile-during-load
4963 :test test
:verbose verbose
4967 (top-level:alias
("show-system" 5) (system)
4968 "Show information about the specified system."
4970 (mk:describe-system system
))
4973 (top-level:alias
("describe-system" 9) (system)
4974 "Show information about the specified system."
4976 (mk:describe-system system
))
4979 (top-level:alias
("system-source-size" 9) (system)
4980 "Show size information about source files in the specified system."
4982 (mk:system-source-size system
))
4985 (top-level:alias
("clean-system" 6)
4986 (system &key force test verbose version
)
4987 "Delete binaries in the specified system."
4989 (mk:clean-system system
:force force
4990 :test test
:verbose verbose
4994 (top-level:alias
("edit-system" 7)
4995 (system &key force test verbose version
)
4996 "Load system source files into Emacs."
4998 (mk:edit-system system
:force force
4999 :test test
:verbose verbose
5003 (top-level:alias
("hardcopy-system" 9)
5004 (system &key force test verbose version
)
5005 "Hardcopy files in the specified system."
5007 (mk:hardcopy-system system
:force force
5008 :test test
:verbose verbose
5012 (top-level:alias
("make-system-tag-table" 13) (system)
5013 "Make an Emacs TAGS file for source files in specified system."
5015 (mk:make-system-tag-table system
))
5018 ;;; ********************************
5019 ;;; Allegro Make System Fasl *******
5020 ;;; ********************************
5022 (defun allegro-make-system-fasl (system destination
5023 &optional
(include-dependents t
))
5025 (format nil
"rm -f ~A; cat~{ ~A~} > ~A"
5027 (if include-dependents
5028 (files-in-system-and-dependents system
:all
:binary
)
5029 (files-in-system system
:all
:binary
))
5032 (defun files-which-need-compilation (system)
5033 (mapcar #'(lambda (comp) (component-full-pathname comp
:source
))
5035 (file-components-in-component
5036 (find-system system
:load
) :new-source
))))
5038 (defun files-in-system-and-dependents (name &optional
(force :all
)
5039 (type :source
) version
)
5040 ;; Returns a list of the pathnames in system and dependents in load order.
5041 (let ((system (find-system name
:load
)))
5042 (multiple-value-bind (*version-dir
* *version-replace
*)
5043 (translate-version version
)
5044 (let ((*version
* version
))
5045 (let ((result (file-pathnames-in-component system type force
)))
5046 (dolist (dependent (reverse (component-depends-on system
)))
5048 (append (files-in-system-and-dependents dependent
5053 (defun files-in-system (name &optional
(force :all
) (type :source
) version
)
5054 ;; Returns a list of the pathnames in system in load order.
5055 (let ((system (if (and (component-p name
)
5056 (member (component-type name
) '(:defsystem
:system
:subsystem
)))
5058 (find-system name
:load
))))
5059 (multiple-value-bind (*version-dir
* *version-replace
*)
5060 (translate-version version
)
5061 (let ((*version
* version
))
5062 (file-pathnames-in-component system type force
)))))
5064 (defun file-pathnames-in-component (component type
&optional
(force :all
))
5065 (mapcar #'(lambda (comp) (component-full-pathname comp type
))
5066 (file-components-in-component component force
)))
5068 (defun file-components-in-component (component &optional
(force :all
)
5069 &aux result changed
)
5070 (case (component-type component
)
5071 ((:file
:private-file
)
5073 (or (find force
'(:all t
) :test
#'eq
)
5074 (and (not (non-empty-listp force
))
5075 (needs-compilation component nil
))))
5078 ((:module
:system
:subsystem
:defsystem
)
5079 (dolist (module (component-components component
))
5080 (multiple-value-bind (r c
)
5081 (file-components-in-component
5083 (cond ((and (some #'(lambda (dependent)
5084 (member dependent changed
))
5085 (component-depends-on module
))
5086 (or (non-empty-listp force
)
5087 (eq force
:new-source-and-dependents
)))
5088 ;; The component depends on a changed file and force agrees.
5090 ((and (non-empty-listp force
)
5091 (member (component-name module
) force
5092 :test
#'string-equal
:key
#'string
))
5093 ;; Force is a list of modules and the component is
5098 (push module changed
)
5099 (setq result
(append result r
)))))))
5100 (values result changed
))
5102 (setf (symbol-function 'oos
) (symbol-function 'operate-on-system
))
5104 ;;; ********************************
5105 ;;; Additional Component Operations
5106 ;;; ********************************
5108 ;;; *** Edit Operation ***
5110 ;;; Should this conditionalization be (or :mcl (and :CCL (not :lispworks)))?
5113 (defun edit-operation (component force
)
5114 "Always returns nil, i.e. component not changed."
5115 (declare (ignore force
))
5117 (let* ((full-pathname (make::component-full-pathname component
:source
))
5118 (already-editing\? #+:mcl
(dolist (w (CCL:windows
:class
5120 (when (equal (CCL:window-filename w
)
5124 (if already-editing
\?
5125 #+:mcl
(CCL:window-select already-editing
\?) #-
:mcl nil
5126 (ed full-pathname
)))
5130 (defun edit-operation (component force
)
5131 "Edit a component - always returns nil, i.e. component not changed."
5132 (declare (ignore force
))
5133 (let ((full-pathname (component-full-pathname component
:source
)))
5137 #+(or :ccl
:allegro
)
5138 (make::component-operation
:edit
'edit-operation
)
5139 #+(or :ccl
:allegro
)
5140 (make::component-operation
'edit
'edit-operation
)
5143 ;;; *** Hardcopy System ***
5144 (defparameter *print-command
* "enscript -2Gr" ; "lpr"
5145 "Command to use for printing files on UNIX systems.")
5147 (defun hardcopy-operation (component force
)
5148 "Hardcopy a component - always returns nil, i.e. component not changed."
5149 (declare (ignore force
))
5150 (let ((full-pathname (component-full-pathname component
:source
)))
5151 (excl:run-shell-command
(format nil
"~A ~A"
5152 *print-command
* full-pathname
)))
5156 (make::component-operation
:hardcopy
'hardcopy-operation
)
5158 (make::component-operation
'hardcopy
'hardcopy-operation
)
5161 ;;; *** System Source Size ***
5163 (defun system-source-size (system-name &optional
(force :all
))
5164 "Prints a short report and returns the size in bytes of the source files in
5166 (let* ((file-list (files-in-system system-name force
:source
))
5167 (total-size (file-list-size file-list
)))
5168 (format t
"~&~a/~a (~:d file~:p) totals ~:d byte~:p (~:d kB)"
5169 system-name force
(length file-list
)
5170 total-size
(round total-size
1024))
5173 (defun file-list-size (file-list)
5174 "Returns the size in bytes of the files in <file-list>."
5176 (let ((total-size 0))
5177 (dolist (file file-list
)
5178 (with-open-file (stream file
)
5179 (incf total-size
(file-length stream
))))
5182 ;;; *** System Tag Table ***
5185 (defun make-system-tag-table (system-name)
5186 "Makes an Emacs tag table using the GNU etags program."
5187 (let ((files-in-system (files-in-system system-name
:all
:source
)))
5189 (format t
"~&Making tag table...")
5190 (excl:run-shell-command
(format nil
"etags ~{~a ~}" files-in-system
))
5191 (format t
"done.~%")))
5194 ;;; end of file -- defsystem.lisp --