source: branches/qres/ccl/lib/compile-ccl.lisp @ 14259

Last change on this file since 14259 was 14259, checked in by gz, 9 years ago

r14258 from trunk (defstruct changes)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 31.2 KB
Line 
1;;;-*-Mode: LISP; Package: CCL -*-
2;;;
3;;;   Copyright (C) 2009 Clozure Associates
4;;;   Copyright (C) 1994-2001 Digitool, Inc
5;;;   This file is part of Clozure CL. 
6;;;
7;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
8;;;   License , known as the LLGPL and distributed with Clozure CL as the
9;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
10;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
11;;;   conflict, the preamble takes precedence. 
12;;;
13;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
14;;;
15;;;   The LLGPL is also available online at
16;;;   http://opensource.franz.com/preamble.html
17
18(in-package "CCL")
19
20(require 'systems)
21
22(defparameter *sysdef-modules*
23  '(systems compile-ccl))
24
25(defparameter *level-1-modules*
26  '(level-1
27    l1-cl-package
28    l1-boot-1 l1-boot-2 l1-boot-3
29    l1-utils l1-init l1-symhash l1-numbers l1-aprims 
30    l1-sort l1-dcode l1-clos-boot l1-clos
31    l1-unicode l1-streams l1-files l1-io 
32    l1-format l1-readloop l1-reader
33    l1-sysio l1-pathnames l1-events
34    l1-boot-lds  l1-readloop-lds 
35    l1-lisp-threads  l1-application l1-processes
36    l1-typesys sysutils l1-error-system
37    l1-error-signal version l1-callbacks
38    l1-sockets linux-files
39    ))
40
41(defparameter *compiler-modules*
42  '(nx optimizers dll-node arch vreg vinsn 
43    reg subprims  backend nx2))
44
45
46(defparameter *ppc-compiler-modules*
47  '(ppc32-arch
48    ppc64-arch
49    ppc-arch
50    ppcenv
51    ppc-asm
52    risc-lap
53    ppc-lap
54    ppc-backend
55))
56
57(defparameter *x86-compiler-modules*
58  '(x8632-arch
59    x8664-arch
60    x86-arch
61    x8632env
62    x8664env
63    x86-asm
64    x86-lap
65    x86-backend
66))
67
68(defparameter *ppc32-compiler-backend-modules*
69  '(ppc32-backend ppc32-vinsns))
70
71(defparameter *ppc64-compiler-backend-modules*
72  '(ppc64-backend ppc64-vinsns))
73
74
75(defparameter *ppc-compiler-backend-modules*
76  '(ppc2))
77
78
79(defparameter *x8632-compiler-backend-modules*
80  '(x8632-backend x8632-vinsns))
81
82(defparameter *x8664-compiler-backend-modules*
83  '(x8664-backend x8664-vinsns))
84
85(defparameter *x86-compiler-backend-modules*
86  '(x862))
87
88
89
90
91(defparameter *ppc-xload-modules* '(xppcfasload xfasload heap-image ))
92(defparameter *x8632-xload-modules* '(xx8632fasload xfasload heap-image ))
93(defparameter *x8664-xload-modules* '(xx8664fasload xfasload heap-image ))
94
95
96;;; Not too OS-specific.
97(defparameter *ppc-xdev-modules* '(ppc-lapmacros ))
98(defparameter *x86-xdev-modules* '(x86-lapmacros ))
99
100(defun target-xdev-modules (&optional (target
101                                       (backend-target-arch-name
102                                        *host-backend*)))
103  (case target
104    ((:ppc32 :ppc64) *ppc-xdev-modules*)
105    ((:x8632 :x8664) *x86-xdev-modules*)))
106
107(defun target-xload-modules (&optional (target
108                                        (backend-target-arch-name *host-backend*)))
109  (case target
110    ((:ppc32 :ppc64) *ppc-xload-modules*)
111    (:x8632 *x8632-xload-modules*)
112    (:x8664 *x8664-xload-modules*)))
113
114
115
116
117
118
119(defparameter *env-modules*
120  '(hash backquote lispequ  level-2 macros
121    defstruct-macros lists chars setf setf-runtime
122    defstruct defstruct-lds 
123    foreign-types
124    db-io
125    nfcomp
126    ))
127
128(defun target-env-modules (&optional (target
129                                      (backend-name *host-backend*)))
130  (append *env-modules*
131          (list
132           (ecase target
133             (:linuxppc32 'ffi-linuxppc32)
134             (:darwinppc32 'ffi-darwinppc32)
135             (:darwinppc64 'ffi-darwinppc64)
136             (:linuxppc64 'ffi-linuxppc64)
137             (:darwinx8632 'ffi-darwinx8632)
138             (:linuxx8664 'ffi-linuxx8664)
139             (:darwinx8664 'ffi-darwinx8664)
140             (:freebsdx8664 'ffi-freebsdx8664)
141             (:solarisx8664 'ffi-solarisx8664)
142             (:win64 'ffi-win64)
143             (:linuxx8632 'ffi-linuxx8632)
144             (:win32 'ffi-win32)
145             (:solarisx8632 'ffi-solarisx8632)
146             (:freebsdx8632 'ffi-freebsdx8632)))))
147
148
149(defun target-compiler-modules (&optional (target
150                                           (backend-target-arch-name
151                                            *host-backend*)))
152  (case target
153    (:ppc32 (append *ppc-compiler-modules*
154                    *ppc32-compiler-backend-modules*
155                    *ppc-compiler-backend-modules*))
156    (:ppc64 (append *ppc-compiler-modules*
157                    *ppc64-compiler-backend-modules*
158                    *ppc-compiler-backend-modules*))
159    (:x8632 (append *x86-compiler-modules*
160                    *x8632-compiler-backend-modules*
161                    *x86-compiler-backend-modules*))
162    (:x8664 (append *x86-compiler-modules*
163                    *x8664-compiler-backend-modules*
164                    *x86-compiler-backend-modules*))))
165
166(defparameter *other-lib-modules*
167  '(streams pathnames backtrace
168    apropos
169    numbers 
170    dumplisp   source-files))
171
172(defun target-other-lib-modules (&optional (target
173                                            (backend-target-arch-name
174                                             *host-backend*)))
175  (append *other-lib-modules*
176          (case target
177            ((:ppc32 :ppc64) '(ppc-backtrace ppc-disassemble))
178            ((:x8632 :x8664) '(x86-backtrace x86-disassemble x86-watch)))))
179         
180
181(defun target-lib-modules (&optional (backend-name
182                                      (backend-name *host-backend*)))
183  (let* ((backend (or (find-backend backend-name) *host-backend*))
184         (arch-name (backend-target-arch-name backend)))
185    (append (target-env-modules backend-name) (target-other-lib-modules arch-name))))
186
187
188(defparameter *code-modules*
189  '(encapsulate
190    read misc  arrays-fry
191    sequences sort 
192    method-combination
193    case-error pprint 
194    format time 
195;        eval step
196    backtrace-lds  ccl-export-syms prepare-mcl-environment))
197
198
199
200(defparameter *aux-modules*
201  '(number-macros number-case-macro
202    loop
203    runtime
204    mcl-compat
205    arglist
206    edit-callers
207    describe
208    cover
209    leaks
210    core-files
211    dominance
212    asdf
213    defsystem
214    jp-encode
215    ))
216
217
218
219
220
221
222
223(defun target-level-1-modules (&optional (target (backend-name *host-backend*)))
224  (append *level-1-modules*
225          (case target
226            ((:linuxppc32 :darwinppc32 :linuxppc64 :darwinppc64)
227             '(ppc-error-signal ppc-trap-support
228               ppc-threads-utils ppc-callback-support))
229            ((:linuxx8664 :freebsdx8664 :darwinx8664 :solarisx8664
230                          :darwinx8632 :win64  :linuxx8632 :win32 :solarisx8632
231                          :freebsdx8632)
232             '(x86-error-signal x86-trap-support
233               x86-threads-utils x86-callback-support)))))
234
235
236;;; Needed to cross-dump an image
237
238
239(unless (fboundp 'xload-level-0)
240  (%fhave 'xload-level-0
241          #'(lambda (&rest rest)
242              (in-development-mode
243               (require-modules (target-xload-modules)))
244              (apply 'xload-level-0 rest))))
245
246(defun find-module (module &optional (target (backend-name *host-backend*))  &aux data fasl sources)
247  (if (setq data (assoc module *ccl-system*))
248    (let* ((backend (or (find-backend target) *host-backend*)))
249      (setq fasl (cadr data) sources (caddr data))     
250      (setq fasl (merge-pathnames (backend-target-fasl-pathname
251                                   backend) fasl))
252      (values fasl (if (listp sources) sources (list sources))))
253    (error "Module ~S not defined" module)))
254
255;compile if needed.
256(defun target-compile-modules (modules target force-compile)
257  (if (not (listp modules)) (setq modules (list modules)))
258  (in-development-mode
259   (dolist (module modules t)
260     (multiple-value-bind (fasl sources) (find-module module target)
261      (if (needs-compile-p fasl sources force-compile)
262        (progn
263          (require'nfcomp)
264          (compile-file (car sources)
265                        :output-file fasl
266                        :verbose t
267                        :target target)))))))
268
269
270(defun needs-compile-p (fasl sources force-compile)
271  (if fasl
272    (if (eq force-compile t)
273      t
274      (if (not (probe-file fasl))
275        t
276        (let ((fasldate (file-write-date fasl)))
277          (if (if (integerp force-compile) (> force-compile fasldate))
278            t
279            (dolist (source sources nil)
280              (if (> (file-write-date source) fasldate)
281                (return t)))))))))
282
283
284
285;;;compile if needed, load if recompiled.
286
287(defun update-modules (modules &optional force-compile)
288  (if (not (listp modules)) (setq modules (list modules)))
289  (in-development-mode
290   (dolist (module modules t)
291     (multiple-value-bind (fasl sources) (find-module module)
292       (if (needs-compile-p fasl sources force-compile)
293         (progn
294           (require'nfcomp)
295           (let* ((*warn-if-redefine* nil))
296             (compile-file (car sources) :output-file fasl :verbose t :load t))
297           (provide module)))))))
298
299(defun compile-modules (modules &optional force-compile)
300  (target-compile-modules modules (backend-name *host-backend*) force-compile)
301)
302
303(defun compile-ccl (&optional force-compile)
304  (with-compilation-unit ()
305    (update-modules *sysdef-modules* force-compile)
306    (update-modules 'nxenv force-compile)
307    (update-modules *compiler-modules* force-compile)
308    (update-modules (target-compiler-modules) force-compile)
309    (update-modules (target-xdev-modules) force-compile)
310    (update-modules (target-xload-modules)  force-compile)
311    (let* ((env-modules (target-env-modules))
312           (other-lib (target-other-lib-modules)))
313      (require-modules env-modules)
314      (update-modules env-modules force-compile)
315      (compile-modules (target-level-1-modules)  force-compile)
316      (update-modules other-lib force-compile)
317      (require-modules other-lib)
318      (require-update-modules *code-modules* force-compile))
319    (compile-modules *aux-modules* force-compile)))
320
321
322
323;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
324
325(defun require-env (&optional force-load)
326  (require-modules  (target-env-modules)
327                   force-load))
328
329(defun compile-level-1 (&optional force-compile)
330  (require-env)
331  (compile-modules (target-level-1-modules (backend-name *host-backend*))
332                   force-compile))
333
334
335
336
337
338(defun compile-lib (&optional force-compile)
339  (compile-modules (target-lib-modules)
340                   force-compile))
341
342(defun compile-code (&optional force-compile)
343  (compile-modules *code-modules* force-compile))
344
345
346;Compile but don't load
347
348(defun xcompile-ccl (&optional force)
349  (with-compilation-unit ()
350    (compile-modules *sysdef-modules* force)
351    (compile-modules 'nxenv force)
352    (compile-modules *compiler-modules* force)
353    (compile-modules (target-compiler-modules) force)
354    (compile-modules (target-xdev-modules) force)
355    (compile-modules (target-xload-modules)  force)
356    (compile-modules (target-env-modules) force)
357    (compile-modules (target-level-1-modules) force)
358    (compile-modules (target-other-lib-modules) force)
359    (compile-modules *code-modules* force)
360    (compile-modules *aux-modules* force)))
361
362(defun require-update-modules (modules &optional force-compile)
363  (if (not (listp modules)) (setq modules (list modules)))
364  (in-development-mode
365    (dolist (module modules)
366    (require-modules module)
367    (update-modules module force-compile))))
368
369
370(defun target-xcompile-ccl (target &optional force)
371  (require-update-modules *sysdef-modules* force) ;in the host
372  (let* ((backend (or (find-backend target) *target-backend*))
373         (arch (backend-target-arch-name backend)))
374    (target-compile-modules 'nxenv target force)
375    (target-compile-modules *compiler-modules* target force)
376    (target-compile-modules (target-compiler-modules arch) target force)
377    (target-compile-modules (target-level-1-modules target) target force)
378    (target-compile-modules (target-lib-modules target) target force)
379    (target-compile-modules *sysdef-modules* target force)
380    (target-compile-modules *aux-modules* target force)
381    (target-compile-modules *code-modules* target force)
382    (target-compile-modules (target-xdev-modules arch) target force)))
383
384(defun cross-compile-ccl (target &optional force)
385  (with-cross-compilation-target (target)
386    (let* ((*target-backend* (find-backend target)))
387      (target-xcompile-ccl target force))))
388
389
390(defun require-module (module force-load)
391  (multiple-value-bind (fasl source) (find-module module)
392      (setq source (car source))
393      (if (if fasl (probe-file fasl))
394        (if force-load
395          (progn
396            (load fasl)
397            (provide module))
398          (require module fasl))
399        (if (probe-file source)
400          (progn
401            (if fasl (format t "~&Can't find ~S so requiring ~S instead"
402                             fasl source))
403            (if force-load
404              (progn
405                (load source)
406                (provide module))
407              (require module source)))
408          (error "Can't find ~S or ~S" fasl source)))))
409
410(defun require-modules (modules &optional force-load)
411  (if (not (listp modules)) (setq modules (list modules)))
412  (let ((*package* (find-package :ccl)))
413    (dolist (m modules t)
414      (require-module m force-load))))
415
416
417(defun target-xcompile-level-1 (target &optional force)
418  (target-compile-modules (target-level-1-modules target) target force))
419
420(defun standard-boot-image-name (&optional (target (backend-name *host-backend*)))
421  (ecase target
422    (:darwinppc32 "ppc-boot.image")
423    (:linuxppc32 "ppc-boot")
424    (:darwinppc64 "ppc-boot64.image")
425    (:linuxppc64 "ppc-boot64")
426    (:darwinx8632 "x86-boot32.image")
427    (:linuxx8664 "x86-boot64")
428    (:freebsdx8664 "fx86-boot64")
429    (:darwinx8664 "x86-boot64.image")
430    (:solarisx8664 "sx86-boot64")
431    (:win64 "wx86-boot64.image")
432    (:linuxx8632 "x86-boot32")
433    (:win32 "wx86-boot32.image")
434    (:solarisx8632 "sx86-boot32")
435    (:freebsdx8632 "fx86-boot32")))
436
437(defun standard-kernel-name (&optional (target (backend-name *host-backend*)))
438  (ecase target
439    (:darwinppc32 "dppccl")
440    (:linuxppc32 "ppccl")
441    (:darwinppc64 "dppccl64")
442    (:darwinx8632 "dx86cl")
443    (:linuxppc64 "ppccl64")
444    (:linuxx8664 "lx86cl64")
445    (:freebsdx8664 "fx86cl64")
446    (:darwinx8664 "dx86cl64")
447    (:solarisx8664 "sx86cl64")
448    (:win64 "wx86cl64.exe")
449    (:linuxx8632 "lx86cl")
450    (:win32 "wx86cl.exe")
451    (:solarisx8632 "sx86cl")
452    (:freebsdx8632 "fx86cl")))
453
454(defun standard-image-name (&optional (target (backend-name *host-backend*)))
455  (concatenate 'string (pathname-name (standard-kernel-name target)) ".image"))
456
457(defun kernel-build-directory (&optional (target (backend-name *host-backend*)))
458  (ecase target
459    (:darwinppc32 "darwinppc")
460    (:linuxppc32 "linuxppc")
461    (:darwinppc64 "darwinppc64")
462    (:linuxppc64 "linuxppc64")
463    (:darwinx8632 "darwinx8632")
464    (:linuxx8664 "linuxx8664")
465    (:freebsdx8664 "freebsdx8664")
466    (:darwinx8664 "darwinx8664")
467    (:solarisx8664 "solarisx64")
468    (:win64 "win64")
469    (:linuxx8632 "linuxx8632")
470    (:win32 "win32")
471    (:solarisx8632 "solarisx86")
472    (:freebsdx8632 "freebsdx8632")))
473
474;;; If we distribute (e.g.) 32- and 64-bit versions for the same
475;;; machine and OS in the same svn directory, return the name of the
476;;; peer backend, or NIL. For example., the peer of :linuxppc64 is
477;;; :linuxppc32.  Note that this may change over time.
478;;; Return NIL if the concept doesn't apply.
479(defun peer-platform (&optional (target (backend-name *host-backend*)))
480  (let* ((pairs '((:darwinppc32 . :darwinppc64)
481                  (:linuxppc32 . :linuxppc64)
482                  (:darwinx8632 . :darwinx8664)
483                  (:linuxx8632 . :linuxx8664)
484                  (:win32 . :win64)
485                  (:solarisx8632 . :solarisx8664)
486                  (:freebsdx8632 . :freebsdx8664))))
487    (or (cdr (assoc target pairs))
488        (car (rassoc target pairs)))))
489
490(defun make-program (&optional (target (backend-name *host-backend*)))
491  ;; The Solaris "make" program is too clever to understand -C, so
492  ;; use GNU make (installed as "gmake").
493  (case target
494    ((:solarisx8664 :solarisx8632) "gmake")
495    (t "make")))
496
497
498(defun describe-external-process-failure (proc reminder)
499  "If it appears that the external-process PROC failed in some way,
500try to return a string that describes that failure.  If it seems
501to have succeeded or if we can't tell why it failed, return NIL.
502This is mostly intended to describe process-creation/fork/exec failures,
503not runtime errors reported by a successfully created process."
504  (multiple-value-bind (status exit-code)
505      (external-process-status proc)
506    (let* ((procname (car (external-process-args proc)))
507           (string
508            (case status
509              (:error
510               (%strerror exit-code))
511              #-windows-target
512              (:exited
513               (when(= exit-code #$EX_OSERR)
514                 "generic OS error in fork/exec")))))
515      (when string
516        (format nil "Error executing ~a: ~a~&~a" procname string reminder)))))
517
518(defparameter *known-optional-features* '(:count-gf-calls :monitor-futex-wait :unique-dcode))
519(defvar *build-time-optional-features* nil)
520(defvar *ccl-save-source-locations* :no-text)
521
522(defun rebuild-ccl (&key update full clean kernel force (reload t) exit
523                    reload-arguments verbose optional-features
524                    (save-source-locations *ccl-save-source-locations*)
525                    (allow-constant-redefinition nil allow-constant-redefinition-p))
526  (let* ((*build-time-optional-features* (intersection *known-optional-features* optional-features))
527         (*features* (append *build-time-optional-features* *features*))
528         (*save-source-locations* save-source-locations))
529    (when *build-time-optional-features*
530      (setq full t))
531    (when full
532      (setq clean t kernel t reload t))
533
534    (when update
535      (multiple-value-bind (changed conflicts new-binaries)
536          (update-ccl :verbose (not (eq update :quiet)))
537        (declare (ignore changed conflicts))
538        (when new-binaries
539          (format t "~&There are new bootstrapping binaries.  Please restart
540the lisp and run REBUILD-CCL again.")
541          (return-from rebuild-ccl nil))))
542    (when (or clean force)
543      ;; for better bug reports...
544      (format t "~&Rebuilding ~a using ~a"
545              (lisp-implementation-type)
546              (lisp-implementation-version))
547          (unless allow-constant-redefinition-p
548      (when (or force clean update)
549        (setq allow-constant-redefinition t))))
550    (let* ((cd (current-directory))
551           (*cerror-on-constant-redefinition* (not allow-constant-redefinition ))
552           (*warn-if-redefine-kernel* nil))
553      (unwind-protect
554           (progn
555             (setf (current-directory) "ccl:")
556             (when clean
557               (dolist (f (directory
558                           (merge-pathnames
559                            (make-pathname :name :wild
560                                           :type (pathname-type *.fasl-pathname*))
561                            "ccl:**;")))
562                 (delete-file f)))
563             (when kernel
564               (when (or clean force)
565                 ;; Do a "make -k clean".
566                 (run-program "make"
567                              (list "-k"
568                                    "-C"
569                                    (format nil "lisp-kernel/~a"
570                                            (kernel-build-directory))
571                                    "clean")))
572               (format t "~&;Building lisp-kernel ...")
573               (with-output-to-string (s)
574                 (let* ((proc (run-program (make-program)
575                                           (list "-k" "-C" 
576                                                 (format nil "lisp-kernel/~a"
577                                                         (kernel-build-directory))
578                                                 "-j"
579                                                           
580                                                 (format nil "~d" (1+ (cpu-count))))
581                                           :output s
582                                           :error :output)))
583                   (multiple-value-bind (status exit-code)
584                       (external-process-status proc)
585                     (if (and (eq :exited status) (zerop exit-code))
586                       (progn
587                         (format t "~&;Kernel built successfully.")
588                         (when verbose
589                           (format t "~&;kernel build output:~%~a"
590                                   (get-output-stream-string s)))
591                         (sleep 1))
592                       (error "Error(s) during kernel compilation.~%~a"
593                              (or
594                               (describe-external-process-failure
595                                proc
596                                "Developer tools may not be installed correctly.")
597                               (get-output-stream-string s))))))))
598             (compile-ccl (not (null force)))
599             (if force (xload-level-0 :force) (xload-level-0))
600             (when reload
601               (with-input-from-string (cmd (format nil
602                                              "(save-application ~s)"
603                                              (standard-image-name)))
604                 (with-output-to-string (output)
605                   (multiple-value-bind (status exit-code)
606                       (external-process-status
607                        (run-program
608                         (format nil "./~a" (standard-kernel-name))
609                         (list* "--image-name" (standard-boot-image-name)
610                                "--batch"
611                                reload-arguments)
612                         :input cmd
613                         :output output
614                         :error output))
615                     (if (and (eq status :exited)
616                              (eql exit-code 0))
617                       (progn
618                         (format t "~&;Wrote heap image: ~s"
619                                 (truename (format nil "ccl:~a"
620                                                   (standard-image-name))))
621                         (when verbose
622                           (format t "~&;Reload heap image output:~%~a"
623                                   (get-output-stream-string output))))
624                       (error "Errors (~s ~s) reloading boot image:~&~a"
625                              status exit-code
626                              (get-output-stream-string output)))))))
627             (when exit
628               (quit)))
629        (setf (current-directory) cd)))))
630                                                 
631               
632(defun create-interfaces (dirname &key target populate-arg)
633  (let* ((backend (if target (find-backend target) *target-backend*))
634         (*default-pathname-defaults* nil)
635         (ftd (backend-target-foreign-type-data backend))
636         (d (use-interface-dir dirname ftd))
637         (populate (merge-pathnames "C/populate.sh"
638                                    (merge-pathnames
639                                     (interface-dir-subdir d)
640                                     (ftd-interface-db-directory ftd))))
641         (cdir (make-pathname :directory (pathname-directory (translate-logical-pathname populate))))
642         (args (list "-c"
643                     (format nil "cd ~a && /bin/sh ~a ~@[~a~]"
644                             (native-translated-namestring cdir)
645                             (native-translated-namestring populate)
646                             populate-arg))))
647    (format t "~&;[Running interface translator via ~s to produce .ffi file(s) from headers]~&" populate)
648    (force-output t)
649    (multiple-value-bind (status exit-code)
650        (external-process-status
651         (run-program "/bin/sh" args :output t))
652      (if (and (eq status :exited)
653               (eql exit-code 0))
654        (let* ((f 'parse-standard-ffi-files))
655          (require "PARSE-FFI")
656          (format t "~%~%;[Parsing .ffi files; may create new .cdb files for ~s]" dirname)
657          (funcall f dirname target)
658          (format t "~%~%;[Parsing .ffi files again to resolve forward-referenced constants]")
659          (funcall f dirname target))))))
660
661(defun update-ccl (&key (verbose t))
662  (let* ((changed ())
663         (new-binaries ())
664         (conflicts ()))
665    (with-output-to-string (out)
666      (with-preserved-working-directory ("ccl:")                     
667        (when verbose (format t "~&;Running 'svn update'."))
668        (multiple-value-bind (status exit-code)
669            (external-process-status
670             (run-program *svn-program* '("update" "--non-interactive") :output out :error t))
671          (when verbose (format t "~&;'svn update' complete."))
672          (if (not (and (eq status :exited)
673                        (eql exit-code 0)))
674            (error "Running \"svn update\" produced exit status ~s, code ~s." status exit-code)
675            (let* ((sout (get-output-stream-string out))
676                   (added ())
677                   (deleted ())
678                   (updated ())
679                   (merged ())
680                   (binaries (list (standard-kernel-name) (standard-image-name )))
681                   (peer (peer-platform)))
682              (when peer
683                (push (standard-kernel-name peer) binaries)
684                (push (standard-image-name peer) binaries))
685              (flet ((svn-revert (string)
686                       (multiple-value-bind (status exit-code)
687                           (external-process-status (run-program *svn-program* `("revert" ,string)))
688                         (when (and (eq status :exited) (eql exit-code 0))
689                           (setq conflicts (delete string conflicts :test #'string=))
690                           (push string updated)))))
691                (with-input-from-string (in sout)
692                  (do* ((line (read-line in nil nil) (read-line in nil nil)))
693                       ((null line))
694                    (when (and (> (length line) 2)
695                               (eql #\space (schar line 1)))
696                      (let* ((path (string-trim " " (subseq line 2))))
697                        (case (schar line 0)
698                          (#\A (push path added))
699                          (#\D (push path deleted))
700                          (#\U (push path updated))
701                          (#\G (push path merged))
702                          (#\C (push path conflicts)))))))
703                ;; If the kernel and/or image conflict, use "svn revert"
704                ;; to replace the working copies with the (just updated)
705                ;; repository versions.
706                (setq changed (if (or added deleted updated merged conflicts) t))
707                (dolist (f binaries)
708                  (cond ((member f conflicts :test #'string=)
709                         (svn-revert f)
710                         (setq new-binaries t))
711                        ((or (member f updated :test #'string=)
712                             (member f merged :test #'string=))
713                         (setq new-binaries t))))
714
715                ;; If there are any remaining conflicts, offer
716                ;; to revert them.
717                (when conflicts
718                  (with-preserved-working-directory ()
719                    (cerror "Discard local changes to these files (using 'svn revert')."
720                            "'svn update' was unable to merge local changes to the following file~p with the updated versions:~{~&~s~}" (length conflicts) conflicts)
721                    (dolist (c (copy-list conflicts))
722                      (svn-revert c))))
723                ;; Report other changes, if verbose.
724                (when (and verbose
725                           (or added deleted updated merged conflicts))
726                  (format t "~&;Changes from svn update:")
727                  (flet ((show-changes (herald files)
728                           (when files
729                             (format t "~&; ~a:~{~&;  ~a~}"
730                                     herald files))))
731                    (show-changes "Conflicting files" conflicts)
732                    (show-changes "New files/directories" added)
733                    (show-changes "Deleted files/directories" deleted)
734                    (show-changes "Updated files" updated)
735                    (show-changes "Files with local changes, successfully merged" merged)))))))))
736    (values changed conflicts new-binaries)))
737
738(defmacro with-preserved-working-directory ((&optional dir) &body body)
739  (let ((wd (gensym)))
740    `(let ((,wd (mac-default-directory)))
741       (unwind-protect
742            (progn 
743              ,@(when dir `((cwd ,dir)))
744              ,@body)
745         (cwd ,wd)))))
746
747(defun ensure-tests-loaded (&key force update ansi ccl)
748  (unless (and (find-package "REGRESSION-TEST") (not force))
749    (if (probe-file "ccl:tests;ansi-tests;")
750      (when update
751        (cwd "ccl:tests;")
752        (run-program *svn-program* '("update")))
753      (let* ((repo (svn-repository))
754             (url (format nil "~a/trunk/tests" repo))
755             (s (make-string-output-stream)))
756        (if (null repo)
757          (error "Can't determine svn repository.  ccl directory is ~s"
758                 (ccl-directory))
759          (progn
760            (format t "~&Using ~a to check out test suite from ~a ~
761                       into ccl:tests;~%" *svn-program* url)
762            (cwd "ccl:")
763            (multiple-value-bind (status exit-code)
764              (external-process-status
765               (run-program *svn-program* (list "checkout" url "tests")
766                            :output s :error s))
767              (unless (and (eq status :exited)
768                           (eql exit-code 0))
769                (error "Failed to check out test suite: ~%~a"
770                       (get-output-stream-string s))))))))
771    (cwd "ccl:tests;ansi-tests;")
772    (run-program "make" '("-k" "clean"))
773    (map nil 'delete-file (directory "*.*fsl"))
774    ;; Muffle the typecase "clause ignored" warnings, since there is really nothing we can do about
775    ;; it without making the test suite non-portable across platforms...
776    (handler-bind ((warning (lambda (c)
777                              (when (let ((w (or (and (typep c 'compiler-warning)
778                                                      (eq (compiler-warning-warning-type c) :program-error)
779                                                      (car (compiler-warning-args c)))
780                                                 c)))
781                                      (and (typep w 'simple-warning)
782                                           (or 
783                                            (string-equal
784                                             (simple-condition-format-control w)
785                                             "Clause ~S ignored in ~S form - shadowed by ~S .")
786                                            ;; Might as well ignore these as well, they're intentional.
787                                            (string-equal
788                                             (simple-condition-format-control w)
789                                             "Duplicate keyform ~s in ~s statement."))))
790                                (muffle-warning c)))))
791      ;; This loads the infrastructure
792      (load "ccl:tests;ansi-tests;gclload1.lsp")
793      ;; This loads the actual tests
794      (let ((redef-var (find-symbol "*WARN-IF-REDEFINE-TEST*" :REGRESSION-TEST)))
795        (progv (list redef-var) (list (if force nil (symbol-value redef-var)))
796          (when ansi
797            (load "ccl:tests;ansi-tests;gclload2.lsp"))
798          ;; And our own tests
799          (when ccl
800            (load "ccl:tests;ansi-tests;ccl.lsp")))))))
801
802(defun test-ccl (&key force (update t) verbose (catch-errors t) (ansi t) (ccl t)
803                      optimization-settings exit)
804  (with-preserved-working-directory ()
805    (let* ((*package* (find-package "CL-USER")))
806      (ensure-tests-loaded :force force :update update :ansi ansi :ccl ccl)
807      (cwd "ccl:tests;ansi-tests;")
808      (let ((do-tests (find-symbol "DO-TESTS" "REGRESSION-TEST"))
809            (failed (find-symbol "*FAILED-TESTS*" "REGRESSION-TEST"))
810            (*print-catch-errors* nil))
811        (prog1
812            (time (funcall do-tests :verbose verbose :compile t
813                           :catch-errors catch-errors
814                           :optimization-settings (or optimization-settings '((safety 2)))))
815          ;; Clean up a little
816          (map nil #'delete-file
817               (directory (merge-pathnames *.fasl-pathname* "ccl:tests;ansi-tests;temp*"))))
818        (let ((failed-tests (symbol-value failed)))
819          (when exit
820            (quit (if failed-tests 1 0)))
821          failed-tests)))))
822
Note: See TracBrowser for help on using the repository browser.