Search code examples
common-lispasdf

How to specify additional files as prerequisites that would cause ASDF to recompile the program


I have written a program that uses read-time evaluation to read strings contained in text files. In this example, the text files are 1.txt and 2.txt, both of which contain text that will be read during read-time. The problem: ASDF will not recompile the program when I edit 1.txt or 2.txt even though the contents of these files affect the behavior of the program. How do I add these two files as additional "prerequisites" that would cause the program to be recompiled if the files are modified?

This is the program in question:

myprog.asd:

(defpackage myprog-asd
  (:use :cl :asdf))
(in-package :myprog-asd)

(defsystem "myprog"
  :components ((:file "myprog")))

myprog.lisp:

(in-package :cl-user)

(eval-when (:compile-toplevel :load-toplevel :execute)
  (defun read-file-string (path)
    "Returns the contents of the file as a string"
    (with-open-file (stream path :direction :input)
      (let ((str (make-string (file-length stream))))
        (read-sequence str stream)
        str))))

(defun run-main ()
  (princ #.(read-file-string "1.txt"))
  (princ #.(read-file-string "2.txt"))
  nil)

Create the 1.txt and 2.txt:

$ echo 'Hello' > 1.txt
$ echo 'World' > 2.txt

Compile and run the program:

$ sbcl
* (require "asdf")
* (asdf:load-asd (merge-pathnames "myprog.asd" (uiop:getcwd)))
* (asdf:load-system :myprog)
* (run-main)
Hello
World
NIL

If I modify 1.txt or 2.txt, the program would not be recompiled, resulting in wrong output for (run-main):

$ echo 'Hi!' > 1.txt
$ echo 'Bye!' > 2.txt
$ sbcl
* (require "asdf")
* (asdf:load-asd (merge-pathnames "myprog.asd" (uiop:getcwd)))
* (asdf:load-system :myprog)
* (run-main)
Hello
World
NIL

How do I fix this problem? (asdf:load-system :myprog :force t) could fix the problem but it recompiles the program even when there are no changes.

(SBCL 2.2.2; ASDF 3.3.5; Ubuntu 20.04)


Solution

  • Just include the auxiliary files as additional dependencies, using the :static-file directive:

    (defsystem "myprog"
      :components ((:static-file "1.txt")
                   (:static-file "2.txt")
                   (:file "myprog" :depends-on ("1.txt" "2.txt"))))