Description
Environment
Attachments
- compile-interop-1.patch30 Nov 2011, 09:54 AM
- write-classes-1.diff.gz11 Dec 2010, 06:34 AM
- 0322-limit-aot-resolved.patch29 Nov 2010, 10:18 PM
- CLJ-322.diff20 Nov 2010, 12:28 PM
Activity
import September 28, 2010 at 3:18 PM
Comment made by: importer
technomancy said: Looks good, but I'm having trouble getting it to work. I tried compiling from master of Chas's fork on github, but I still got the all the .class files generated with -Dclojure.compiler.transitive=false. It could be a quirk of the way I'm using ant to fork off processes though. Is it possible to set it using System/setProperty, or must it be given as a property on the command-line?
import September 28, 2010 at 3:18 PM
Comment made by: importer
cemerick said: A first cut of a change to address this issue is here (caution, work in progress!):
http://github.com/cemerick/clojure/commit/6f14e0790c0d283a7e44056adf1bb3f36bb16e0e
This makes available a new recognized system property, clojure.compiler.transitive, which defaults to true. When set/bound to false (i.e. -Dclojure.compiler.transitive=false when using clojure.lang.Compile), only the first loaded file (either the ns named in the call to compile or each of the namespaces named as arguments to clojure.lang.Compile) will have classfiles written to disk.
This means that this compilation invocation:
java -cp <your classpath> -Dclojure.compiler.transitive=false clojure.lang.Compile com.bar com.bazwill generate classfiles only for com.bar and com.baz, but not for any of the namespaces or other files they load, require, or use.
The only shortcoming of this WIP patch is that classfiles are still generated for proxy and gen-class classes defined outside of the explicitly-named namespaces. What I thought was a solution for this ended up breaking the loading of generated interfaces (as produced by defprotocol, etc).
I'll take a second look at this before the end of the week, but wanted to get this out there so as to get any comments people might have.
import September 28, 2010 at 3:18 PM
Comment made by: importer
cemerick said: This behaviour is an implementation detail of Clojure's AOT compilation process, and is orthogonal to any particular build tooling.
I am working on a patch that would provide a mechanism for such tooling to disable this default behaviour.
import September 28, 2010 at 3:18 PM
Comment made by: importer
hlship said: I'd like to reinforce this. I've been doing research on Clojure build tools for an upcoming talk and all of them (Maven, Leiningen, Gradle) have the same problem: the AOT compile extends from the desired namespaces (such as one containing a :gen-class) to every reached namespace. This is going to cause a real ugliness when application A uses libraries B and C that both depend on library D (such as clojure-contrib) and B and C are thus both bloated with duplicate, unwanted AOT compiled classes from the library D.
import September 28, 2010 at 3:18 PM
Comment made by: importer
Converted from http://www.assembla.com/spaces/clojure/tickets/322
Attachments:
aot-transitivity-option-compat-322.diff - https://www.assembla.com/spaces/clojure/documents/aI7Eu-HeGr35ImeJe5cbLA/download/aI7Eu-HeGr35ImeJe5cbLA
aot-transitivity-option-322.diff - https://www.assembla.com/spaces/clojure/documents/aIWFiWHeGr35ImeJe5cbLA/download/aIWFiWHeGr35ImeJe5cbLA
Why This Was Declined
The current behavior of transitive compilation is a valuable semantic. It is arguably essential to e.g. AOT protocols ahead of their call sites.
On the other hand, you should not ship AOT compiled classes for which your project is not the source. As worded in the original ticket:
"Having the option of shipping either all AOT-compiled classfiles or mixed source/AOT depending upon one's distribution requirements would make that phase of work with a clojure codebase significantly easier and less error-prone."
This latter goal can be accomplished by keeping "what you compile" and "what you ship" cleanly separate. The compiler does not know or care about the latter, and tools can automate this with e.g. boot's
sift.Historical Context
This was originally/erroneously reported by Howard Lewis Ship in the clojure-contrib assembla:
My build file specifies the namespaces to AOT compile but if I include another namespace (even from a JAR dependency) that is not AOT compiled, the other namespace will be compiled as well. In my case, I was using clojure-contrib's clojure.contrib.str-utils2 namespace, and I got a bunch of clojure/contrib/str_utils2 classes in my output directory. I think that the AOT compiler should NOT precompile any namespaces that are transitively reached, only namespaces in the set specified by the command line are appropriate. As currently coded, you will frequently find unwanted third-party dependencies in your output JARs; further, if multiple parties depend on the same JARs, this could cause bloating and duplication in the eventual runtime classpath.The only question in my mind is what the default should be. We're all used to the current behaviour, but I'd guess that any nontrivial project where the form of the distributable matters (i.e. the source/AOT mix), providing as much control as possible by default makes the most sense. Given the tooling that most people are using, it's trivial (and common practice, IIUC) to provide a comprehensive list of namespaces one wishes to compile, so making that the default shouldn't be a hurdle to anyone. If an escape hatch is desired, a --transitive switch to clojure.lang.Compile could be added.