Creating output directories with asdf

Kevin Rosenberg <[email protected]>
Newsgroups gmane.lisp.cclan.general
Message-ID <[email protected]>
Hello CCLAN guys,

Adding support to clc for asdf files without :pathname's, I've
enountered trouble adsf system's that have module components. These
modules refer to output directories that don't yet exist, so cclan and
asdf fails because the output directory does not exist. One solution
is to have output-files routine automaticlly ensure the existence of
output directory. This can be done like,

(defmethod output-files ((operations compile-op) (c cl-source-file))
  (let ((bin-file (compile-file-pathname src-file)))
    (ensure-directory-exists (pathname-directory bin-file))
    (list bin-file)))

This part is easy, the hard part is the non-portable
ENSURE-DIRECTORY-EXISTS function.  The first solution below is nice
because it is short and uses an impl-dependent functions already in
asdf. Unfortunately, it is limited to unix (and maybe even GNU's mkdir
command with the -p option).

(defmethod ensure-directory-exists-1 (dir)
  (run-shell-command (format nil "mkdir -p ~A" (namestring
                                                (make-pathname
						dir)))))

The second solution has the advantage of working with any OS and not
requiring a shell subcommand, but is longer and adds two more
impl-dependent functions that I recycled from CLOCC.

(defmethod ensure-directory-exists-2 (dir)
  (dotimes (i (length dir))
    (let ((dpath (make-pathname
                  :directory (subseq dir 0 (1+ i)))))
      (unless (probe-directory dpath)
        (format *trace-output* ";; Making directory ~S" dpath)
        (mkdir dpath)))))

(defun probe-directory (filename)
  "Check whether the file name names an existing directory."
  (let* ((path (pathname filename))
         (name (pathname-name path))
         (type (pathname-type path))
         (new-dir
          (cond ((and name type) (list (concatenate 'string name "."
	  type)))
                (name (list name))
                (type (list type))
                (t nil))))
    (when new-dir
      (setq path (make-pathname
                  :directory (append (pathname-directory path)
		  new-dir)
                  :name nil :type nil :defaults path)))
    #+allegro (excl::probe-directory path)
    #+clisp (values
             (ignore-errors
              (#+lisp=cl ext:probe-directory #-lisp=cl
	      lisp:probe-directory
                         path)))
    #+cmu (eq :directory (unix:unix-file-kind (namestring path)))
    #+lispworks (lw:file-directory-p path)
    #+sbcl (eq :directory (sb-unix:unix-file-kind (namestring path)))
    #-(or allegro clisp cmu lispworks sbcl)
    (probe-file path)))


(defun mkdir (dir)
  #+allegro (excl:make-directory dir)
  #+clisp (#+lisp=cl ext:make-dir #-lisp=cl lisp:make-dir dir)
  #+cmu (unix:unix-mkdir (directory-namestring dir) #o777)  
  #+lispworks (system:make-directory dir)
  #+sbcl (sb-unix:unix-mkdir (directory-namestring dir) #o777)
  #-(or allegro clisp cmu lispworks sbcl)
  (error 'not-implemented :proc (list 'mkdir dir)))


So, what do you think? Should one of the functions go into asdf?  I
think the answer is yes. I learn towards the former because of it's
brevity.

--
       Kevin Rosenberg        |  .''`.  ** Debian GNU/Linux **
  http://b9.com/debian.html   | : :' :      The  universal
  GPG signed and encrypted    | `. `'      Operating System
     messages accepted.       |   `-    http://www.debian.org/





-------------------------------------------------------
Sponsored by: AMD - Your access to the experts on Hammer Technology! 
Open Source & Linux Developers, register now for the AMD Developer 
Symposium. Code: EX8664 http://www.developwithamd.com/developerlab
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.