October 5th, 2011

Resource access and ASDF

In olden times, I would sometimes make CL applications that referenced resources adjacent to the source code, e.g. template files, font files, images, and things like that. To get a pathname for those resources, I would do something like this:
(defvar *font-pathname*
  (merge-pathnames #p"font.ttf" *load-truename*)))
Then ASDF2 arrived, and with its default policy of storing FASL files separated from source files, the above construct broke. *load-truename* wound up being something like /Users/xach/.cache/common-lisp/foo/bar/app/funk.fasl instead of /Users/xach/src/app/funk.fasl, and font.ttf wasn't anywhere nearby.

I initially switched my defvar forms to use something like this instead:
(defvar *font-pathname* 
  (asdf:system-relative-pathname 'app #p"font.ttf"))
That works ok. I don't like embedding ASDF references in my source code, though, so for now I'm switching to something like this in my app.asd file:
(defpackage #:app-config (:export #:*base-directory*))
(defparameter app-config:*base-directory* 
  (make-pathname :name nil :type nil :defaults *load-truename*))
And in the source:
(defvar *font-pathname*
  (merge-pathnames #p"font.ttf" app-config:*base-directory*))
That way at least I won't have to update the application source code when I replace ASDF with something else!