changeset 508: | e2d577f31866 |
parent: | 9472976adda9 |
child: | f68a5996a2b1 |
author: | Richard Westhaver <ellis@rwest.io> |
date: | Thu, 04 Jul 2024 21:03:47 -0400 |
permissions: | -rw-r--r-- |
description: | viz updates |
478 | 1 | ;;; makefile.lisp --- GNU Makefile Components |
91 | 2 | |
478 | 3 | ;; GNU Makefile skel components. |
91 | 4 | |
5 | ;;; Commentary: |
|
6 | ||
478 | 7 | ;; Makefiles are a reasonably portable build medium. We can parse them using |
8 | ;; the same general strategy as GNU make and compile them from skelfiles |
|
9 | ;; (rule, source, target, command). |
|
91 | 10 | |
11 | ;; HACK 2023-09-15: MVP |
|
12 | ||
13 | ;; SO, the absolute priority ATM is to transpile our `sk-rule' objects |
|
14 | ;; into a working Makefile. We're ignoring most of the niceties like |
|
15 | ;; line-splitting and any JIT or compile-time execution. |
|
16 | ||
17 | ;; https://github.com/takagi/lake |
|
18 | ||
19 | ;; https://www.gnu.org/software/make/manual/html_node/Parsing-Makefiles.html |
|
20 | ||
21 | ;;; Code: |
|
384 | 22 | (in-package :skel/comp/makefile) |
91 | 23 | |
24 | (defparameter *default-makefile* "makefile") |
|
25 | (defparameter *makefile-extension* "mk") |
|
26 | ||
27 | ;; TODO 2023-09-27: what is $(@D) ?? (target-dir) |
|
28 | (defvar *mk-magic-vars* #(#\@ #\< #\^ #\* #\+ #\? #\|)) |
|
29 | ||
30 | (defvar *mk-command-prefixes* #(#\@ #\- #\+)) |
|
31 | ||
32 | (deftype mk-val-designator () '(member nil :simple :immediate :conditional :recursive :once :append :shell)) |
|
33 | ||
384 | 34 | (defstruct mk-val (kind nil :type mk-val-designator) (val nil :type sxp:form)) |
91 | 35 | |
384 | 36 | (defstruct mk-var |
37 | (key "" :type string) |
|
38 | (val (make-mk-val) :type mk-val)) |
|
91 | 39 | |
40 | ;; https://www.gnu.org/software/make/manual/html_node/Makefile-Contents.html |
|
41 | (defclass makefile (skel sk-meta) |
|
42 | ((directives :initform (make-array 0 :element-type 'sk-command :adjustable t :fill-pointer 0) |
|
43 | :type (vector sk-command) :accessor mk-directives) |
|
44 | (variables :initform (make-hash-table) |
|
45 | :type (hash-table) :accessor mk-vars) |
|
46 | (explicit :initform (make-array 0 :element-type 'sk-rule :adjustable t :fill-pointer 0) |
|
47 | :type (vector sk-rule) :accessor mk-erules) |
|
48 | (implicit :initform (make-array 0 :element-type 'sk-rule :adjustable t :fill-pointer 0) |
|
49 | :type (vector sk-rule) :accessor mk-irules)) |
|
50 | (:documentation "A virtual GNU Makefile.")) |
|
51 | ||
384 | 52 | (defmethod push-mk-rule ((self sk-rule) (place makefile) &optional implicit) |
91 | 53 | (if implicit |
54 | (vector-push-extend self (mk-irules place)) |
|
55 | (vector-push-extend self (mk-erules place)))) |
|
56 | ||
384 | 57 | (defmethod push-mk-directive ((self sk-command) (place makefile)) |
91 | 58 | (vector-push-extend self (mk-directives place))) |
59 | ||
384 | 60 | (defmethod push-mk-var ((self cons) (place makefile)) |
91 | 61 | (destructuring-bind (k v) self |
62 | (setf (gethash k (mk-vars place)) v))) |
|
63 | ||
64 | (defmethod sk-compile ((self makefile) stream &key &allow-other-keys) |
|
65 | "Compile the makefile SELF to output STREAM." |
|
66 | (with-open-stream (s stream) |
|
67 | (with-slots (directives variables explicit implicit) self |
|
68 | ;; directives |
|
69 | (loop for d across directives |
|
70 | do (sk-writeln d s)) |
|
71 | ;; variables |
|
72 | (maphash (lambda (x y) (format s "~A=~A~%" x y)) variables) |
|
73 | ;; explicit rules |
|
74 | (loop for exp across explicit |
|
75 | do (format s "~A:~A;~A~%" |
|
508 | 76 | (sk-rule-target exp) |
77 | (sk-rule-source exp) |
|
91 | 78 | (sk-write-string (sk-rule-recipe exp)))) |
79 | ;; TODO implicit rules |
|
80 | (loop for imp across implicit |
|
81 | do (format s "~A:~A;~A~%" |
|
508 | 82 | (sk-rule-target imp) |
83 | (sk-rule-source imp) |
|
91 | 84 | (sk-write-string (sk-rule-recipe imp))))))) |
85 | ||
86 | (defmethod sk-write-file ((self makefile) &key (path *default-makefile*) (comment t) (if-exists :overwrite)) |
|
87 | (with-open-file (out path |
|
88 | :direction :output |
|
89 | :if-exists if-exists |
|
90 | :if-does-not-exist :create) |
|
91 | (when comment (princ |
|
92 | (make-source-header-comment |
|
93 | (sk-name self) |
|
94 | :cchar #\# |
|
95 | :timestamp t |
|
96 | :description (sk-description self) |
|
97 | :opts '("mode: makefile-gmake;")) |
|
98 | out)) |
|
99 | (sk-compile self out))) |
|
100 | ||
162 | 101 | (defmethod sk-read-file ((self makefile) path) |
163 | 102 | (with-open-file (in path :direction :input))) |
384 | 103 | |
104 | ;;; Readtable |
|
105 | (defreadtable :makefile |
|
106 | (:merge :std)) |
|
107 | ||
108 | ;;; Auto Vars |
|
109 | ||
110 | ;; simplified version of GNU Make Automatic Variables |
|
111 | ||
112 | ;; don't need these: $% $? $+ $* |
|
113 | ||
439
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
384
diff
changeset
|
114 | ;; (defmacro def-mk-auto (sym ll &body body)) |
384 | 115 | |
439
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
384
diff
changeset
|
116 | ;; (def-mk-auto $@ (rule) (sk-rule-target rule)) |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
384
diff
changeset
|
117 | ;; (def-mk-auto $< (rule) (car (sk-rule-source rule))) |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
384
diff
changeset
|
118 | ;; (def-mk-auto $^ (rule) (sk-rule-source rule)) |
384 | 119 |