Ahead-of-time (AOT) compilation runs Clojure compilation before the application starts and caches the result as class files on disk. Use `compile` on a namespace, or invoke `clojure.lang.Compile` from the command line. Generated files go under `*compile-path*` (by default, `classes`); when both class files and sources are present, the class files take precedence. section 17.4
Choose AOT when its deployment benefits outweigh its constraints:
- It can reduce startup time, avoid distributing Clojure sources, and make generated classes available to Java and other JVM languages. section 17.4
- Generated classes are tied to a particular Clojure-JVM version. Builds must track which sources need recompilation, and tests can miss problems in code they never evaluate. section 17.4
Compile a namespace
Given a classpath-visible `source.clj` containing `(ns source)` and `(defn plus [x y] (+ x y))`, evaluate `(compile 'source)`; it returns `source` and writes class files for the namespace and its functions under `*compile-path*`. The generated classes can then be found through the classpath. section 17.4
For Java-facing entry points, `gen-class` works with AOT compilation to put a physical class on disk. Declaring `:main true` alone is insufficient: the associated namespace must also define `-main`, or calling the generated `main` fails. A `gen-class` call made directly in an already-running REPL does not generate the class; compile a file containing the declaration instead. `deftype`, by contrast, can generate types without AOT, though AOT can export them for Java use. section 15.3 section 15.4
(spit (str *compile-path* "/bookgenclass.clj")
"(ns bookgenclass)
(gen-class :name book.GenClass
:main true)
(defn -main [& args] ; #1
(println \"Hello from Java!\"))")
(compile 'bookgenclass) ; #2
(GenClass/main (make-array String 0)) ; #3
;; Hello from Java!
Compile a namespace that declares a Java `main` class and implements `-main`; calling the generated method prints `Hello from Java!`. section 15.3
Compilation time is also an evaluation boundary. `compile` binds `*compile-files*` to true, so initialization that depends on the deployment machine can be guarded until runtime; `delay` is another option but requires an explicit dereference. Compile-time bindings can change generated behavior: binding `*assert*` to false while compiling disables those assertions, and binding `clojure.test/*load-tests*` to false prevents colocated test functions from being generated. section 23.6 section 23.4
;; export CLOJURE_JAR=~/.m2/repository/org/clojure/clojure/1.8.0/clojure-1.8.0.jar ; #1
;; java -cp $CLOJURE_JAR:. clojure.main
(spit "math.clj" ; #2
"(ns math (:require [clojure.test :as t]))
(defn sum [a b] (+ a b))
(t/deftest sum-test (t/is (= 2 (sum 1 1))))")
(require '[clojure.test :as t])
(binding [*compile-path* "."
t/*load-tests* false] ; #3
(compile 'math))
;; math
The `math` example binds `*compile-path*` and `clojure.test/*load-tests*` around `compile`, producing a deployment build without its colocated test. section 23.14
AOT is therefore a deliberate build choice, not a default replacement for source loading: it trades some flexibility and build simplicity for reusable class files and deployment-time advantages. section 17.4


