Re: How do I replace my broken ':perform' forms?
Thom Goodsell <[email protected]> Wed, 10 Dec 2008 09:35:16 -0500
| Newsgroups | gmane.lisp.cclan.general |
|---|---|
| Message-ID | <[email protected]> |
On Dec 8, 2008, at 11:47 AM, Robert Goldman wrote: > Thom Goodsell wrote: >> Sorry if this has been covered, or if it's just really obvious, but I >> couldn't find anything helpful in the archives. >> >> I recently (i.e., about 15 minutes ago) got a new version of >> asdf.lisp >> when I updated my copy of ccl, and it broke a behavior I've been >> using. I *believe* that I was using the behavior incorrectly, and >> that >> the change was a bugfix, though I could be misunderstanding the svn >> logs. >> >> In my defsystem, I have the following bit of code: >> >> :perform (load-op :before (op c) >> ;; the before method runs after dependencies are loaded, >> ;; but before the components are loaded, so clsql-mysql is >> available >> (pushnew #p"/usr/local/mysql/lib/" ; local development >> (symbol-value (find-symbol "*FOREIGN-LIBRARY-SEARCH-PATHS*" >> :clsql-sys))) >> (asdf:oos 'asdf:load-op 'clsql-mysql)) >> >> It appears, now, that my comment is not correct. The idea is that I >> want to load all the systems from :depends-on, which includes clsql. >> Then I want to set up clsql-sys:*foreign-library-search-paths* to >> include the correct version of the MySQL libraries. Finally, I want >> to >> load the mysql components of clsql. >> >> Does anyone have advice on the Right Way (or even just a good way) to >> do this? >> > > If I understand correctly, this won't work because the system itself > undergoes the perform operation only /after/ all of its components > undergo that operation. I.e., if you have a system S with > components A > and B, you'll see something like > > (perform <op> A) (perform <op> B) (perform <op> C) > > This has been a perpetual source of friction in using ASDF to do > non-standard things. For example, this is why I can't write > an :around > method to dynamically bind a variable over the entire set of > operations > on a system. > > What would be nice would be if the ASDF plan were to include a > hierarchical structure something like: > > (perform <composite-op> S > :children > ((perform <op> A) > (perform <op> B) > (perform <op> C))) > > It's not obvious how to do this, though, since I think one could end > up > with complex plans where the loading operations for a single component > (S) are non-contiguous. > > There are various unpleasant kludges around this. For your case, I > would suggest making a faux system something like > > (defsystem clsql-version-identifier > :depends-on (:clsql) > :perform ... generalization of your :before method here... > ) > > Then make your *real* system depend on clsql-version-identifier. > > Note that I have NOT tried this, and I have a vague memory that ASDF > may > behave oddly when given a system that has no components. You'll > have to > investigate this yourself. > > Alternatively, can't you just define a method like > > (defmethod perform :after ((op load-op) (c (find-system 'clsql- > mysql))) > ....) For the record, this was the approach I ended up using (though the proper specialization is "(eql (find-system 'clsql-mysql))". After considering the other recommendations, this seemed like the best option for me. I do not intend to distribute this system (it's the key piece of our corporate IP), and my personal preference is to keep system startup as simple as possible, which I felt means keeping this functionality within the asd file so my start script can just load the system and start. Thanks, all, for the suggestions. Thom ------------------------------------------------------------------------------ SF.Net email is Sponsored by MIX09, March 18-20, 2009 in Las Vegas, Nevada. The future of the web can't happen without you. Join us at MIX09 to help pave the way to the Next Web now. Learn more and register at http://ad.doubleclick.net/clk;208669438;13503038;i?http://2009.visitmix.com/