From: Thom G. <tho...@ma...> - 2008-12-10 14:35:26
|
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 |