one-off-output function
output-module function
output-type-pathname function
+ write-dependency-file generic
module-parse.lisp
class-item
module class
module-dependencies generic setf-generic
module-errors generic
+ module-files generic setf-generic
module-import generic
module-items generic setf-generic
module-name generic
t module
module-errors
module
+module-files
+ module
+(setf module-files)
+ t module
module-import
t
module
vtmsgs
vtmsgs-subclass
vtmsgs
+write-dependency-file
+ module t t
-----------------------------------------------------------------------------
Package `sod-frontend'
\end{describe}
\begin{describe}{cls}
- {module () \&key :name :pset :items :dependencies :variables :state}
+ {module ()
+ \&key :name :pset :items :files :dependencies :variables :state}
\end{describe}
\begin{describe*}
\dhead{gf}{module-errors @<module> @> @<integer>}
\dhead{gf}{module-items @<module> @> @<list>}
\dhead{gf}{setf (module-items @<module>) @<list>}
+ \dhead{gf}{module-files @<module> @> @<list>}
+ \dhead{gf}{setf (module-files @<module>) @<list>}
\dhead{gf}{module-dependencies @<module> @> @<list>}
\dhead{gf}{setf (module-dependencies @<module>) @<list>}
\dhead{gf}{module-state @<module> @> @<symbol>}
\end{describe*}
\end{describe}
+\begin{describe}{gf}{write-dependency-file @<module> @<reason> @<output-dir>}
+\end{describe}
+
\begin{describe}{fun}{output-module @<module> @<reason> @<stream>}
\end{describe}
(backtracep nil)
(builtinsp nil)
(stdoutp nil)
+ (track-deps-p nil)
(args nil))
;; Option definitions.
:print nil))))
(error (error)
(option-parse-error "~A" error))))))
+ (#\M "track-dependencies"
+ "Write make(1) fragments recording dependencies."
+ (set track-deps-p))
(#\p "stdout"
("Write output files to standard output.")
(set stdoutp))
:direction :output
:if-exists :supersede
:if-does-not-exist :create)
- (output-module module reason stream))))
+ (output-module module reason stream))
+
+ (when track-deps-p
+ (write-dependency-file module reason
+ output-path))))
;; Error recovery.
(continue ()
The output file name will be constructed by merging the module's pathname
with PATHNAME."
+ (pushnew reason *output-types*)
(setf (get reason 'output-type) pathname))
(export 'output-type-pathname)
(make-pathname :directory nil
:defaults (module-name module)))))
+(export 'write-dependency-file)
+(defgeneric write-dependency-file (module reason output-dir)
+ (:documentation
+ "Write a dependency-tracking make(1) fragment.
+
+ Specifically, we've processed a MODULE for a particular REASON (a
+ symbol), and the user has requested that output be written to OUTPUT-DIR
+ (a pathname): determine a suitable output pathname and write a make(1)
+ fragment explaining that the output file we've made depends on all of the
+ files we had to read to load the module."))
+
+(defmethod write-dependency-file ((module module) reason output-dir)
+ (let* ((common-case
+ ;; Bletch. We want to derive the filetype from the one we're
+ ;; given, but we need to determine the environment's preferred
+ ;; filetype case to do that. Make a pathname and inspect it to
+ ;; find out how to do this.
+
+ (if (upper-case-p
+ (char (pathname-type (make-pathname
+ :type "TEST"
+ :case :common))
+ 0))
+ #'string-upcase
+ #'string-downcase))
+
+ (outpath (output-type-pathname reason))
+ (deppath (make-pathname :type (concatenate 'string
+ (pathname-type outpath)
+ (funcall common-case
+ "-DEP"))
+ :defaults outpath))
+ (outfile (module-output-file module reason output-dir))
+ (depfile (module-output-file module deppath output-dir)))
+
+ (with-open-file (dep depfile
+ :direction :output
+ :if-exists :supersede
+ :if-does-not-exist :create)
+ (format dep "### -*-makefile-*-~%~
+ ~A:~{ \\~% ~A~}~%"
+ outfile
+ (cons (module-name module)
+ (module-files module))))))
+
(define-clear-the-decks reset-output-types
"Clear out the registered output types."
(dolist (reason *output-types*) (remprop reason 'output-type))
:truename true)))
(when module
(module-import module)
+ (pushnew path (module-files *module*))
(pushnew module
(module-dependencies
*module*))))
(common name "LISP" "Lisp file"
(lambda (path true)
(handler-case
- (load true :verbose nil :print nil)
+ (progn
+ (pushnew path (module-files *module*))
+ (load true :verbose nil :print nil))
(error (error)
(cerror* "Error loading Lisp file ~S: ~A"
path error)))))))))))
;;; Module objects.
(export '(module module-name module-pset module-errors
- module-items module-dependencies module-state))
+ module-items module-files module-dependencies module-state))
(defclass module ()
((name :initarg :name :type pathname :reader module-name)
(%pset :initarg :pset :initform (make-pset)
:type pset :reader module-pset)
(errors :initarg :errors :initform 0 :type fixnum :reader module-errors)
(items :initarg :items :initform nil :type list :accessor module-items)
+ (files :initarg :files :initform nil :type list :accessor module-files)
(dependencies :initarg :dependencies :initform nil
:type list :accessor module-dependencies)
(variables :initarg :variables :type list :accessor module-variables
* A list of other modules that this one depends on.
+ * A list of other files this module has read.
+
* A list of module-variable values, in the order in which they're named
in `*module-bindings-alist*'.
### The silly Chimaera example.
check_PROGRAMS += chimaera
+-include chimaera.c-dep chimaera.h-dep
EXTRA_DIST += chimaera.sod
nodist_chimaera_SOURCES = chimaera.c chimaera.h
TESTS += test
check_PROGRAMS += test
+-include test.c-dep test.h-dep
EXTRA_DIST += test.sod
nodist_test_SOURCES = test.c test.h
diff -u $(srcdir)/kwtest.ref kwtest.out
check_PROGRAMS += rat
+-include rat.c-dep rat.h-dep
EXTRA_DIST += rat.sod rat.ref
nodist_rat_SOURCES = rat.c rat.h
SUFFIXES += .c .h .sod
.sod.c:; $(V_SOD_c)$(SOD) -tc $<
.sod.h:; $(V_SOD_h)$(SOD) -th $<
-%.c: %.sod $(SOD); $(V_SOD_c)$(SOD) -tc $<
-%.h: %.sod $(SOD); $(V_SOD_h)$(SOD) -th $<
+%.c: %.sod $(SOD); $(V_SOD_c)$(SOD) -M -tc $<
+%.h: %.sod $(SOD); $(V_SOD_h)$(SOD) -M -th $<
+
+DISTCLEANFILES += *.c-dep *.h-dep
###--------------------------------------------------------------------------
### Silent rules for Lisp.