Clementson's Blog

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

November 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
Oct  Dec

Locating ASDF packages on Win32

Saturday, November 13, 2004

On c.l.l., Mark Carter asked:

"The Standard Operating Procedure for ASDF is that there is a soft link from an .asd file in the systems directory to its source directory. The problem is that Windows XP doesn't have soft links (it has 'shortcuts', but those are not the same thing).

Is there a convenient solution to this problem; preferrably something that doesn't involve a whole edifice of plumbing?"
This is a common problem for Win32 ASDF users. Some people choose to manually specify where the Lisp package locations are (see step#5 in this post for an example of this); however, this is inconvenient and gets to be a hassle after a while. Everytime you download a new package or a new version of an existing package that you are using, you have to remember to update your asdf:*central-registry* variable and that's a real bore. Edi Weitz suggested a number of alternatives:
"There are several ways, I think. None of them is as convenient as the Unix way, though.
  1. With newer versions of Windows on NTFS file systems you can create 'hard links' with tools like these:

    http://hermann.schinagl.tripod.com/nt/hardlinkshellext/hardlinkshellext.html http://www.rekenwonder.com/linkmagic.htm

  2. I have something like this in my LispWorks initialization file
         #+:asdf
         (dolist (dir-candidate (directory "c:/home/lisp/*"))
           (when (lw:file-directory-p dir-candidate)
             (let ((asd-candidate (merge-pathnames "*.asd" dir-candidate)))
               (when (directory asd-candidate)
                 (push dir-candidate asdf:*central-registry*)))))

    and obviously put all libraries into the c:/home/lisp/ directory.

  3. I describe a similar approach here:

    http://weitz.de/asdf-install/#load-asdf-install
2 and 3 suffer from the fact that they won't automatically find the newest version if you have libraries foo-1.3 and foo-1.4 installed. But then again, if you use (soft or hard) links you have to update them, too."
I liked Edi's approach#2 since (like Edi) I also keep all of my ASDF-installable packages under a single directory. However, Edi's code only works properly for LispWorks. Since I also use ACL and CLISP, I put the following in my initialization file:
(defvar *lisp-dirs* "c:/usr/home/lisp/" "Root location of CL library installs")
(load (concatenate 'string *lisp-dirs* "asdf/asdf.lisp"))

#+allegro (dolist (dir-candidate (directory (concatenate 'string *lisp-dirs* "*"))) (when (file-directory-p dir-candidate) (let ((asd-candidate (merge-pathnames "*.asd" (pathname-as-directory dir-candidate)))) (when (directory asd-candidate) (push (pathname-as-directory dir-candidate) asdf:*central-registry*)))))
#+lispworks (dolist (dir-candidate (directory (concatenate 'string *lisp-dirs* "*"))) (when (lw:file-directory-p dir-candidate) (let ((asd-candidate (merge-pathnames "*.asd" dir-candidate))) (when (directory asd-candidate) (push dir-candidate asdf:*central-registry*)))))
#+clisp (dolist (dir-candidate (directory (concatenate 'string *lisp-dirs* "*/"))) (let ((asd-candidate (merge-pathnames "*.asd" dir-candidate))) (when (directory asd-candidate) (push dir-candidate asdf:*central-registry*))))

Thanks Edi, life is suddenly easier! :-)

Update-2004-11-14: Edi Weitz pointed out that one should load "asdf" rather than "asdf.lisp" so that the compiled file is loaded if it is available. There used to be some problem with LispWorks or CLISP and loading the compiled asdf file; however, the problem no longer exists on current versions of these CL's. He also sent me his version of the ACL code. His version is similar to mine but avoids having to call PATHNAME-AS-DIRECTORY twice:
(dolist (dir-candidate (directory "c:/home/lisp/*" :directories-are-files nil))
    (when (excl:file-directory-p dir-candidate)
      (let ((asd-candidate (merge-pathnames "*.asd" dir-candidate)))
        (when (directory asd-candidate)
          (push dir-candidate asdf:*central-registry*)))))

emacs Copyright © 2005 by Bill Clementson