ASDF Build Directories
Wednesday, December 22, 2004
Daniel Barlow's ASDF utility is the build utility of choice for many CL developers (myself included). However, as with most utilities, people often find little "tweaks" that they can do to make the utility work better in their own environments. For example, I previously discussed how Win32 users can more easily configure ASDF to find their Lisp package locations. Another such "tweak" was asked about on c.l.l. a few weeks ago. Frederic Brunel wanted to know whether it was possible to specify a "build directory" for ASDF builds. In other words, have the compiled output of the ASDF build go to a specified directory. This would allow you to keep your build output separate from your source files even if the .asd file for the project didn't specify a separate build directory location. Although this is not a standard feature in ASDF, Björn Lindberg showed how it could be done by specializing the ASDF:OUTPUT-FILES method on ASDF:COMPILE-OP. Since I might want to do something similar at some stage, I decided to try out his code by building Miles Eagan's XMLS XML parser into a separate "fasl directory". Here are the steps I followed:
- In my init file, I already had code to load ASDF and to set the asdf:*central-registry* variable (see my earlier posting)
- I had the source for Miles Eagan's XMLS XML parser in the "c:/usr/home/lisp/xmls-1.2/" directory. I created a "c:/usr/home/lisp/bin/" directory for the generated fasl's.
- I put Björn Lindberg's code in a separate "asdf-build.lisp" file, modifying the *system-configuration-paths* variable to
indicate that I wanted XMLS output to go to the specified output
directory (the *system-configuration-paths* variable holds
source/binary directory pairs so that you can choose to put your
binaries wherever you want on a per-project basis):
(in-package :asdf)
(defvar *system-configuration-paths* '(("c:/usr/home/lisp/xmls-1.2/" "c:/usr/home/lisp/bin/")))
(defun pathname-prefix-p (prefix pathname) (not (equal (enough-namestring pathname prefix) (namestring pathname))))
(defmethod output-files :around ((operation compile-op) (c source-file)) (let ((source (component-pathname c)) (paths (call-next-method))) (mapcar #'(lambda (path) (loop for (from to) in *system-configuration-paths* when (pathname-prefix-p from source) do (return (merge-pathnames (make-pathname :type (pathname-type path)) (merge-pathnames (enough-namestring source from) to))) finally (return path))) paths))) - I then started up a CL implementation and loaded the
"asdf-build.lisp" file. Next, I built XMLS:
CL-USER> (asdf:oos 'asdf:load-op :xmls) ; loading system definition from c:\usr\home\lisp\xmls-1.2\xmls.asd ; into #<The ASDF243 package> ; Loading c:\usr\home\lisp\xmls-1.2\xmls.asd ; registering #<SYSTEM :XMLS @ #x2055d3d2> as XMLS ;;; Compiling file c:\usr\home\lisp\xmls-1.2\xmls.lisp ;;; Writing fasl file c:\usr\home\lisp\bin\xmls.fasl ;;; Fasl write complete ; Fast loading c:\usr\home\lisp\bin\xmls.fasl NIL CL-USER>

