forked from Moonchild/fancy-build
fancy colours
This commit is contained in:
parent
474353345f
commit
5b79bc0b42
@ -1,5 +1,6 @@
|
||||
(defun runp (cmd)
|
||||
(assert (zerop (uiop:wait-process (uiop:launch-program cmd :output *standard-output* :error-output *error-output*)))))
|
||||
(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)
|
||||
|
42
readme
42
readme
@ -4,7 +4,45 @@ Models constraints of and is able to interoperate with any other build system.
|
||||
(Ideally. In practice, something like scons will be impractical; but make,
|
||||
cargo, cpan, dub, etc. are fine.)
|
||||
|
||||
Closest in design to shake (https://shakebuild.com/). Primary differences:
|
||||
- Build starts instantly. No need to build your build file.
|
||||
Pros:
|
||||
- Fast
|
||||
* Don't do any more work than you have to
|
||||
+ SCons, redo, and bazel (and bazel's derivatives--buck, please, etc.)
|
||||
get this right. Most others (make, ninja, etc.) don't.
|
||||
× ninja has an open ticket to resolve this, but maintainers seem
|
||||
uninterested in resolving it. (https://github.com/ninja-build/ninja/issues/1459)
|
||||
+ Example: purely syntactic (not semantic) change shouldn't require a re-link.
|
||||
* Parallel
|
||||
- Correct
|
||||
* Always rebuild if you have to
|
||||
+ SCons, redo, and bazel&co (again) get this right.
|
||||
+ Example: update system c compiler or headers.
|
||||
× For some, even just updating locally-referenced headers is enough.
|
||||
- Easy to use for tiny projects, but programmable enough to scale indefinitely
|
||||
* SCons hits these points, but it's slow; not pathologically so, just incidentally.
|
||||
* Redo uses shell, which has difficulty with abstraction.
|
||||
* Ditto make.
|
||||
* Bazel (and derivatives) are interesting:
|
||||
+ Reasonably powerful programming language
|
||||
+ Build description for a toy project looks reasonable: 5
|
||||
lines indicating source and target files.
|
||||
But:
|
||||
+ Heavyweight. Slow startup time is solved by running a persistent build
|
||||
server; not unreasonable for google-scale projects but that seems like
|
||||
overkill when you look at the 20-line build description it executes.
|
||||
+ Builtin build rules insufficiently introspectible or modifiable.
|
||||
For example, changing the toolchain used, or the build flags, is much
|
||||
more complex than it need be--than it is, in most build systems.
|
||||
× Partly, this is just because those build rules don't expose hooks to
|
||||
modify those attributes. But mostly it's because the build language
|
||||
doesn't lend itself well to such dynamism, so it's not encouraged.
|
||||
× (https://github.com/bazelbuild/bazel/issues/2954,
|
||||
https://github.com/bazelbuild/bazel/issues/4644)
|
||||
It's not a problem that such bugs exist, but it is a problem that
|
||||
they can't be easily fixed or worked around 'in userspace'.
|
||||
|
||||
The closest build systems to solving all these are SCons and Shake
|
||||
(https://shakebuild.com/). SCons is slow. Compared with shake, we have:
|
||||
- No conflation of build targets with on-disc files. Represent deployment,
|
||||
dependencies from (network) package registry, ...
|
||||
- Build starts instantly. No need to build your build file.
|
||||
|
@ -11,7 +11,7 @@
|
||||
(defclass buildable ()
|
||||
((dependencies :initarg :dependencies :initform nil :accessor dependencies)
|
||||
(cached-snapshot :initform nil)
|
||||
(pretty-name :initarg :pretty-name :initform "" :accessor pretty-name)
|
||||
(pretty-name :initarg :pretty-name :initform nil :accessor pretty-name)
|
||||
(unique-key :initform nil :accessor unique-key)))
|
||||
|
||||
(defgeneric snapshot (buildable))
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
(defun main ()
|
||||
(unless (probe-file "fancy.build")
|
||||
(die "Could not find build description file 'fancy.build'."))
|
||||
(die "could not find build description file 'fancy.build'"))
|
||||
|
||||
(when (probe-file "fancy.buildcache")
|
||||
(with-open-file (fp "fancy.buildcache"
|
||||
@ -21,12 +21,11 @@
|
||||
(load "fancy.build"))
|
||||
|
||||
(let ((targets-list (mapcar #'(lambda (name)
|
||||
(or (gethash name *targets*) (die "No target named '~a'." name)))
|
||||
(or (gethash name *targets*) (die "no target named '~a'" name)))
|
||||
(or (uiop:command-line-arguments) '("default")))))
|
||||
(parallel-build (if (cdr targets-list)
|
||||
(make-instance 'buildable :dependencies targets-list)
|
||||
(car targets-list))))
|
||||
;(naively-build target)
|
||||
|
||||
|
||||
(with-open-file (fp "fancy.buildcache"
|
||||
|
@ -1,6 +1,6 @@
|
||||
(in-package :fancybuild)
|
||||
|
||||
(export 'target)
|
||||
(export '(target die dwarn notice))
|
||||
|
||||
(defparameter *targets* (make-hash-table :test #'equal))
|
||||
(defparameter *global-cache* (make-hash-table :test #'equal))
|
||||
@ -15,11 +15,35 @@
|
||||
`(let ((- ,test))
|
||||
(unless - ,@body)))
|
||||
|
||||
(defun stdout-tty-p () (interactive-stream-p *standard-output*))
|
||||
|
||||
(defun clr-maybe (seq)
|
||||
(if (stdout-tty-p)
|
||||
(apply #'format `(,nil ,seq #\esc))
|
||||
""))
|
||||
(defun clr-red () (clr-maybe "~a[31m"))
|
||||
(defun clr-green () (clr-maybe "~a[32m"))
|
||||
(defun clr-brown () (clr-maybe "~a[33m"))
|
||||
(defun clr-blue () (clr-maybe "~a[34m"))
|
||||
(defun clr-magenta () (clr-maybe "~a[35m"))
|
||||
(defun clr-cyan () (clr-maybe "~a[36m"))
|
||||
(defun clr-gray () (clr-maybe "~a[37m")) ; note: may be black on some terminals; avoid
|
||||
(defun clr-reset () (clr-maybe "~a[0m"))
|
||||
(defun clr-bold () (clr-maybe "~a[1m"))
|
||||
(defun clr-dim () (clr-maybe "~a[2m"))
|
||||
(defun clr-invert () (clr-maybe "~a[3m"))
|
||||
(defun clr-underline () (clr-maybe "~a[4m"))
|
||||
|
||||
(defun die (&rest msg)
|
||||
(apply #'format (cons t msg))
|
||||
(format t "~%")
|
||||
(format t "~a~aERROR~a: ~a~%" (clr-bold) (clr-red) (clr-reset) (apply #'format (cons nil msg)))
|
||||
(uiop:quit 1))
|
||||
|
||||
(defun dwarn (&rest msg)
|
||||
(format t "~a~aWARNING~a: ~a~%" (clr-bold) (clr-brown) (clr-reset) (apply #'format (cons nil msg))))
|
||||
|
||||
(defun notice (&rest msg)
|
||||
(format t "~a~%" (apply #'format (cons nil msg))))
|
||||
|
||||
(defun target (name target)
|
||||
(setf (gethash name *targets*) target))
|
||||
|
||||
@ -32,10 +56,8 @@
|
||||
|
||||
(unless (and (slot-value b 'cached-snapshot)
|
||||
(not (is-dirty b (slot-value b 'cached-snapshot))))
|
||||
(format t "Building ~a...~%" (pretty-name b))
|
||||
(handler-case (do-build b)
|
||||
(error ()
|
||||
(die "Error building ~a!" (pretty-name b)))))
|
||||
(notice "building ~a..." (pretty-name b))
|
||||
(do-build b))
|
||||
(setf (slot-value b 'cached-snapshot) (snapshot b))
|
||||
(when (unique-key b)
|
||||
(setf (gethash (unique-key b) *global-cache*)
|
||||
|
@ -38,7 +38,7 @@
|
||||
:do (let ((b (pop currently-buildable)))
|
||||
(when (check-dirty (parallel-buildable-base b))
|
||||
(awhen (pretty-name (parallel-buildable-base b))
|
||||
(format t "Building ~a...~%" -))
|
||||
(notice "building ~a..." -))
|
||||
(do-build (parallel-buildable-base b))
|
||||
(setf (slot-value (parallel-buildable-base b) 'cached-snapshot) (snapshot (parallel-buildable-base b)))
|
||||
(setf (gethash (unique-key (parallel-buildable-base b)) *global-cache*) (slot-value (parallel-buildable-base b) 'cached-snapshot)))
|
||||
|
Loading…
Reference in New Issue
Block a user