Log in

No account? Create an account

More irritant-reduction

In SBCL, ASDF hooks into the REQUIRE mechanism so you can type (require 'mysystem). On other systems you can also figure out a way to hook REQUIRE, so you can avoid typing (asdf:oos 'asdf:load-op 'mysystem).

I got tired of trying to figure out how to do this in different ways on different Lisp systems, so below is a file I've been loading from my init files to get consistent, concise ASDF loading across implementations. It also adds a crude registry maintenance system and a way to reload a system without using :FORCE. :FORCE has the downside of recompiling and reloading all other dependencies, which is never what I want.

It's a work in progress, but so far I've been pretty happy using (asdf:load* 'mysystem) and (asdf:reload 'mysystem). YMMV.

(require 'asdf)

(in-package #:asdf)

(export '(load* reload register register-permanently))

(defvar *registry-file*
  (merge-pathnames (make-pathname :directory '(:relative "asdf")
                                  :name "registry"
                                  :type "sexp")

(eval-when (:compile-toplevel :load-toplevel :execute)
  (let ((registry (probe-file *registry-file*)))
    (when registry
      (with-open-file (stream registry)
        (loop for form = (read stream nil)
              while form do (push form *central-registry*))
        (setf *central-registry*
              (remove-duplicates *central-registry* :test #'equalp))))))

(defun load* (system &key verbose)
  (oos 'load-op system :verbose verbose)

(defun reload (system)
  (let ((name (coerce-name system)))
    (remhash name *defined-systems*)
    (load* name)))

(defun register (form)
  (pushnew form *central-registry* :test #'equalp))

(defun register-permanently (form)
  (register form)
  (ensure-directories-exist *registry-file*)
  (with-open-file (stream *registry-file*
                   :direction :output
                   :if-exists :append
                   :if-does-not-exist :create)
    (prin1 form stream)
    (terpri stream)))

;;; Automatically recompile stale FASLs

(handler-bind ((style-warning #'muffle-warning))
  (defmethod perform :around ((o load-op) (c cl-source-file))
    (handler-case (call-next-method o c)
      (#+sbcl sb-ext:invalid-fasl
       #-sbcl error ()
       (perform (make-instance 'compile-op) c)

Do you have any ugly local hacks that you think aren't polished enough to share, but that make your life much easier? Share them anyway, and let's clean them up and use them and improve life everywhere.




This bit isn't writted in lisp, but I've hacked up Cusp so that when I start sbcl it scans my libraries directory and pushes all folders in there onto asdf:*central-registry*. It cuts out the annoyance of adding a new library and then having to make a symlink for it, plus it works on Windows.

-Tim Jasko
I've also heard of doing a custom system-search-function that does something like that, too.

Why not do it in a lisp init file, though?


No compelling reason. One wrinkle is that I don't really know beforehand what folder Cusp is installed in, so even if the bulk of the function were written in lisp, I'd still need to call some function from Cusp to pass in the directory to search.

In the end, I think it boiled down to the fact that I already knew all the Java functions for dealing with the file system. It wasn't a terribly interesting bit of code, but at least it didn't take long to write.

-Tim Jasko



Wasn't somebody (ITA?) working on a better alternative to ASDF? The CL package system is incredibly flexible, but the price of that is complexity. I've never managed to learn how to do even the basics with it. And ASDF has some of the worst documentation I've ever seen in a library. :/

Also, "(asdf:load* 'mysystem)" is great. I'm sure we've all done that independently by now, which kind of makes the "ASDF is designed to be an extensible system" answer in their FAQ look like a complete non sequitur. :-)


The package system is pretty simple. ASDF is, in my humble opinion, too flexible to build much infrastructure on.


REPL commands for ASDF

We use both SBCL and ACL at my company, so we have code like this:
(defmacro defalias (name vars &body forms)
  #+(or allegro sbcl)
  `(#+allegro top-level:alias #+sbcl sb-aclrepl:alias
	      ,(string-downcase (symbol-name name)) ,vars ,@forms)
  #-(or allegro sbcl)

(defalias acs (system-name &optional force)
  "Compile system using ASDF"
  (asdf:oos 'asdf:compile-op system-name :force force))
(defalias als (system-name &optional force)
  "Load system using ASDF"
  (asdf:oos 'asdf:load-op system-name :force force))
(defalias ats (system-name &optional force)
  "Test system using ASDF"
  (asdf:oos 'asdf:test-op system-name :force force))

Re: REPL commands for ASDF

I use sb-aclrepl whenever I'm not in slime, but 90% or more of my time is spent in slime. It pays off more for me to make short functions that work both in the nude repl and in slime.


quickie for asdf :force issue