In Leiningen I've added a workaround to CLJ-322 (AOT being transitive by default) in which .class files unrelated to the project are removed after compilation. The heuristic used is that a .class file is kept if its package exists as a directory or .clj file in the source tree of the project.
The problem here is that the project could have a dependency that includes a protocol that's not AOT'd. When the project is AOT'd it AOTs the dependency's protocol, and it seems to hard-code the project's .class files to point at the AOT'd interface, which is then deleted because it's not part of the project. I suppose this is not a problem outside AOT because during JIT looking up the protocol is always going to point to the right interface by definition. If there were a way to determine if a .class file contained a protocol without loading it that would be helpful, but it seems like a long shot.
Is there anything that can be done about this apart from fixing CLJ-322 ASAP? Is it too late for users of Clojure 1.2?
-Phil
I think the only solution for now is to avoid AOT compilation
altogether.
gen-class is the only situation where you need AOT compilation. If
possible, keep the one .class file emitted by gen-class and discard
everything else.
AOT-compiled Clojure code really helps me on Google App Engine. While
the Clojure compiler is fast, it still adds significant overhead when
running in an environment which constantly kills and starts new JVMs,
and has a hard 30-second request time limit. For the time being, I use
Leiningen's :keep-non-project-classes set to true, which works well.
Anyway, please don't deprecate non-gen-class AOT compilation.
AOT is appropriate and non-problematic in applications, but for
libraries it's important to avoid it as much as possible. Perhaps the
distinction of "end user" vs "upstream" needs to be made more
explicit, since clearly different approaches are needed in either
case.
-Phil