forked from Moonchild/fancy-build
91 lines
3.5 KiB
Plaintext
91 lines
3.5 KiB
Plaintext
(defun runp (cmd)
|
|
(unless (zerop (uiop:wait-process (uiop:launch-program cmd :output *standard-output* :error-output *error-output*)))
|
|
(die "command '~a' failed" cmd)))
|
|
|
|
(defclass c-compiler (buildable)
|
|
((cached-snapshot :accessor c-compiler-executable :initform nil)
|
|
(supports-md :initform nil)))
|
|
(defmethod initialize-instance :after ((b c-compiler) &key)
|
|
(setf (unique-key b) 'cc))
|
|
(defmethod do-build ((b c-compiler))
|
|
; todo more sophisticated c compiler location mechanics
|
|
(runp "cc -v")
|
|
(setf (c-compiler-executable b) "cc -c")
|
|
(setf (slot-value b 'supports-md) t))
|
|
(defmethod snapshot ((b c-compiler)) (c-compiler-executable b))
|
|
(defmethod is-dirty ((b c-compiler) old) (not (string-equal (c-compiler-executable b) old)))
|
|
|
|
; will this ever be different from the compiler?
|
|
(defclass c-linker (buildable)
|
|
((cached-snapshot :accessor c-linker-executable :initform nil)))
|
|
(defmethod initialize-instance :after ((b c-linker) &key)
|
|
(setf (unique-key b) 'ccld))
|
|
(defmethod do-build ((b c-linker))
|
|
; todo: ditto more sophisticated
|
|
(runp "cc -v")
|
|
(setf (c-linker-executable b) "cc"))
|
|
(defmethod snapshot ((b c-linker)) (c-linker-executable b))
|
|
(defmethod is-dirty ((b c-linker) old) (not (string-equal (c-linker-executable b) old)))
|
|
|
|
(defclass c-source-buildable (rebuilt-on-file-change)
|
|
((source-file :initarg :source-file)
|
|
(obj-file :initarg :obj-file)))
|
|
|
|
(defclass c-binary-buildable (rebuilt-on-file-change)
|
|
((target-binary :initarg :target-binary)
|
|
(obj-files)))
|
|
|
|
(defmethod initialize-instance :after ((b c-binary-buildable) &key)
|
|
(setf (slot-value b 'obj-files)
|
|
(mapcar #'(lambda (x)
|
|
(slot-value x 'obj-file))
|
|
(remove-if-not #'(lambda (x) (typep x 'c-source-buildable))
|
|
(dependencies b))))
|
|
(setf (slot-value b 'input-files) (slot-value b 'obj-files))
|
|
(setf (slot-value b 'output-files) `(,(slot-value b 'target-binary)))
|
|
(setf (pretty-name b) (slot-value b 'target-binary))
|
|
(setf (unique-key b) (cons 'c-binary-buildable (cons (slot-value b 'target-binary) (slot-value b 'obj-files))))
|
|
(push (make-instance 'c-linker) (dependencies b)))
|
|
|
|
(defmethod do-build ((b c-binary-buildable))
|
|
(runp (format nil "~a -o ~a ~{~a~^ ~}"
|
|
(c-linker-executable (car (dependencies b)))
|
|
(slot-value b 'target-binary)
|
|
(slot-value b 'obj-files))))
|
|
|
|
(defmethod initialize-instance :after ((b c-source-buildable) &key)
|
|
(setf (slot-value b 'input-files) `(,(slot-value b 'source-file)))
|
|
(setf (slot-value b 'output-files) `(,(slot-value b 'obj-file)))
|
|
(setf (pretty-name b) (slot-value b 'source-file))
|
|
(setf (unique-key b) `(c-source-buildable ,(slot-value b 'obj-file) ,(slot-value b 'source-file)))
|
|
(push (make-instance 'c-compiler) (dependencies b)))
|
|
|
|
(defmethod do-build ((b c-source-buildable))
|
|
(ensure-directories-exist (directory-namestring (slot-value b 'obj-file)))
|
|
(runp (format nil "~a -o ~a ~a"
|
|
(c-compiler-executable (car (dependencies b)))
|
|
(slot-value b 'obj-file)
|
|
(slot-value b 'source-file))))
|
|
|
|
(defun c-source (file)
|
|
(make-instance 'c-source-buildable
|
|
:source-file file
|
|
:obj-file (format nil "build/~a.o" file)))
|
|
(defun c-sourcelist (srclist)
|
|
(mapcar #'c-source srclist))
|
|
|
|
(defun c-binary (bin deps)
|
|
(make-instance 'c-binary-buildable
|
|
:target-binary (format nil "build/~a" bin)
|
|
:dependencies deps))
|
|
|
|
(defparameter *t1*
|
|
(c-binary "test"
|
|
(c-sourcelist '("src/add.c" "src/test.c"))))
|
|
(defparameter *t2*
|
|
(c-binary "test2"
|
|
(c-sourcelist '("src/add.c" "src/test2.c"))))
|
|
|
|
(target "default" *t1*)
|
|
(target "other" *t2*)
|