Response from Phoebe Goldman hand-forwarded because of problems with
common-lisp.net's email server:
A few things.
1. ECHO-OP should not be selfward. SELFWARD-OPERATION is for (OPERATION
COMPONENT) pairs which depend on (DIFFERENT-OPERATION COMPONENT) for the same
COMPONENT. For example, LOAD-OP is selfward with respect to COMPILE-OP, because
in order to perform (load-op FILE), you must first perform (compile-op FILE).
Your ECHO-OP has no such dependency. In this case, I believe you want ECHO-OP
to be downward and sideways, meaning that (ECHO-OP MODULE) depends on (ECHO-OP
MODULE-COMPONENT) for each of the children MODULE-COMPONENTs of the MODULE, and
that (ECHO-OP SOURCE-FILE) depends on (ECHO-OP EARLIER-SOURCE-FILE) for each of
the EARLIER-SOURCE-FILEs in SOURCE-FILE's :DEPENDS-ON list. This way, when you
call (OPERATE 'ECHO-OP (FIND-SYSTEM "whatever")), ASDF will do a depth-first
dependency-order traversal of your system.
2. Your COMPONENT-DEPENDS-ON method is wrong. No pair of (OPERATION COMPONENT)
should ever depend on the same (OPERATION COMPONENT). What you're saying is,
"in order to perform (ECHO-OP FILE), you must first perform (ECHO-OP FILE)."
3. For operations that subclass one or more of DOWNWARD- UPWARD- SIDEWAY-
SELFWARD- or NON-PROPOGATING-OPERATION, you don't need to define a
COMPONENT-DEPENDS-ON method.
4. Most (OPERATION COMPONENT) pairs have very uninteresting sets of input
files. (COMPILE-OP CL-SOURCE-FILE) has one input file, the .lisp source file.
(LOAD-OP CL-SOURCE-FILE) has one input file, the .fasl compiled file. (ECHO-OP
CL-SOURCE-FILE) will have no input files at all, unless you define a method on
INPUT-FILES to list them.
I think the following definition of ECHO-OP might be enlightening to you:
```
(uiop:define-package :echo-op
(:use :cl)
(:export #:echo-op))
(in-package :echo-op)
(defclass echo-op (asdf:sideway-operation asdf:downward-operation) ())
(defun print-input-files (op c)
(format t "~&Operation ~a on component ~a has input files:~{~% ~a~}~%"
op c (asdf:input-files op c)))
(defun print-dependencies (op c)
(format t "~&Operation ~a on component ~a depends on ~{~% ~a~}~%"
op c (asdf:component-depends-on op c)))
(defmethod asdf:perform ((op echo-op) c)
(flet ((do-operations (thunk)
(funcall thunk op c)
(funcall thunk (asdf:make-operation 'asdf:compile-op) c)
(funcall thunk (asdf:make-operation 'asdf:load-op) c)))
(format t "~&~%Input files for component ~a with a variety of
operations:~%~%" c)
(do-operations #'print-input-files)
(format t "~&~%Dependencies for component ~a with a variety of
operations:~%~%" c)
(do-operations #'print-dependencies)))
```
Note that:
1. The only method I have defined is on PERFORM, and it is a primary method,
not an :AROUND method. ASDF already has all the COMPONENT-DEPENDS-ON methods I
need.
2. I print the COMPONENT-DEPENDS-ON list in addition to the INPUT-FILES list.
3. I print both the COMPONENT-DEPENDS-ON and INPUT-FILES lists for all three of
ECHO-OP, COMPILE-OP and LOAD-OP.
I recommend you load this version, try (ASDF:OPERATE 'ECHO-OP:ECHO-OP
(ASDF:FIND-SYSTEM "echo-op-test") :FORCE T) and see what output you get.
cheers,
phoebe
> On Apr 26, 2022, at 3:40 AM, zacque <[email protected]
> <mailto:[email protected]:
>>>
> Hi,
>>>
> I'm trying to learn how ASDF object model works by defining a simple
> operation "echo-op". I want it to print out pathnames of all loaded lisp
> files to *standard-output*. It sounds like a simple task, but I couldn't
> get it to work. Thus I'm asking for help here.
>>>
> To do that, I define a project:
> ----------- file: echo-op.asd -------------------
> (defsystem #:echo-op
> :components
> ((:file "package")
> (:file "echo-op")))
> -------------------------------------------------
>>>
> ----------- file: package.lisp -------------------
> (defpackage #:echo-op
> (:use #:cl #:asdf)
> (:export
> #:selfward-echo-op))
> -------------------------------------------------
>>>
> ----------- file: echo-op.lisp -------------------
> (in-package #:echo-op)
>>>
> (defclass selfward-echo-op (selfward-operation)
> ())
>>>
> (defmethod asdf:component-depends-on ((op selfward-echo-op) c)
> `((selfward-echo-op ,c) ,@(call-next-method)))
>>>
> (defmethod asdf:output-files ((op selfward-echo-op) c)
> nil)
>>>
> (defmethod asdf:perform :around ((op selfward-echo-op) c)
> (let ((input-files (asdf:input-files op c)))
> (loop for file in input-files
> do (format t "~s" file))))
>>>
> (setf (find-class 'asdf::selfward-echo-op) (find-class 'selfward-echo-op))
> -------------------------------------------------
>>>
> Then, if I run these from the REPL:
> ----------- REPL -------------------
> CL-USER> (asdf:load-system :echo-op :force t)
> ; compiling file
> ; compilation finished in 0:00:00.004
> ; compiling file
> ; wrote
> ; compilation finished in 0:00:00.036
> T
> CL-USER> (asdf:operate 'asdf::selfward-echo-op :echo-op-test)
> ; Evaluation aborted on
> #<SB-PCL::NO-APPLICABLE-METHOD-ERROR {1002341273}>.
> -------------------------------------------------
>>>
> I got the error:
> ----------- SLIME *sldb* -------------------
> The slot ASDF/ACTION:SELFWARD-OPERATION is unbound in the object
> #<SELFWARD-ECHO-OP >.
> [Condition of type UNBOUND-SLOT]
> -------------------------------------------------
>>>
> The "echo-op-test" system is simply:
> ----------- file: echo-op-test.lisp -------------------
> (defsystem #:echo-op-test
> :defsystem-depends-on (#:echo-op)
> :components
> ((:file "package")
> (:file "example")
> (:file "main")))
> -------------------------------------------------
> with empty files package.lisp, example.lisp, and main.lisp.
>>>
> Now, if I redefine selfward-echo-op to subclass load-op, I got this
> error instead:
> ----------- SLIME *sldb* -------------------
> Circular dependency of
> #1=(#<ECHO-OP:SELFWARD-ECHO-OP >
> . #<ASDF/SYSTEM:SYSTEM "echo-op-test">)
> on:
> (#1#)
> [Condition of type ASDF/ACTION:CIRCULAR-DEPENDENCY]
> -------------------------------------------------
> which I have no idea what is going on.
>>>
> I'm still learning about ASDF, so any help to achieve what I want to do
> would be very much appreciated.
>>>
> Thanks!
>>>
> --
> Regards,
> zacque
>>>
>>
>
>
>