Also known as CLJ-322
Why do we AOT compile?
- To consume a Java API
- Concrete derivation (gen-class)
- Naming/packaging conventions
- To expose an API to Java code
- Deployment environments
- Special classloaders, e.g. OSGi, Eclipse
- Application delivery
- Main method (gen-class)
- Mitigated by "-m" option to clojure.main
- Bytecode post-processing
- Faster startup
- Only an issue in constrained environments like Android
- Hide source code from consumers
- Syntax check & reflection warnings
- Doesn't require writing files to disk
- But still a common use case for invoking the compiler
- Some tools support emitting .class files to temp dir
- e.g. Mark Derricutt's clojure-maven-plugin
What do we want to AOT-compile?
- Just a few things
- For the Interop case
- Or to shorten build times
- Not currently supported
- For the "Application delivery", "Syntax check", and "reflection warnings" cases
- Currently supported by
- Why is AOT-compilation transitive?
- Clojure does not support separate compilation
- All symbols must resolved at compile time
compile-files is a boolean
- The effects of transitive compilation when AOT-comipiling a namespace "A"
- When namespace A loads namespace B within the same project
- Namespace B is AOT-compiled and emitted
- When namespace A loads library C from external JAR
- Library C's namespaces are AOT-compiled and emitted alongside A's
- Build tools: filter unwanted .class files from JAR
- Ant, Maven, scripting
- Clojure itself does this, e.g. "slim" JAR
- Not commonly used
- Wastes time during builds to AOT-compile things which will be deleted
- Write Java
Finer-grained control of the compilation process
- A. Global flag for transitive/non-transitive compilation
- Chas Emerick's patch
- New system property "clojure.compiler.transitive"
- When true (default), preserves current behavior
- When false, only namespaces give as arguments to `compile` are emitted
- Doesn't handle classes created by deftype/record/etc.
- B. Specify exactly which .class files should be emitted
- Stuart Sierra's patch
- Specified as a Set of Strings, but could be any function, e.g. regex
- C. Global flag for compiling "interop" forms
- Is there a universal definition of what an "interop" form is?
- gen-class, obviously
- Does not require maintaining list of .class files to emit
- Could provide a convenient defaults for the common case
- Macros like "deftype" can opt in with metadata
- D. Metadata to control AOT-compilation
- Permits fine-grained control
- In-line with source code
- How to support multiple AOT-compilation strategies in a single build
- E.g. dev build only AOT-compiles interop forms, production AOT-compiles everything
Separate writing class files from compilation
- E. Compiler holds references to generated bytecode
- Not currently implemented in any patch
- After compilation, call function to emit .class files
- Will use lots of memory!
- Or will it? The JVM already has this stuff in memory
- Must disable in production!
- Brings us closer to a Smalltalk-like "program image"