1. Problems with the :feature feature.
(asdf:defsystem foo :components ((:file "pkg") (:file "code") (:file "foo" :depends-on ((:feature :frob)))))
If :frob is not on *features*, load-system gives me:
Error: Bad dependency (FEATURE FROB). Dependencies must be (:version <version>), (:feature <feature>), or a name
If :frob is a *feature* I get a different error:
Error: Error component :FROB not found, required by #<CL-SOURCE-FILE "foo" #x8B7A3E6>
Did I misunderstand something?
2. Suppose I would like some code to run at compile-time / load-time to determine where the fasls should live (e.g. hypothetically, in a subdirectory named after a timestamp, or according to what patches I have loaded). How do I express this?
(I'm using version 1.363)
Thanks.
- nick
2009/9/30 Nick Levine ndl@ravenbrook.com:
- Problems with the :feature feature.
(asdf:defsystem foo :components ((:file "pkg") (:file "code") (:file "foo" :depends-on ((:feature :frob)))))
If :frob is not on *features*, load-system gives me:
Error: Bad dependency (FEATURE FROB). Dependencies must be (:version <version>), (:feature <feature>), or a name
If :frob is a *feature* I get a different error:
Error: Error component :FROB not found, required by #<CL-SOURCE-FILE "foo" #x8B7A3E6>
Did I misunderstand something?
Maybe what you want is #+frob (:file "foo")
- Suppose I would like some code to run at compile-time / load-time
to determine where the fasls should live (e.g. hypothetically, in a subdirectory named after a timestamp, or according to what patches I have loaded). How do I express this?
You can define your own :around method on output-files, and/or override default methods. See how ASDF-BINARY-LOCATIONS (now part of ASDF 1.366 and later) does it.
Note that with XCVB, you can :depends-on (:when (:featurep :frob) "foo") and you can xcvb --object-directory obj-$(timestamp) ...
[ François-René ÐVB Rideau | Reflection&Cybernethics | http://fare.tunes.org ] If a vegetarian eats vegetables, what does a humanitarian eat? -- Mark Twain
Maybe what you want is #+frob (:file "foo")
Ideally not, as you'd have to remember to reload all your .asd files every time you messed with features.
If this isn't what :feature does, then what is it for?
- Suppose I would like some code to run at compile-time /
load-time to determine where the fasls should live (e.g. hypothetically, in a subdirectory named after a timestamp, or according to what patches I have loaded). How do I express this?
You can define your own :around method on output-files, and/or override default methods. See how ASDF-BINARY-LOCATIONS (now part of ASDF 1.366 and later) does it.
Hmm, that's an improvement. (Otoh writing about a rapidly moving target is tricky. Each time I review this it's changed.)
Note that with XCVB, you can :depends-on (:when (:featurep :frob) "foo") and you can xcvb --object-directory obj-$(timestamp) ...
OK. So you still can't say: look for the :frob feature and decide whether to include this component?
Thanks,
- n
2009/9/30 Nick Levine ndl@ravenbrook.com:
Maybe what you want is #+frob (:file "foo")
Ideally not, as you'd have to remember to reload all your .asd files every time you messed with features.
If this isn't what :feature does, then what is it for?
I had never heard of it before. Looks like it's broken by design.
You can define your own :around method on output-files, and/or override default methods. See how ASDF-BINARY-LOCATIONS (now part of ASDF 1.366 and later) does it.
Hmm, that's an improvement. (Otoh writing about a rapidly moving target is tricky. Each time I review this it's changed.)
ASDF was a nice hack originally, but is lacking in many ways. Development has resumed, which is good, but it's not there yet. If you have feature requests, please present them.
Note that with XCVB, you can :depends-on (:when (:featurep :frob) "foo") and you can xcvb --object-directory obj-$(timestamp) ...
OK. So you still can't say: look for the :frob feature and decide whether to include this component?
Uh, that's what (:when (:featurep :frob) ...) does with XCVB, or #+frob in ASDF. As for reloading a system, you can probably manually (load "blah.asd") and try to re-operate with ASDF but that is not completely supported. Actually, re-compiling in general is not completely supported by the CL standard: changes to the package import tree, to the signature of generic functions, to the special or constant nature of variable bindings, to the class definition of structures being used, etc., are NOT supported and you have to manually clean things up if you're gonna do this (see the painful xcvb/no-asdf.lisp); and you also have to make sure the stuff you're layering on top of CL (compile-time dictionaries, etc.) does support the redefinitions you're going to make. That, and you have to recompile all the sites that use your redefined macros or inlined functions, recursively.
XCVB doesn't currently make at attempt to provide fake support in-image compilation, beside manually compiling and loading stuff including C-c C-k at your SLIME debug prompt. Because I think it's a failed concept in CL (for the reasons above). That said, the public seems to demand a bug-compatible upgrade path from ASDF, so I'll eventually give something to the public: it can't be guaranteed to work, but it just might if you didn't ask too much and you'll hopefully get an explicit error message if you did.
[ François-René ÐVB Rideau | Reflection&Cybernethics | http://fare.tunes.org ] (labels(({(] &rest [)(apply([ ])[))([(>)(elt(]())>))(](<)(do-external-symbols(] :cl)(push ] <))(sort <`string<`:key`string))(}({ + ^)({`816`1/5)({`688({`875({`398()"~{~A~^ ~}"(]())){(+ { +)))({`381)^))(do*(({`5248({`584 }`36063))([`874({`395 {`6))(]`4({`584 {`6))(}`#36RH4G6HUTA1NVC1ZHC({`395 }`36063)))((} [ ] ({`977 ]))({`902)({`381))))
Faré fahree@gmail.com writes:
2009/9/30 Nick Levine ndl@ravenbrook.com:
Maybe what you want is #+frob (:file "foo")
Ideally not, as you'd have to remember to reload all your .asd files every time you messed with features.
If this isn't what :feature does, then what is it for?
I had never heard of it before. Looks like it's broken by design.
Well, that's one possibility.
The reason that you don't want reader conditionals for implementation-specific files in a system description is that compilation and loading isn't the only thing that you do to a system. Another thing that you might do, for example, is package up the system, whether that is as a tarball or an operating-system package (e.g. a .deb). To do that from within a Lisp, you need to be able to see all the files, not just the ones that that particular lisp has *features* for; that's what the asdf:feature dependency allows you to encode.
(This isn't just theoretical; the long-forgotten CCLANv1 that operated as a bunch of .debs with common-lisp-controller support worked this way)
[Nick]
Hmm, that's an improvement. (Otoh writing about a rapidly moving target is tricky. Each time I review this it's changed.)
As far as I know, the :around output-files method way of customizing the output location of an asdf operation has worked for many, many years.
Cheers,
Christophe
Nick Levine ndl@ravenbrook.com writes:
- Problems with the :feature feature.
It's the "asdf:feature feature", not the ":feature feature".
(asdf:defsystem foo :components ((:file "pkg") (:file "code") (:file "foo" :depends-on ((:feature :frob)))))
If :frob is not on *features*, load-system gives me:
Error: Bad dependency (FEATURE FROB). Dependencies must be (:version <version>), (:feature <feature>), or a name
If :frob is a *feature* I get a different error:
Error: Error component :FROB not found, required by #<CL-SOURCE-FILE "foo" #x8B7A3E6>
Did I misunderstand something?
You'll probably also want :if-component-dep-fails :ignore, if the effect you want is for foo simply not to be loaded if :frob is not present on *features*.
- Suppose I would like some code to run at compile-time / load-time
to determine where the fasls should live (e.g. hypothetically, in a subdirectory named after a timestamp, or according to what patches I have loaded). How do I express this?
With an :around method on asdf:output-files. Note that this typically shouldn't live with any given system definition, but in your own init files or equivalent -- the philosophical point is that asdf the software merely describes the system and (approximately) how to build it, and it's a matter of local or user policy as to where the output files end up.
Best,
Christophe
- Problems with the :feature feature.
It's the "asdf:feature feature", not the ":feature feature".
If you're suggesting I can go
(:file "foo" :depends-on ((asdf:feature :frob)))
-- well, I tried it and the results weren't any different.
You'll probably also want :if-component-dep-fails :ignore, if the effect you want is for foo simply not to be loaded if :frob is not present on *features*.
Wouldn't that supress all sorts of genuine errors?
[...]
With an :around method on asdf:output-files.
Tried that, it didn't have any effect.
Never mind, I'll find something else to write about (uhm, some other aspects of ASDF, I mean).
- n
With an :around method on asdf:output-files.
Tried that, it didn't have any effect.
Ah, sorted. I had expected :output-files at the system level to do something useful.
- n
Nick Levine ndl@ravenbrook.com writes:
- Problems with the :feature feature.
It's the "asdf:feature feature", not the ":feature feature".
If you're suggesting I can go
(:file "foo" :depends-on ((asdf:feature :frob)))
-- well, I tried it and the results weren't any different.
Yeah. This has worked at some point in the past, but it certainly looks broken now. What with the change in development repository, vcs, history and management I can't track down how this was meant to work and why exactly it doesn't, but... it does seem like it's been broken for a long time.
You'll probably also want :if-component-dep-fails :ignore, if the effect you want is for foo simply not to be loaded if :frob is not present on *features*.
Wouldn't that supress all sorts of genuine errors?
The way I've used this in the past (in at least my recollection) is something like
(defsystem foo :components ((:module "impl-dep" :if-component-dep-fails :try-next :components (("sbcl" :depends-on ((feature :sbcl))) ("abcl" :depends-on ((feature :abcl))) ...)) (:module "actual-stuff" :depends-on "impl-dep" ...)))
[...]
With an :around method on asdf:output-files.
Tried that, it didn't have any effect.
At least here, doing
(defmethod asdf:output-files :around ((o asdf:compile-op) (c asdf:cl-source-file)) (let ((results (call-next-method))) (mapcar (lambda (x) (make-pathname :directory '(:absolute "tmp") :name (pathname-name x) :type (pathname-type x))) results)))
results in fasls being placed in /tmp/ rather than wherever they would normally have ended up. This is with asdf as distributed with SBCL; I'm afraid I'm not up to date with the changes that have been made to asdf development recently.
Cheers,
Christophe
Hi Nick,
- Problems with the :feature feature.
(asdf:defsystem foo :components ((:file "pkg") (:file "code") (:file "foo" :depends-on ((:feature :frob)))))
I haven't made time to read Christophe's and Faré's comments but I agree that this is broken in various ways. We'll add it to the list of things to fix.
- Suppose I would like some code to run at compile-time / load-time
to determine where the fasls should live (e.g. hypothetically, in a subdirectory named after a timestamp, or according to what patches I have loaded). How do I express this?
The output-files technique is the most flexible. However, as Faré said, ASDF now includes some measure of customization out of the box (1.365). See http://common-lisp.net/project/asdf/getting-started.html#header2-27 and http://common-lisp.net/project/asdf/manual.html#binary-locations
-- Gary Warren King, metabang.com Cell: (413) 559 8738 Fax: (206) 338-4052 gwkkwg on Skype * garethsan on AIM * gwking on twitter
Gary et al.,
Thanks for the feedback. I can do without mentioning features, I have too much to say already. But controlling output destinations is useful and I think (sigh) I'm going to have to upgrade this chapter of LOtB to asdf 1.365.
- nick
On Wed, 2009-09-30 at 14:30 +0100, Nick Levine wrote:
Gary et al.,
Thanks for the feedback. I can do without mentioning features, I have too much to say already. But controlling output destinations is useful and I think (sigh) I'm going to have to upgrade this chapter of LOtB to asdf 1.365.
Perhaps it would be a good idea to leave this chapter for the end, because by the time you finish the rest of the chapters many current bugs will have been fixed and possibly new features added.
Gary King wrote:
The output-files technique is the most flexible. However, as Faré said, ASDF now includes some measure of customization out of the box (1.365). See http://common-lisp.net/project/asdf/getting-started.html#header2-27 and http://common-lisp.net/project/asdf/manual.html#binary-locations
I am looking at asdf.texinfo and I see no discussion of binary locations. What's going on here?
Hi Robert,
On Sep 30, 2009, at 9:31 AM, Robert Goldman wrote:
Gary King wrote:
The output-files technique is the most flexible. However, as Faré said, ASDF now includes some measure of customization out of the box (1.365). See http://common-lisp.net/project/asdf/getting-started.html#header2-27 and http://common-lisp.net/project/asdf/manual.html#binary-locations
I am looking at asdf.texinfo and I see no discussion of binary locations. What's going on here?
Well, ... that's a long story <smile>.
Perhaps rashly, I moved ASDF's documentation into CL-Markdown without discussion quite a few months ago and have incorporated your patches, etc. there.
The current live docs are in website/source.
I understand your concerns about the move but I also know that maintaining the docs as they are now is a lot easier for me...
For now, I'd like to keep the docs in CL-Markdown and think about moving them back into TexInfo when time permits.
-- Gary Warren King, metabang.com Cell: (413) 559 8738 Fax: (206) 338-4052 gwkkwg on Skype * garethsan on AIM * gwking on twitter
I'll take a look at the markdown docs and see if I can supply a patch that puts the material back into texinfo. Texinfo isn't perfect, but it works with my toolchain and I can read it offline, whereas I can't read markdown except off the website...
Sent from my iPod
On Oct 1, 2009, at 19:52, Gary King gwking@metabang.com wrote:
Hi Robert,
On Sep 30, 2009, at 9:31 AM, Robert Goldman wrote:
Gary King wrote:
The output-files technique is the most flexible. However, as Faré said, ASDF now includes some measure of customization out of the box (1.365). See http://common-lisp.net/project/asdf/getting-started.html#header2-27 and http://common-lisp.net/project/asdf/manual.html#binary-locations
I am looking at asdf.texinfo and I see no discussion of binary locations. What's going on here?
Well, ... that's a long story <smile>.
Perhaps rashly, I moved ASDF's documentation into CL-Markdown without discussion quite a few months ago and have incorporated your patches, etc. there.
The current live docs are in website/source.
I understand your concerns about the move but I also know that maintaining the docs as they are now is a lot easier for me...
For now, I'd like to keep the docs in CL-Markdown and think about moving them back into TexInfo when time permits.
-- Gary Warren King, metabang.com Cell: (413) 559 8738 Fax: (206) 338-4052 gwkkwg on Skype * garethsan on AIM * gwking on twitter
In version 1.366 I see the following:
(do-dep (op dep) (cond ((eq op 'feature) (or (member (car dep) *features*) (error 'missing-dependency :required-by c :requires (car dep)))) (t (dolist (d dep) (cond ((consp d) (cond ((string-equal (symbol-name (first d)) "VERSION") (appendf forced (do-one-dep op (second d) (third d)))) ((and (string-equal (symbol-name (first d)) "FEATURE") (find (second d) *features* :test 'string-equal)) (appendf forced (do-one-dep op (second d) (third d)))) (t (error "Bad dependency ~a. Dependencies must be (:version <version>), (:feature <feature>), or a name" d)))) (t (appendf forced (do-one-dep op d nil))))))))
I really wish there was a comment here, since I don't know why there are two branches that seem to handle feature, and that handle it differently (why does the former just eq match and the latter do the more careful string-equal testing?).
Looks like there might be two ways that :feature is trying to be handled --- one where it's (feature <feat>) and one where it's (feature <feat> <dep>).
Alas, the manual does not seem to clarify this. This, I think is a problem with the manual's design. In the discussion of DEFSYSTEM we have two example pages, and then we have the grammar. The grammar specifies the /syntax/ of defsystem, but there really isn't any way to specify the /semantics/ of bits of defsystem. Note that the operations (object model) bit of the manual does /not/ serve this purpose. It would be OK for us to specify the semantics in terms of those operations, but we do not do so. If we were to do so we would need to add a section that bridges from the syntax to the object model by specifying how the syntax gets rewritten into the object model.
I would not favor defining the semantics in terms of the object model, although this would be a principled thing to do. I believe that ASDF users should be able to use ASDF at some limited level without having to fully understand the object model.
Proposal: In my copious free time, I will work to add a page to the manual that comes /after/ the defsystem grammar and that describes the semantics of the defsystem form. Please jump in and object now if you think that this would be A Bad Idea, as I'd rather not waste my time if the community thinks this would not be worth doing.
Best, Robert
2009/9/30 Robert Goldman rpgoldman@sift.info:
I really wish there was a comment here, since I don't know why there are two branches that seem to handle feature, and that handle it differently (why does the former just eq match and the latter do the more careful string-equal testing?).
The answer is that first case handles things like
:in-order-to ((compile-op (feature :foo)))
and the second -- which is not the atm -- would handle things like
:depends-on ((feature :foo))
...both are best combined with :if-componend-dep-fails :try-next
so you can do things like
(:module "ports" :if-component-dep-fails :try-next :components ((:file "sbcl" :in-order-to ((compile-op (feature :sbcl)))) (:file "ccl" :in-order-to ((compile-op (feature :ccl))))))
Cheers,
-- Nikodemus