changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > core / lisp/lib/skel/comp/makefile.lisp

changeset 594: 5bd0eb9fa1fa
parent: f68a5996a2b1
child: cc89b337384b
author: Richard Westhaver <ellis@rwest.io>
date: Wed, 14 Aug 2024 21:49:56 -0400
permissions: -rw-r--r--
description: rocksdb callbacks, missing symbol fixes
1 ;;; makefile.lisp --- GNU Makefile Components
2 
3 ;; GNU Makefile skel components.
4 
5 ;;; Commentary:
6 
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).
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:
22 (in-package :skel/comp/makefile)
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 
34 (defstruct mk-val (kind nil :type mk-val-designator) (val nil :type sxp:form))
35 
36 (defstruct mk-var
37  (key "" :type string)
38  (val (make-mk-val) :type mk-val))
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 
52 (defmethod push-mk-rule ((self sk-rule) (place makefile) &optional implicit)
53  (if implicit
54  (vector-push-extend self (mk-irules place))
55  (vector-push-extend self (mk-erules place))))
56 
57 (defmethod push-mk-directive ((self sk-command) (place makefile))
58  (vector-push-extend self (mk-directives place)))
59 
60 (defmethod push-mk-var ((self cons) (place makefile))
61  (destructuring-bind (k v) self
62  (setf (gethash k (mk-vars place)) v)))
63 
64 (defmethod sk-compile ((self makefile) &key stream &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~%"
76  (sk-rule-target exp)
77  (sk-rule-source exp)
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~%"
82  (sk-rule-target imp)
83  (sk-rule-source imp)
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 :stream out)))
100 
101 (defmethod sk-read-file ((self makefile) path)
102  (with-open-file (in path :direction :input)))
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 
114 ;; (defmacro def-mk-auto (sym ll &body body))
115 
116 ;; (def-mk-auto $@ (rule) (sk-rule-target rule))
117 ;; (def-mk-auto $< (rule) (car (sk-rule-source rule)))
118 ;; (def-mk-auto $^ (rule) (sk-rule-source rule))
119