Clementson's Blog

Bits and pieces (mostly Lisp-related) that I collect from the ether.

December 2004
Sun Mon Tue Wed Thu Fri Sat
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
Nov  Jan

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:

  1. In my init file, I already had code to load ASDF and to set the asdf:*central-registry* variable (see my earlier posting)
  2. 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.
  3. 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)))
  4. 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> 
The generated XMLS fasl file was placed in the correct output directory. Another example of how specialized methods in CL allow us to extend standard functionality without any modifications to the underlying code!

emacs Copyright © 2005 by Bill Clementson