| 1 | ;;; build-abcl.lisp | 
|---|
| 2 |  | 
|---|
| 3 | #+abcl | 
|---|
| 4 | (require 'format) | 
|---|
| 5 |  | 
|---|
| 6 | (defpackage build-abcl | 
|---|
| 7 |   (:use "COMMON-LISP") | 
|---|
| 8 |   (:export #:build-abcl #:make-dist) | 
|---|
| 9 |   #+abcl (:import-from #:extensions #:run-shell-command #:probe-directory) | 
|---|
| 10 |   #+allegro (:import-from #:excl #:probe-directory) | 
|---|
| 11 |   #+clisp (:import-from #:ext #:probe-directory) | 
|---|
| 12 |   ) | 
|---|
| 13 |  | 
|---|
| 14 | (in-package #:build-abcl) | 
|---|
| 15 |  | 
|---|
| 16 | ;; Platform detection. | 
|---|
| 17 |  | 
|---|
| 18 | (defun platform () | 
|---|
| 19 |   #-clisp | 
|---|
| 20 |   (let ((software-type (software-type))) | 
|---|
| 21 |     (cond ((search "Linux" software-type) | 
|---|
| 22 |            :linux) | 
|---|
| 23 |           ((or (search "Mac OS X" software-type) ; abcl | 
|---|
| 24 |                (search "Darwin" software-type))  ; sbcl | 
|---|
| 25 |            :darwin) | 
|---|
| 26 |           ((search "Windows" software-type) | 
|---|
| 27 |            :windows) | 
|---|
| 28 |           (t | 
|---|
| 29 |            :unknown))) | 
|---|
| 30 |   #+clisp | 
|---|
| 31 |   (cond ((member :win32 *features*) | 
|---|
| 32 |          :windows) | 
|---|
| 33 |         ((zerop (ext:run-shell-command "uname | grep -i darwin" :output nil)) | 
|---|
| 34 |          :darwin) | 
|---|
| 35 |         ((zerop (ext:run-shell-command "uname | grep -i linux" :output nil)) | 
|---|
| 36 |          :linux) | 
|---|
| 37 |         (t | 
|---|
| 38 |          :unknown))) | 
|---|
| 39 |  | 
|---|
| 40 | (defparameter *platform* (platform)) | 
|---|
| 41 |  | 
|---|
| 42 | (defparameter *file-separator-char* | 
|---|
| 43 |   (if (eq *platform* :windows) #\\ #\/)) | 
|---|
| 44 |  | 
|---|
| 45 | (defparameter *path-separator-char* | 
|---|
| 46 |   (if (eq *platform* :windows) #\; #\:)) | 
|---|
| 47 |  | 
|---|
| 48 | (defmacro with-current-directory ((directory) &body body) | 
|---|
| 49 |   `(let ((*default-pathname-defaults* ,directory) | 
|---|
| 50 |          #+clisp | 
|---|
| 51 |          (old-directory (ext:cd))) | 
|---|
| 52 |      #+clisp | 
|---|
| 53 |      (ext:cd ,directory) | 
|---|
| 54 |      (unwind-protect | 
|---|
| 55 |          (progn ,@body) | 
|---|
| 56 |        #+clisp | 
|---|
| 57 |        (ext:cd old-directory) | 
|---|
| 58 |        ))) | 
|---|
| 59 |  | 
|---|
| 60 | #+sbcl | 
|---|
| 61 | (defun run-shell-command (command &key directory (output *standard-output*)) | 
|---|
| 62 |   (when directory | 
|---|
| 63 |     (setf command (concatenate 'string | 
|---|
| 64 |                                "\\cd \"" | 
|---|
| 65 |                                (namestring (pathname directory)) | 
|---|
| 66 |                                "\" && " | 
|---|
| 67 |                                command))) | 
|---|
| 68 |   (sb-ext:process-exit-code | 
|---|
| 69 |    (sb-ext:run-program | 
|---|
| 70 |     "/bin/sh" | 
|---|
| 71 |     (list  "-c" command) | 
|---|
| 72 |     :input nil :output output))) | 
|---|
| 73 |  | 
|---|
| 74 | #+cmu | 
|---|
| 75 | (defun run-shell-command (command &key directory (output *standard-output*)) | 
|---|
| 76 |   (when directory | 
|---|
| 77 |     (setf command (concatenate 'string | 
|---|
| 78 |                                "\\cd \"" | 
|---|
| 79 |                                (namestring (pathname directory)) | 
|---|
| 80 |                                "\" && " | 
|---|
| 81 |                                command))) | 
|---|
| 82 |   (ext::process-exit-code | 
|---|
| 83 |    (ext:run-program | 
|---|
| 84 |     "/bin/sh" | 
|---|
| 85 |     (list  "-c" command) | 
|---|
| 86 |     :input nil :output output))) | 
|---|
| 87 |  | 
|---|
| 88 | #+clisp | 
|---|
| 89 | (defun run-shell-command (command &key directory (output *standard-output*)) | 
|---|
| 90 |   (declare (ignore output)) ;; FIXME | 
|---|
| 91 |   (let (status old-directory) | 
|---|
| 92 |     (when directory | 
|---|
| 93 |       (setf old-directory (ext:cd)) | 
|---|
| 94 |       (ext:cd directory)) | 
|---|
| 95 |     (unwind-protect | 
|---|
| 96 |         (setf status (ext:shell command)) | 
|---|
| 97 |       (when old-directory | 
|---|
| 98 |         (ext:cd old-directory))) | 
|---|
| 99 |     (cond ((numberp status) | 
|---|
| 100 |            status) | 
|---|
| 101 |           ((eq status t) | 
|---|
| 102 |            0) | 
|---|
| 103 |           (t | 
|---|
| 104 |            -1)))) | 
|---|
| 105 |  | 
|---|
| 106 | #+lispworks | 
|---|
| 107 | (defun run-shell-command (command &key directory (output *standard-output*)) | 
|---|
| 108 |   (when directory | 
|---|
| 109 |     (unless (eq *platform* :windows) | 
|---|
| 110 |       (setf command (concatenate 'string | 
|---|
| 111 |                                  "\\cd \"" | 
|---|
| 112 |                                  (namestring (pathname directory)) | 
|---|
| 113 |                                  "\" && " | 
|---|
| 114 |                                  command)))) | 
|---|
| 115 |   (system:call-system-showing-output command | 
|---|
| 116 |                                      :shell-type "/bin/sh" | 
|---|
| 117 |                                      :output-stream output)) | 
|---|
| 118 |  | 
|---|
| 119 | #+allegro | 
|---|
| 120 | (defun run-shell-command (command &key directory (output *standard-output*)) | 
|---|
| 121 |   (excl:run-shell-command command | 
|---|
| 122 |                           :directory directory | 
|---|
| 123 |                           :input nil | 
|---|
| 124 |                           :output #+ide nil #-ide output)) | 
|---|
| 125 |  | 
|---|
| 126 | #+openmcl | 
|---|
| 127 | (defun run-shell-command (command &key directory (output *standard-output*)) | 
|---|
| 128 |   (when directory | 
|---|
| 129 |     (setf command (concatenate 'string | 
|---|
| 130 |                                "\\cd \"" | 
|---|
| 131 |                                (namestring (pathname directory)) | 
|---|
| 132 |                                "\" && " | 
|---|
| 133 |                                command))) | 
|---|
| 134 |   (multiple-value-bind (status exitcode) | 
|---|
| 135 |       (ccl:external-process-status | 
|---|
| 136 |        (ccl:run-program | 
|---|
| 137 |         "/bin/sh" | 
|---|
| 138 |         (list  "-c" command) | 
|---|
| 139 |         :wait t :input nil :output output)) | 
|---|
| 140 |     (declare (ignore status)) | 
|---|
| 141 |     exitcode)) | 
|---|
| 142 |  | 
|---|
| 143 | #+(or sbcl cmu lispworks openmcl) | 
|---|
| 144 | (defun probe-directory (pathspec) | 
|---|
| 145 |   (let* ((truename (probe-file pathspec)) ; TRUENAME is a pathname. | 
|---|
| 146 |          (namestring (and truename (namestring truename)))) ; NAMESTRING is a string. | 
|---|
| 147 |     (and namestring | 
|---|
| 148 |          (> (length namestring) 0) | 
|---|
| 149 |          (eql (char namestring (1- (length namestring))) *file-separator-char*) | 
|---|
| 150 |          truename))) | 
|---|
| 151 |  | 
|---|
| 152 | (defparameter *build-root* | 
|---|
| 153 |   (make-pathname :device (pathname-device *load-truename*) | 
|---|
| 154 |                  :directory (pathname-directory *load-truename*))) | 
|---|
| 155 |  | 
|---|
| 156 | (defparameter *customizations-file* | 
|---|
| 157 |   (merge-pathnames "customizations.lisp" *build-root*)) | 
|---|
| 158 |  | 
|---|
| 159 | (defparameter *abcl-dir* | 
|---|
| 160 |   (merge-pathnames "src/org/armedbear/lisp/" *build-root*)) | 
|---|
| 161 |  | 
|---|
| 162 | (defparameter *jdk*           nil) | 
|---|
| 163 | (defparameter *java-compiler* nil) | 
|---|
| 164 | (defparameter *javac-options* nil) | 
|---|
| 165 | (defparameter *jikes-options* nil) | 
|---|
| 166 | (defparameter *jar*           nil) | 
|---|
| 167 |  | 
|---|
| 168 | (defvar *classpath*) | 
|---|
| 169 | (defvar *java*) | 
|---|
| 170 | (defvar *java-compiler-options*) | 
|---|
| 171 | (defvar *java-compiler-command-line-prefix*) | 
|---|
| 172 |  | 
|---|
| 173 | (defun initialize-build () | 
|---|
| 174 |   (setf *jdk*           nil | 
|---|
| 175 |         *java-compiler* nil | 
|---|
| 176 |         *javac-options* nil | 
|---|
| 177 |         *jikes-options* nil | 
|---|
| 178 |         *jar*           nil) | 
|---|
| 179 |   (load *customizations-file*) | 
|---|
| 180 |   (setf *java* (probe-file (merge-pathnames (if (eq *platform* :windows) | 
|---|
| 181 |                                                 "bin\\java.exe" | 
|---|
| 182 |                                                 "bin/java") | 
|---|
| 183 |                                             *jdk*))) | 
|---|
| 184 |   (unless *java* | 
|---|
| 185 |     (error "Can't find Java executable.")) | 
|---|
| 186 |   (unless *java-compiler* | 
|---|
| 187 |     (setf *java-compiler* (merge-pathnames (if (eq *platform* :windows) | 
|---|
| 188 |                                                "bin/javac.exe" | 
|---|
| 189 |                                                "bin/javac") | 
|---|
| 190 |                                            *jdk*))) | 
|---|
| 191 |   (unless *jar* | 
|---|
| 192 |     (setf *jar* (merge-pathnames (if (eq *platform* :windows) | 
|---|
| 193 |                                      "bin/jar.exe" | 
|---|
| 194 |                                      "bin/jar") | 
|---|
| 195 |                                  *jdk*))) | 
|---|
| 196 |   (let ((classpath-components (list (merge-pathnames "src" *build-root*) | 
|---|
| 197 |                                     (if (eq *platform* :darwin) | 
|---|
| 198 |                                         #p"/System/Library/Frameworks/JavaVM.framework/Classes/classes.jar" | 
|---|
| 199 |                                         (merge-pathnames "jre/lib/rt.jar" *jdk*))))) | 
|---|
| 200 |     (setf *classpath* | 
|---|
| 201 |           (with-output-to-string (s) | 
|---|
| 202 |             (do* ((components classpath-components (cdr components)) | 
|---|
| 203 |                   (component (car components) (car components))) | 
|---|
| 204 |                  ((null components)) | 
|---|
| 205 |               (princ (safe-namestring component) s) | 
|---|
| 206 |               (unless (null (cdr components)) | 
|---|
| 207 |                 (write-char *path-separator-char* s)))))) | 
|---|
| 208 |   (let ((prefix (concatenate 'string | 
|---|
| 209 |                              (safe-namestring *java-compiler*) | 
|---|
| 210 |                              " -classpath " *classpath*))) | 
|---|
| 211 |     (setf *java-compiler-options* | 
|---|
| 212 |           (if (string-equal (pathname-name (pathname *java-compiler*)) "jikes") | 
|---|
| 213 |               *jikes-options* | 
|---|
| 214 |               *javac-options*)) | 
|---|
| 215 |     (setf prefix | 
|---|
| 216 |           (if *java-compiler-options* | 
|---|
| 217 |               (concatenate 'string prefix " " *java-compiler-options* " ") | 
|---|
| 218 |               (concatenate 'string prefix " "))) | 
|---|
| 219 |     (setf *java-compiler-command-line-prefix* prefix))) | 
|---|
| 220 |  | 
|---|
| 221 | (defun substitute-in-string (string substitutions-alist) | 
|---|
| 222 |   (dolist (entry substitutions-alist) | 
|---|
| 223 |     (let ((index (search (car entry) string :test #'string=))) | 
|---|
| 224 |       (when index | 
|---|
| 225 |         (setf string (concatenate 'string | 
|---|
| 226 |                                   (subseq string 0 index) | 
|---|
| 227 |                                   (cdr entry) | 
|---|
| 228 |                                   (subseq string (+ index (length (car entry))))))))) | 
|---|
| 229 |   string) | 
|---|
| 230 |  | 
|---|
| 231 | (defun copy-with-substitutions (source-file target-file substitutions-alist) | 
|---|
| 232 |   (with-open-file (in source-file :direction :input) | 
|---|
| 233 |     (with-open-file (out target-file :direction :output :if-exists :supersede) | 
|---|
| 234 |       (loop | 
|---|
| 235 |         (let ((string (read-line in nil))) | 
|---|
| 236 |           (when (null string) | 
|---|
| 237 |             (return)) | 
|---|
| 238 |           (write-line (substitute-in-string string substitutions-alist) out)))))) | 
|---|
| 239 |  | 
|---|
| 240 | (defun build-javac-command-line (source-file) | 
|---|
| 241 |   (concatenate 'string | 
|---|
| 242 |                *java-compiler-command-line-prefix* | 
|---|
| 243 |                (namestring source-file))) | 
|---|
| 244 |  | 
|---|
| 245 | (defun java-compile-file (source-file) | 
|---|
| 246 |   (let ((cmdline (build-javac-command-line source-file))) | 
|---|
| 247 |     (zerop (run-shell-command cmdline :directory *abcl-dir*)))) | 
|---|
| 248 |  | 
|---|
| 249 | (defun make-classes (force batch) | 
|---|
| 250 |   (let* ((source-files | 
|---|
| 251 |           (append (with-current-directory (*abcl-dir*) | 
|---|
| 252 |                     (directory "*.java")) | 
|---|
| 253 |                   (with-current-directory ((merge-pathnames "java/awt/" *abcl-dir*)) | 
|---|
| 254 |                     (directory "*.java")))) | 
|---|
| 255 |          (to-do ())) | 
|---|
| 256 |     (if force | 
|---|
| 257 |         (setf to-do source-files) | 
|---|
| 258 |         (dolist (source-file source-files) | 
|---|
| 259 |           (let ((class-file (merge-pathnames (make-pathname :type "class" | 
|---|
| 260 |                                                             :defaults source-file)))) | 
|---|
| 261 |             (when (or (null (probe-file class-file)) | 
|---|
| 262 |                       (>= (file-write-date source-file) | 
|---|
| 263 |                           (file-write-date class-file))) | 
|---|
| 264 |               (push source-file to-do))))) | 
|---|
| 265 |     (format t "~&JDK: ~A~%" *jdk*) | 
|---|
| 266 |     (format t "Java compiler: ~A~%" *java-compiler*) | 
|---|
| 267 |     (format t "Compiler options: ~A~%~%" (if *java-compiler-options* *java-compiler-options* "")) | 
|---|
| 268 |     (finish-output) | 
|---|
| 269 |     (cond ((null to-do) | 
|---|
| 270 |            (format t "Classes are up to date.~%") | 
|---|
| 271 |            (finish-output) | 
|---|
| 272 |            t) | 
|---|
| 273 |           (t | 
|---|
| 274 |            (cond (batch | 
|---|
| 275 |                   (let* ((dir (pathname-directory *abcl-dir*)) | 
|---|
| 276 |                          (cmdline (with-output-to-string (s) | 
|---|
| 277 |                                     (princ *java-compiler-command-line-prefix* s) | 
|---|
| 278 |                                     (dolist (source-file to-do) | 
|---|
| 279 |                                       (princ | 
|---|
| 280 |                                        (if (equal (pathname-directory source-file) dir) | 
|---|
| 281 |                                            (file-namestring source-file) | 
|---|
| 282 |                                            (namestring source-file)) | 
|---|
| 283 |                                        s) | 
|---|
| 284 |                                       (princ #\space s)))) | 
|---|
| 285 |                          (status (run-shell-command cmdline :directory *abcl-dir*))) | 
|---|
| 286 |                     (zerop status))) | 
|---|
| 287 |                  (t | 
|---|
| 288 |                   (dolist (source-file to-do t) | 
|---|
| 289 |                     (unless (java-compile-file source-file) | 
|---|
| 290 |                       (format t "Build failed.~%") | 
|---|
| 291 |                       (return nil))))))))) | 
|---|
| 292 |  | 
|---|
| 293 | (defun make-jar () | 
|---|
| 294 |   (let ((*default-pathname-defaults* *build-root*) | 
|---|
| 295 |         (jar-namestring (namestring *jar*))) | 
|---|
| 296 |     (when (position #\space jar-namestring) | 
|---|
| 297 |       (setf jar-namestring (concatenate 'string "\"" jar-namestring "\""))) | 
|---|
| 298 |     (let ((substitutions-alist (acons "@JAR@" jar-namestring nil)) | 
|---|
| 299 |           (source-file (if (eq *platform* :windows) "make-jar.bat.in" "make-jar.in")) | 
|---|
| 300 |           (target-file (if (eq *platform* :windows) "make-jar.bat"    "make-jar")) | 
|---|
| 301 |           (command     (if (eq *platform* :windows) "make-jar.bat"    "sh make-jar"))) | 
|---|
| 302 |       (copy-with-substitutions source-file target-file substitutions-alist) | 
|---|
| 303 |       (let ((status (run-shell-command command :directory *build-root*))) | 
|---|
| 304 |         (unless (zerop status) | 
|---|
| 305 |           (format t "~A returned ~S~%" command status)) | 
|---|
| 306 |         status)))) | 
|---|
| 307 |  | 
|---|
| 308 | (defun do-compile-system (&key (zip t)) | 
|---|
| 309 |   (terpri) | 
|---|
| 310 |   (finish-output) | 
|---|
| 311 |   (let* ((java-namestring (safe-namestring *java*)) | 
|---|
| 312 |          status) | 
|---|
| 313 |     (cond ((eq *platform* :windows) | 
|---|
| 314 |            (with-open-file (stream | 
|---|
| 315 |                             (merge-pathnames "compile-system.bat" *build-root*) | 
|---|
| 316 |                             :direction :output | 
|---|
| 317 |                             :if-exists :supersede) | 
|---|
| 318 |              (princ java-namestring stream) | 
|---|
| 319 |              (write-string " -cp " stream) | 
|---|
| 320 |              (princ "src" stream) | 
|---|
| 321 |              (write-char #\space stream) | 
|---|
| 322 |              (write-string | 
|---|
| 323 |               (if zip | 
|---|
| 324 |                  "org.armedbear.lisp.Main --eval \"(compile-system :zip t :quit t)\"" | 
|---|
| 325 |                  "org.armedbear.lisp.Main --eval \"(compile-system :zip nil :quit t)\"") | 
|---|
| 326 |               stream) | 
|---|
| 327 |              (terpri stream)) | 
|---|
| 328 |            (setf status | 
|---|
| 329 |                  (run-shell-command "compile-system.bat" | 
|---|
| 330 |                                     :directory *build-root*))) | 
|---|
| 331 |           (t ; Linux | 
|---|
| 332 |            (let ((cmdline | 
|---|
| 333 |                   (with-output-to-string (s) | 
|---|
| 334 |                     (princ java-namestring s) | 
|---|
| 335 |                     (write-string " -cp " s) | 
|---|
| 336 |                     (princ "src" s) | 
|---|
| 337 |                     (write-char #\space s) | 
|---|
| 338 |                     (write-string | 
|---|
| 339 |                      (if zip | 
|---|
| 340 |                          "org.armedbear.lisp.Main --eval \"(compile-system :zip t :quit t)\"" | 
|---|
| 341 |                          "org.armedbear.lisp.Main --eval \"(compile-system :zip nil :quit t)\"") | 
|---|
| 342 |                      s)))) | 
|---|
| 343 |              (setf status | 
|---|
| 344 |                    (run-shell-command cmdline | 
|---|
| 345 |                                       :directory *build-root*))))) | 
|---|
| 346 |     status)) | 
|---|
| 347 |  | 
|---|
| 348 | (defun make-libabcl () | 
|---|
| 349 |   (and (let* ((javah-namestring (namestring (probe-file (merge-pathnames "bin/javah" *jdk*)))) | 
|---|
| 350 |               (command | 
|---|
| 351 |                (format nil "~A -o org/armedbear/lisp/native.h org.armedbear.lisp.Native" | 
|---|
| 352 |                        javah-namestring)) | 
|---|
| 353 |               (status | 
|---|
| 354 |                (run-shell-command command :directory (merge-pathnames "src/" *build-root*)))) | 
|---|
| 355 |          (unless (zerop status) | 
|---|
| 356 |            (format t "~A returned ~S~%" command status)) | 
|---|
| 357 |          (zerop status)) | 
|---|
| 358 |        (let* ((jdk-namestring (namestring *jdk*)) | 
|---|
| 359 |               (command | 
|---|
| 360 |                (format nil "gcc -shared -o libabcl.so -O -D_REENTRANT -fpic -I~Ainclude -I~Ainclude/~A native.c" | 
|---|
| 361 |                        jdk-namestring jdk-namestring | 
|---|
| 362 |                        (cond ((eq *platform* :linux) | 
|---|
| 363 |                               "linux") | 
|---|
| 364 |                              ((search "SunOS" (software-type)) | 
|---|
| 365 |                               "solaris") | 
|---|
| 366 |                              ((search "FreeBSD" (software-type)) | 
|---|
| 367 |                               "freebsd")))) | 
|---|
| 368 |               (status | 
|---|
| 369 |                (run-shell-command command :directory *abcl-dir*))) | 
|---|
| 370 |          (unless (zerop status) | 
|---|
| 371 |            (format t "~A returned ~S~%" command status)) | 
|---|
| 372 |          (zerop status)))) | 
|---|
| 373 |  | 
|---|
| 374 | ;; abcl/abcl.bat | 
|---|
| 375 | (defun make-launch-script () | 
|---|
| 376 |   ;; Use the -Xss4M and -Xmx256M flags so that the default launch script can be | 
|---|
| 377 |   ;; used to build sbcl. | 
|---|
| 378 |   (cond ((eq *platform* :windows) | 
|---|
| 379 |          (with-open-file (s | 
|---|
| 380 |                           (merge-pathnames "abcl.bat" *build-root*) | 
|---|
| 381 |                           :direction :output | 
|---|
| 382 |                           :if-exists :supersede) | 
|---|
| 383 |            (format s "~A -Xss4M -Xmx256M -cp \"~A;~A\" org.armedbear.lisp.Main %1 %2 %3 %4 %5 %6 %7 %8 %9~%" | 
|---|
| 384 |                    (safe-namestring *java*) | 
|---|
| 385 |                    (namestring (merge-pathnames "src" *build-root*)) | 
|---|
| 386 |                    (namestring (merge-pathnames "abcl.jar" *build-root*))))) | 
|---|
| 387 |         (t | 
|---|
| 388 |          (let ((pathname (merge-pathnames "abcl" *build-root*))) | 
|---|
| 389 |            (with-open-file (s pathname :direction :output :if-exists :supersede) | 
|---|
| 390 |              (if (eq *platform* :linux) | 
|---|
| 391 |                  ;; On Linux, set java.library.path for libabcl.so. | 
|---|
| 392 |                  (format s "#!/bin/sh~%exec ~A -Xss4M -Xmx256M -Xrs -Djava.library.path=~A -cp ~A:~A org.armedbear.lisp.Main \"$@\"~%" | 
|---|
| 393 |                          (safe-namestring *java*) | 
|---|
| 394 |                          (safe-namestring *abcl-dir*) | 
|---|
| 395 |                          (safe-namestring (merge-pathnames "src" *build-root*)) | 
|---|
| 396 |                          (safe-namestring (merge-pathnames "abcl.jar" *build-root*))) | 
|---|
| 397 |                  ;; Not Linux. | 
|---|
| 398 |                  (format s "#!/bin/sh~%exec ~A -Xss4M -Xmx256M -cp ~A:~A org.armedbear.lisp.Main \"$@\"~%" | 
|---|
| 399 |                          (safe-namestring *java*) | 
|---|
| 400 |                          (safe-namestring (merge-pathnames "src" *build-root*)) | 
|---|
| 401 |                          (safe-namestring (merge-pathnames "abcl.jar" *build-root*))))) | 
|---|
| 402 |            (run-shell-command (format nil "chmod +x ~A" (safe-namestring pathname)) | 
|---|
| 403 |                               :directory *build-root*))))) | 
|---|
| 404 |  | 
|---|
| 405 | (defun build-stamp () | 
|---|
| 406 |   (multiple-value-bind | 
|---|
| 407 |       (second minute hour date month year day daylight-p zone) | 
|---|
| 408 |       (decode-universal-time (get-universal-time)) | 
|---|
| 409 |     (declare (ignore daylight-p)) | 
|---|
| 410 |     (setf day (nth day '("Mon" "Tue" "Wed" "Thu" "Fri" "Sat" "Sun"))) | 
|---|
| 411 |     (setf month (nth (1- month) '("Jan" "Feb" "Mar" "Apr" "May" "Jun" | 
|---|
| 412 |                                   "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"))) | 
|---|
| 413 |     (setf zone (* zone 100)) ;; FIXME | 
|---|
| 414 |     (format nil "~A ~A ~D ~D ~2,'0D:~2,'0D:~2,'0D -~4,'0D" | 
|---|
| 415 |             day month date year hour minute second zone))) | 
|---|
| 416 |  | 
|---|
| 417 | (defun make-build-stamp () | 
|---|
| 418 |   (with-open-file (s | 
|---|
| 419 |                    (merge-pathnames (make-pathname :name "build" | 
|---|
| 420 |                                                    :defaults *abcl-dir*)) | 
|---|
| 421 |                    :direction :output | 
|---|
| 422 |                    :if-exists :supersede) | 
|---|
| 423 |     (format s "~A" (build-stamp)))) | 
|---|
| 424 |  | 
|---|
| 425 | (defun delete-files (pathnames) | 
|---|
| 426 |   (dolist (pathname pathnames) | 
|---|
| 427 |     (let ((truename (probe-file pathname))) | 
|---|
| 428 |       (when truename | 
|---|
| 429 |         (delete-file truename))))) | 
|---|
| 430 |  | 
|---|
| 431 | (defun clean () | 
|---|
| 432 |   (with-current-directory (*build-root*) | 
|---|
| 433 |     (delete-files (list "abcl.jar"))) | 
|---|
| 434 |   (with-current-directory (*abcl-dir*) | 
|---|
| 435 |     (delete-files (directory "*.class")) | 
|---|
| 436 |     (delete-files (directory "*.abcl")) | 
|---|
| 437 |     (delete-files (directory "*.cls")) | 
|---|
| 438 |     (delete-files '("native.h" "libabcl.so" "build"))) | 
|---|
| 439 |   (with-current-directory ((merge-pathnames "java/awt/" *abcl-dir*)) | 
|---|
| 440 |     (delete-files (directory "*.class")))) | 
|---|
| 441 |  | 
|---|
| 442 | (defun safe-namestring (pathname) | 
|---|
| 443 |   (let ((string (namestring pathname))) | 
|---|
| 444 |     (when (position #\space string) | 
|---|
| 445 |       (setf string (concatenate 'string "\"" string "\""))) | 
|---|
| 446 |     string)) | 
|---|
| 447 |  | 
|---|
| 448 | (defun build-abcl (&key force | 
|---|
| 449 |                         (batch t) | 
|---|
| 450 |                         compile-system | 
|---|
| 451 |                         jar | 
|---|
| 452 |                         clean | 
|---|
| 453 |                         libabcl | 
|---|
| 454 |                         full) | 
|---|
| 455 |   (let ((start (get-internal-real-time))) | 
|---|
| 456 |  | 
|---|
| 457 |     #+lispworks | 
|---|
| 458 |     (when (eq *platform* :windows) | 
|---|
| 459 |       (setf batch nil)) | 
|---|
| 460 |  | 
|---|
| 461 |     (initialize-build) | 
|---|
| 462 |     (format t "~&Platform: ~A~%" | 
|---|
| 463 |             (case *platform* | 
|---|
| 464 |               (:windows "Windows") | 
|---|
| 465 |               (:linux   "Linux") | 
|---|
| 466 |               (:darwin  "Mac OS X") | 
|---|
| 467 |               (t        (software-type)))) | 
|---|
| 468 |     (finish-output) | 
|---|
| 469 |     ;; clean | 
|---|
| 470 |     (when clean | 
|---|
| 471 |       (clean)) | 
|---|
| 472 |     ;; classes | 
|---|
| 473 |     (unless (make-classes force batch) | 
|---|
| 474 |       (format t "Build failed.~%") | 
|---|
| 475 |       (return-from build-abcl nil)) | 
|---|
| 476 |     ;; COMPILE-SYSTEM | 
|---|
| 477 |     (when (or full compile-system) | 
|---|
| 478 |       (let* ((zip    (if (or full jar) nil t)) | 
|---|
| 479 |              (status (do-compile-system :zip zip))) | 
|---|
| 480 |         (unless (zerop status) | 
|---|
| 481 |           (format t "Build failed.~%") | 
|---|
| 482 |           (return-from build-abcl nil)))) | 
|---|
| 483 |     ;; abcl.jar | 
|---|
| 484 |     (when (or full jar) | 
|---|
| 485 |       (let ((status (make-jar))) | 
|---|
| 486 |         (unless (zerop status) | 
|---|
| 487 |           (format t "Build failed.~%") | 
|---|
| 488 |           (return-from build-abcl nil)))) | 
|---|
| 489 |     ;; libabcl.so | 
|---|
| 490 |     (when (and (or full libabcl) | 
|---|
| 491 |                (or (eq *platform* :linux) | 
|---|
| 492 |                    (search "SunOS" (software-type)) | 
|---|
| 493 |                    (search "FreeBSD" (software-type)))) | 
|---|
| 494 |       ;; A failure here is not fatal. | 
|---|
| 495 |       (make-libabcl)) | 
|---|
| 496 |     ;; abcl/abcl.bat | 
|---|
| 497 |     (make-launch-script) | 
|---|
| 498 |     (make-build-stamp) | 
|---|
| 499 |     (let ((end (get-internal-real-time))) | 
|---|
| 500 |       (format t "Build completed successfully in ~A seconds.~%" | 
|---|
| 501 |               (/ (float (- end start)) internal-time-units-per-second))) | 
|---|
| 502 |     t)) | 
|---|
| 503 |  | 
|---|
| 504 | (defun build-abcl-executable () | 
|---|
| 505 |   (let* ((*default-pathname-defaults* *abcl-dir*) | 
|---|
| 506 |          (source-files (directory "*.java")) | 
|---|
| 507 |          (cmdline (with-output-to-string (s) | 
|---|
| 508 |                     (princ "gcj -g -O0 " s) | 
|---|
| 509 |                     (dolist (source-file source-files) | 
|---|
| 510 |                       (unless (string= (pathname-name source-file) "Native") | 
|---|
| 511 |                         (princ (pathname-name source-file) s) | 
|---|
| 512 |                         (princ ".java" s) | 
|---|
| 513 |                         (princ #\space s))) | 
|---|
| 514 |                     (princ "--main=org.armedbear.lisp.Main -o lisp" s))) | 
|---|
| 515 |          (result (run-shell-command cmdline :directory *abcl-dir*))) | 
|---|
| 516 |     (zerop result))) | 
|---|
| 517 |  | 
|---|
| 518 | (defvar *copy-verbose* nil) | 
|---|
| 519 |  | 
|---|
| 520 | (defun copy-file (source target) | 
|---|
| 521 |   (when *copy-verbose* | 
|---|
| 522 |     (format t "~A -> ~A~%" source target)) | 
|---|
| 523 |   (let ((buffer (make-array 4096 :element-type '(unsigned-byte 8)))) | 
|---|
| 524 |     (with-open-file (in source :direction :input :element-type '(unsigned-byte 8)) | 
|---|
| 525 |       (with-open-file (out target :direction :output :element-type '(unsigned-byte 8) | 
|---|
| 526 |                            :if-exists :supersede) | 
|---|
| 527 |         (loop | 
|---|
| 528 |           (let ((end (read-sequence buffer in))) | 
|---|
| 529 |             (when (zerop end) | 
|---|
| 530 |               (return)) | 
|---|
| 531 |             (write-sequence buffer out :end end))))))) | 
|---|
| 532 |  | 
|---|
| 533 | (defun copy-files (files source-dir target-dir) | 
|---|
| 534 |   (ensure-directories-exist target-dir) | 
|---|
| 535 |   (dolist (file files) | 
|---|
| 536 |     (copy-file (merge-pathnames file source-dir) | 
|---|
| 537 |                (merge-pathnames file target-dir)))) | 
|---|
| 538 |  | 
|---|
| 539 | (defun make-dist-dir (version-string) | 
|---|
| 540 |   (unless (eq *platform* :linux) | 
|---|
| 541 |     (error "MAKE-DIST is only supported on Linux.")) | 
|---|
| 542 |   (let ((target-root (pathname (concatenate 'string "/var/tmp/" version-string "/")))) | 
|---|
| 543 |     (when (probe-directory target-root) | 
|---|
| 544 |       (error "Target directory ~S already exists." target-root)) | 
|---|
| 545 |     (let* ((source-dir *build-root*) | 
|---|
| 546 |            (target-dir target-root) | 
|---|
| 547 |            (files (list "README" | 
|---|
| 548 |                         "COPYING" | 
|---|
| 549 |                         "build-abcl.lisp" | 
|---|
| 550 |                         "customizations.lisp" | 
|---|
| 551 |                         "make-jar.bat.in" | 
|---|
| 552 |                         "make-jar.in"))) | 
|---|
| 553 |       (copy-files files source-dir target-dir)) | 
|---|
| 554 |     (let* ((source-dir (merge-pathnames "examples/" *build-root*)) | 
|---|
| 555 |            (target-dir (merge-pathnames "examples/" target-root)) | 
|---|
| 556 |            (files '("hello.java"))) | 
|---|
| 557 |       (copy-files files source-dir target-dir)) | 
|---|
| 558 |     (let* ((source-dir (merge-pathnames "src/" *build-root*)) | 
|---|
| 559 |            (target-dir (merge-pathnames "src/" target-root)) | 
|---|
| 560 |            (files '("manifest-abcl"))) | 
|---|
| 561 |       (copy-files files source-dir target-dir)) | 
|---|
| 562 |     (let* ((source-dir *abcl-dir*) | 
|---|
| 563 |            (target-dir (merge-pathnames "src/org/armedbear/lisp/" target-root)) | 
|---|
| 564 |            (*default-pathname-defaults* source-dir) | 
|---|
| 565 |            (files (mapcar #'file-namestring (append (directory "*.java") | 
|---|
| 566 |                                                     (directory "*.lisp") | 
|---|
| 567 |                                                     (list "LICENSE" "native.c"))))) | 
|---|
| 568 |       (copy-files files source-dir target-dir)) | 
|---|
| 569 |     (let* ((source-dir (merge-pathnames "tests/" *abcl-dir*)) | 
|---|
| 570 |            (target-dir (merge-pathnames "src/org/armedbear/lisp/tests/" target-root)) | 
|---|
| 571 |            (*default-pathname-defaults* source-dir) | 
|---|
| 572 |            (files (append (mapcar #'file-namestring (directory "*.lisp")) | 
|---|
| 573 |                           (list "jl-config.cl")))) | 
|---|
| 574 |       (copy-files files source-dir target-dir)) | 
|---|
| 575 |     (let* ((source-dir (merge-pathnames "java/awt/" *abcl-dir*)) | 
|---|
| 576 |            (target-dir (merge-pathnames "src/org/armedbear/lisp/java/awt/" target-root)) | 
|---|
| 577 |            (*default-pathname-defaults* source-dir) | 
|---|
| 578 |            (files (mapcar #'file-namestring (directory "*.java")))) | 
|---|
| 579 |       (copy-files files source-dir target-dir)) | 
|---|
| 580 |     target-root)) | 
|---|
| 581 |  | 
|---|
| 582 | (defun make-dist (version-string) | 
|---|
| 583 |   (let* ((dist-dir (make-dist-dir version-string)) | 
|---|
| 584 |          (parent-dir (merge-pathnames (make-pathname :directory '(:relative :back)) | 
|---|
| 585 |                                       dist-dir))) | 
|---|
| 586 |     (let* ((command (format nil "tar czf ~A~A.tar.gz ~A" | 
|---|
| 587 |                             (namestring parent-dir) | 
|---|
| 588 |                             version-string version-string)) | 
|---|
| 589 |            (status (run-shell-command command :directory parent-dir))) | 
|---|
| 590 |       (unless (zerop status) | 
|---|
| 591 |         (format t "~A returned ~S~%" command status))) | 
|---|
| 592 |     (let* ((command (format nil "zip -q -r ~A~A.zip ~A" | 
|---|
| 593 |                             (namestring parent-dir) | 
|---|
| 594 |                             version-string version-string)) | 
|---|
| 595 |            (status (run-shell-command command :directory parent-dir))) | 
|---|
| 596 |       (unless (zerop status) | 
|---|
| 597 |         (format t "~A returned ~S~%" command status))))) | 
|---|