/[slime]/slime/swank-loader.lisp
ViewVC logotype

Contents of /slime/swank-loader.lisp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.110 - (show annotations)
Sun Nov 7 19:48:14 2010 UTC (3 years, 5 months ago) by heller
Branch: MAIN
CVS Tags: SLIME-2-3, SLIME-2-2, byte-stream, FAIRLY-STABLE
Changes since 1.109: +6 -26 lines
* swank-loader.lisp: ASDF free again.  And proud of it!
(default-fasl-dir, load-swank): Remove asdf stuff.
1 ;;;; -*- indent-tabs-mode: nil -*-
2 ;;;
3 ;;; swank-loader.lisp --- Compile and load the Slime backend.
4 ;;;
5 ;;; Created 2003, James Bielman <jamesjb@jamesjb.com>
6 ;;;
7 ;;; This code has been placed in the Public Domain. All warranties
8 ;;; are disclaimed.
9 ;;;
10
11 ;; If you want customize the source- or fasl-directory you can set
12 ;; swank-loader:*source-directory* resp. swank-loader:*fasl-directory*
13 ;; before loading this files. (you also need to create the
14 ;; swank-loader package.)
15 ;; E.g.:
16 ;;
17 ;; (make-package :swank-loader)
18 ;; (defparameter swank-loader::*fasl-directory* "/tmp/fasl/")
19 ;; (load ".../swank-loader.lisp")
20
21 (cl:defpackage :swank-loader
22 (:use :cl)
23 (:export :init
24 :dump-image
25 :*source-directory*
26 :*fasl-directory*))
27
28 (cl:in-package :swank-loader)
29
30 (defvar *source-directory*
31 (make-pathname :name nil :type nil
32 :defaults (or *load-pathname* *default-pathname-defaults*))
33 "The directory where to look for the source.")
34
35 (defparameter *sysdep-files*
36 #+cmu '(swank-source-path-parser swank-source-file-cache swank-cmucl)
37 #+scl '(swank-source-path-parser swank-source-file-cache swank-scl)
38 #+sbcl '(swank-source-path-parser swank-source-file-cache
39 swank-sbcl swank-gray)
40 #+clozure '(metering swank-ccl swank-gray)
41 #+lispworks '(swank-lispworks swank-gray)
42 #+allegro '(swank-allegro swank-gray)
43 #+clisp '(xref metering swank-clisp swank-gray)
44 #+armedbear '(swank-abcl)
45 #+cormanlisp '(swank-corman swank-gray)
46 #+ecl '(swank-source-path-parser swank-source-file-cache
47 swank-ecl swank-gray))
48
49 (defparameter *implementation-features*
50 '(:allegro :lispworks :sbcl :clozure :cmu :clisp :ccl :corman :cormanlisp
51 :armedbear :gcl :ecl :scl))
52
53 (defparameter *os-features*
54 '(:macosx :linux :windows :mswindows :win32 :solaris :darwin :sunos :hpux
55 :unix))
56
57 (defparameter *architecture-features*
58 '(:powerpc :ppc :x86 :x86-64 :x86_64 :amd64 :i686 :i586 :i486 :pc386 :iapx386
59 :sparc64 :sparc :hppa64 :hppa :arm
60 :pentium3 :pentium4
61 :java-1.4 :java-1.5 :java-1.6 :java-1.7))
62
63 (defun q (s) (read-from-string s))
64
65 #+ecl
66 (defun ecl-version-string ()
67 (format nil "~A~@[-~A~]"
68 (lisp-implementation-version)
69 (when (find-symbol "LISP-IMPLEMENTATION-VCS-ID" :ext)
70 (let ((vcs-id (funcall (q "ext:lisp-implementation-vcs-id"))))
71 (when (>= (length vcs-id) 8)
72 (subseq vcs-id 0 8))))))
73
74 (defun lisp-version-string ()
75 #+(or clozure cmu) (substitute-if #\_ (lambda (x) (find x " /"))
76 (lisp-implementation-version))
77 #+(or cormanlisp scl sbcl) (lisp-implementation-version)
78 #+lispworks (lisp-implementation-version)
79 #+allegro (format nil "~A~A~A~A"
80 excl::*common-lisp-version-number*
81 (if (eq 'h 'H) "A" "M") ; ANSI vs MoDeRn
82 (if (member :64bit *features*) "-64bit" "")
83 (excl:ics-target-case
84 (:-ics "")
85 (:+ics "-ics")))
86 #+clisp (let ((s (lisp-implementation-version)))
87 (subseq s 0 (position #\space s)))
88 #+armedbear (lisp-implementation-version)
89 #+ecl (ecl-version-string) )
90
91 (defun unique-dir-name ()
92 "Return a name that can be used as a directory name that is
93 unique to a Lisp implementation, Lisp implementation version,
94 operating system, and hardware architecture."
95 (flet ((first-of (features)
96 (loop for f in features
97 when (find f *features*) return it))
98 (maybe-warn (value fstring &rest args)
99 (cond (value)
100 (t (apply #'warn fstring args)
101 "unknown"))))
102 (let ((lisp (maybe-warn (first-of *implementation-features*)
103 "No implementation feature found in ~a."
104 *implementation-features*))
105 (os (maybe-warn (first-of *os-features*)
106 "No os feature found in ~a." *os-features*))
107 (arch (maybe-warn (first-of *architecture-features*)
108 "No architecture feature found in ~a."
109 *architecture-features*))
110 (version (maybe-warn (lisp-version-string)
111 "Don't know how to get Lisp ~
112 implementation version.")))
113 (format nil "~(~@{~a~^-~}~)" lisp version os arch))))
114
115 (defun file-newer-p (new-file old-file)
116 "Returns true if NEW-FILE is newer than OLD-FILE."
117 (> (file-write-date new-file) (file-write-date old-file)))
118
119 (defun slime-version-string ()
120 "Return a string identifying the SLIME version.
121 Return nil if nothing appropriate is available."
122 (with-open-file (s (merge-pathnames "ChangeLog" *source-directory*)
123 :if-does-not-exist nil)
124 (and s (symbol-name (read s)))))
125
126 (defun default-fasl-dir ()
127 (merge-pathnames
128 (make-pathname
129 :directory `(:relative ".slime" "fasl"
130 ,@(if (slime-version-string) (list (slime-version-string)))
131 ,(unique-dir-name)))
132 (user-homedir-pathname)))
133
134 (defvar *fasl-directory* (default-fasl-dir)
135 "The directory where fasl files should be placed.")
136
137 (defun binary-pathname (src-pathname binary-dir)
138 "Return the pathname where SRC-PATHNAME's binary should be compiled."
139 (let ((cfp (compile-file-pathname src-pathname)))
140 (merge-pathnames (make-pathname :name (pathname-name cfp)
141 :type (pathname-type cfp))
142 binary-dir)))
143
144 (defun handle-swank-load-error (condition context pathname)
145 (fresh-line *error-output*)
146 (pprint-logical-block (*error-output* () :per-line-prefix ";; ")
147 (format *error-output*
148 "~%Error while ~A ~A:~% ~A~%Aborting.~%"
149 context pathname condition))
150 (when (equal (directory-namestring pathname)
151 (directory-namestring *fasl-directory*))
152 (ignore-errors (delete-file pathname)))
153 (abort))
154
155 (defun compile-files (files fasl-dir load)
156 "Compile each file in FILES if the source is newer than its
157 corresponding binary, or the file preceding it was recompiled.
158 If LOAD is true, load the fasl file."
159 (let ((needs-recompile nil)
160 (state :unknown))
161 (dolist (src files)
162 (let ((dest (binary-pathname src fasl-dir)))
163 (handler-case
164 (progn
165 (when (or needs-recompile
166 (not (probe-file dest))
167 (file-newer-p src dest))
168 (ensure-directories-exist dest)
169 ;; need to recompile SRC, so we'll need to recompile
170 ;; everything after this too.
171 (setq needs-recompile t)
172 (setq state :compile)
173 (or (compile-file src :output-file dest :print nil :verbose t)
174 ;; An implementation may not necessarily signal a
175 ;; condition itself when COMPILE-FILE fails (e.g. ECL)
176 (error "COMPILE-FILE returned NIL.")))
177 (when load
178 (setq state :load)
179 (load dest :verbose t)))
180 ;; Fail as early as possible
181 (serious-condition (c)
182 (ecase state
183 (:compile (handle-swank-load-error c "compiling" src))
184 (:load (handle-swank-load-error c "loading" dest))
185 (:unknown (handle-swank-load-error c "???ing" src)))))))))
186
187 #+(or cormanlisp)
188 (defun compile-files (files fasl-dir load)
189 "Corman Lisp has trouble with compiled files."
190 (declare (ignore fasl-dir))
191 (when load
192 (dolist (file files)
193 (load file :verbose t)
194 (force-output))))
195
196 (defun load-user-init-file ()
197 "Load the user init file, return NIL if it does not exist."
198 (load (merge-pathnames (user-homedir-pathname)
199 (make-pathname :name ".swank" :type "lisp"))
200 :if-does-not-exist nil))
201
202 (defun load-site-init-file (dir)
203 (load (make-pathname :name "site-init" :type "lisp"
204 :defaults dir)
205 :if-does-not-exist nil))
206
207 (defun src-files (names src-dir)
208 (mapcar (lambda (name)
209 (make-pathname :name (string-downcase name) :type "lisp"
210 :defaults src-dir))
211 names))
212
213 (defvar *swank-files*
214 `(swank-backend ,@*sysdep-files* swank-match swank-rpc swank))
215
216 (defvar *contribs*
217 '(swank-c-p-c swank-arglists swank-fuzzy
218 swank-fancy-inspector
219 swank-presentations swank-presentation-streams
220 #+(or asdf sbcl ecl) swank-asdf
221 swank-package-fu
222 swank-hyperdoc
223 #+sbcl swank-sbcl-exts
224 )
225 "List of names for contrib modules.")
226
227 (defun append-dir (absolute name)
228 (merge-pathnames
229 (make-pathname :directory `(:relative ,name) :defaults absolute)
230 absolute))
231
232 (defun contrib-dir (base-dir)
233 (append-dir base-dir "contrib"))
234
235 (defun load-swank (&key (src-dir *source-directory*)
236 (fasl-dir *fasl-directory*))
237 (compile-files (src-files *swank-files* src-dir) fasl-dir t)
238 (funcall (q "swank::before-init")
239 (slime-version-string)
240 (list (contrib-dir fasl-dir)
241 (contrib-dir src-dir))))
242
243 (defun compile-contribs (&key (src-dir (contrib-dir *source-directory*))
244 (fasl-dir (contrib-dir *fasl-directory*))
245 load)
246 (compile-files (src-files *contribs* src-dir) fasl-dir load))
247
248 (defun loadup ()
249 (load-swank)
250 (compile-contribs :load t))
251
252 (defun setup ()
253 (load-site-init-file *source-directory*)
254 (load-user-init-file)
255 (when (#-clisp probe-file
256 #+clisp ext:probe-directory
257 (contrib-dir *source-directory*))
258 (eval `(pushnew 'compile-contribs ,(q "swank::*after-init-hook*"))))
259 (funcall (q "swank::init")))
260
261 (defun init (&key delete reload load-contribs (setup t))
262 "Load SWANK and initialize some global variables.
263 If DELETE is true, delete any existing SWANK packages.
264 If RELOAD is true, reload SWANK, even if the SWANK package already exists.
265 If LOAD-CONTRIBS is true, load all contribs
266 If SETUP is true, load user init files and initialize some
267 global variabes in SWANK."
268 (when (and delete (find-package :swank))
269 (mapc #'delete-package '(:swank :swank-io-package :swank-backend)))
270 (cond ((or (not (find-package :swank)) reload)
271 (load-swank))
272 (t
273 (warn "Not reloading SWANK. Package already exists.")))
274 (when load-contribs
275 (compile-contribs :load t))
276 (when setup
277 (setup)))
278
279 (defun dump-image (filename)
280 (init :setup nil)
281 (funcall (q "swank-backend:save-image") filename))

  ViewVC Help
Powered by ViewVC 1.1.5