-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathne-makefile-backend.lisp
140 lines (131 loc) · 6.32 KB
/
ne-makefile-backend.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#+xcvb
(module
(:depends-on ("makefile-backend" "asdf-backend" "simplifying-traversal")))
(in-package :xcvb)
(defclass nem-traversal (asdf-traversal makefile-traversal)
())
(defmethod build-in-target-p ((env nem-traversal) build)
(declare (ignorable env build))
t)
(defmethod issue-dependency ((env nem-traversal) (grain lisp-file-grain))
(unless (member (second (fullname grain)) '("/xcvb/driver" "/asdf/asdf" "/poiu/poiu")
:test 'equal)
(call-next-method))
(values))
(defun make-nem-stage (env asdf-name build &key previous parallel)
(nest
(let ((*computations* nil)
(*asdf-system-dependencies* nil)
(*require-dependencies* nil)))
(progn (graph-for-build-module-grain env build))
(let ((inputs (loop :for computation :in (reverse *computations*)
:for i = (first (computation-inputs computation))
:when (and i (not (grain-computation i)))
:collect i))
(asd-vp (make-vp :obj "/" asdf-name "." "asd"))))
(progn (do-write-asd-file env :output-path (vp-namestring env asd-vp)
:asdf-name asdf-name))
(let* ((image-name `(:image ,(strcat "/" asdf-name)))
(image (setf (registered-grain image-name)
(make-grain 'image-grain :fullname image-name)))
(previous-spec (if previous
`(:image (:image ,(strcat "/" previous)))
(progn
(setf inputs
(append (mapcar #'registered-grain *lisp-setup-dependencies*)
inputs))
`(:load ,*lisp-setup-dependencies*))))
(computation
(make-computation ()
:outputs (list image)
:inputs inputs
:command
`(:xcvb-driver-command ,previous-spec
(:create-image
(:image ,image-name)
(:register-asdf-directory ,*object-cache*)
,@(when parallel
`((:register-asdf-directory
,(pathname-directory-pathname
(grain-pathname (registered-build "/poiu" :ensure-build t))))))
(:initialize-asdf)
,@(when parallel '((:load-asdf :poiu)))
(:load-asdf ,(coerce-asdf-system-name asdf-name)
,@(when parallel `(:parallel t)))))))
(*computations* (list computation)))
(computations-to-Makefile env))))
(defun write-non-enforcing-makefile (build-names &key output-path asdf-name parallel)
"Write a Makefile to output-path with information about how to compile the specified BUILD
in a fast way that doesn't enforce dependencies."
(let* ((*print-pretty* nil); otherwise SBCL will slow us down a lot.
(*use-cfasls* nil) ;; We use ASDF that doesn't know about them
(builds ;; TODO: somehow use handle-target instead
(mapcar (lambda (n) (registered-build n :ensure-build t)) build-names))
(last-build (first (last builds)))
(asdf-names (loop :for (build . rest) :on build-names :for i :from 1
:collect (if rest
(format nil "~A-stage~D-~A" asdf-name i build)
asdf-name)))
(default-output-path (subpathname (grain-pathname last-build) "xcvb-ne.mk"))
(output-path (merge-pathnames* output-path default-output-path))
(makefile-path (ensure-absolute-pathname output-path))
(makefile-dir (pathname-directory-pathname makefile-path))
(*default-pathname-defaults* makefile-dir)
(*makefile-target-directories* (make-hash-table :test 'equal))
(*makefile-target-directories-to-mkdir* nil)
(*makefile-phonies* nil)
(lisp-env-var (lisp-environment-variable-name :prefix nil))
(*lisp-executable-pathname* ;; magic escape!
(list :makefile "${" lisp-env-var "}"))
(smt (make-instance 'static-makefile-traversal))
(env (make-instance 'nem-traversal))
(static-rules
(prog2
(issue-image-named smt nil)
(computations-to-Makefile smt)
(setf *computations* nil)))
(build-rules
(loop
;; :for build-name :in build-names
:for build :in builds
:for previous-asdf = nil :then asdf-name
:for asdf-name :in asdf-names
:collect (make-nem-stage env asdf-name build
:previous previous-asdf
:parallel parallel))))
(ensure-directories-exist makefile-path)
(with-open-file (out makefile-path
:direction :output
:if-exists :supersede)
(write-makefile-prelude :stream out :lisp-env-var lisp-env-var)
(dolist (body (reverse (cons static-rules build-rules)))
(princ body out))
(write-makefile-conclusion out))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; non-enforcing makefile ;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-command non-enforcing-makefile
(("non-enforcing-makefile" "nemk" "nm")
(&rest keys &key)
`(,@+multi-build-option-spec+
,@+setup-option-spec+
,@+base-image-option-spec+
,@+source-registry-option-spec+
(("name" #\n) :type string :optional t :initial-value "xcvb-tmp" :documentation "ASDF name for the target")
(("output-path" #\o) :type string :initial-value "xcvb-ne.mk" :documentation "specify output path")
,@+xcvb-program-option-spec+
,@+workspace-option-spec+
,@+lisp-implementation-option-spec+
(("parallel" #\P) :type boolean :optional t :initial-value nil :documentation "compile in parallel with POIU")
;; ,@+profiling-option-spec+
,@+verbosity-option-spec+)
"Create some Makefile for a non-enforcing build"
"Create some Makefile for a non-enforcing build,
that will use ASDF or POIU to create one or a series of images each containing
the previous image, a build and its dependencies."
(build name output-path parallel))
(apply 'handle-global-options #|:disable-cfasl (not force-cfasl)|# keys)
(with-maybe-profiling ()
(write-non-enforcing-makefile
(mapcar #'canonicalize-fullname build)
:asdf-name name
:output-path output-path
:parallel parallel)))