Dear Orivej,
I believe this is a bug in CFFI, and ASDF cannot do much about it. I'm copying the CFFI-devel mailing-list.
I'm not convinced that these pathnames with invalid namestring would have a valid native-namestring (did you try?), and using native-namestring in asdf/cache:normalize-namestring would be quite impractical, since the function CL:FILE-WRITE-DATE that we subsequently use requires a Lisp namestring.
The correct thing to do would be for CFFI to assume ASDF3 (which has been out for almost 2 years and has since been adopted by all maintained implementations), and use this definition:
(defun exe-filename (defaults) (let ((defaults (uiop:ensure-pathname defaults :namestring :native :want-non-wild t :want-file t))) ;; YMMV (uiop:subpathname defaults (uiop:parse-unix-namestring (pathname-name defaults) :type *exe-extension*)))
NB: if ASDF3 is adopted, the #+sbcl and other such kluges in cffi.asd could also be replaced by :if-feature :sbcl, the defmethod for operation-done-p should be dropped, and the defmethod perform could be replaced by: (defsystem "cffi" ... :in-order-to ((test-op (test-op "cffi-tests")))) and cffi-tests could similarly use an inline method :perform (test-op (o c) ...) instead of a defmethod.
PS: the reason why SBCL (and many other implementations) have unprintable pathnames is because of the read-write consistency requirements for pathnames, which for the CLHS (see *print-readably* entry) specifies must be WRITE-n in a way that they must be read back as a "similar" object, which section 3.2.4.2.2 specifies as component-wise similarity, so that (make-pathname :name "foo.bar" :type nil) MUST NOT have the same readable representation as (make-pathname :name "foo" :type "bar").
—♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• http://fare.tunes.org The most exciting phrase to hear in science, the one that heralds new discoveries, is not "Eureka!" (I found it!) but "That's funny ..." — Isaac Asimov
On Tue, Nov 25, 2014 at 11:24 AM, Orivej Desh c@orivej.org wrote:
Currently, between CFFI-GROVEL and ASDF, neither normalizes pathnames with a dot in :NAME and NIL in :TYPE.
(cffi-grovel:grovel-file "grovel.cffi")
in a system definition may cause an error under SBCL in ASDF/CACHE:NORMALIZE-NAMESTRING when it calls NAMESTRING on the value of CFFI-GROVEL::EXE-FILENAME:
Calling
(cffi-grovel::exe-filename #p"grovel.cffi.lisp")
returns
#<pathname (with no namestring) :HOST #<sb-impl::unix-host {10002ACE43}> :DEVICE nil :DIRECTORY (:relative ".") :NAME "grovel.cffi" :TYPE nil :VERSION :newest>
to ASDF/ACTION:COMPUTE-ACTION-STAMP which can't deal with it when called with :JUST-DONE NIL.
Backtrace: http://report.quicklisp.org/cl-libssh2/2014-09-26/failtail.txt
One solution is to make CFFI-GROVEL::EXE-FILENAME normalize resulting pathname: https://github.com/cffi/cffi/pull/52
Another is to make ASDF/CACHE:NORMALIZE-NAMESTRING call NATIVE-NAMESTRING instead of NAMESTRING.
Who should be responsible for normalizing such a pathname, ASDF of CFFI-GROVEL?
- REPLICATION:
Would you please let me know how to replicate this error?
I was hoping that (ql:quickload "libssh2") would get this for me, but not in my current client.
I can replicate it reliable by cleaning (renaming, actually) ~/.cache/common-lisp and loading libssh2. Is there another way to ensure that COMPUTE-ACTION-STAMP is called with :JUST-DONE NIL? (I don't understand how exactly this affects JUST-DONE, but it does.)
* * *
I'm not convinced that these pathnames with invalid namestring would have a valid native-namestring (did you try?)
They have:
(uiop:native-namestring (make-pathname :name "a.b" :type nil)) => "a.b"
using native-namestring in asdf/cache:normalize-namestring would be quite impractical, since the function CL:FILE-WRITE-DATE that we subsequently use requires a Lisp namestring.
I anticipated this would be a problem. So, NATIVE-NAMESTRING is not acceptable.
I believe this is a bug in CFFI, and ASDF cannot do much about it. I'm copying the CFFI-devel mailing-list.
I hoped that ASDF would smooth out working with pathnames for CFFI-GROVEL as much as possible; providing UIOP seems to be this much.
(defun exe-filename (defaults) (let ((defaults (uiop:ensure-pathname defaults :namestring :native :want-non-wild t :want-file t))) ;; YMMV (uiop:subpathname defaults (uiop:parse-unix-namestring (pathname-name defaults) :type *exe-extension*)))
Thank you for this example.
If DEFAULTS is a pathname of an existing file, ENSURE-PATHNAME seems unnecessary. Under this assumption, the following definition appears equivalent:
(defun exe-filename (defaults) (uiop:parse-unix-namestring (pathname-name defaults) :type *exe-extension* :defaults defaults))
(N.B. Neither definition prepends "./" to relative paths.)