Skip to content

Circumnavigating Watch and AOT Compilation Limitations

Bob Shelton edited this page Mar 4, 2016 · 1 revision

The problem: When one wants to have an executable recompiled each time a source file is changed, the waiting required is practically immeasurable. AOT is the culprit and can be reduced to interfering with one's life by the folliwing means. The jist is to create a shim that acts as an entry point to your application.

The structure (upon completion):

├── build.boot
├── src      
│   ├── clj
│   │   └── foo
│   │       ├── core.clj <-- where -main is located
│   │       ├── bar.clj <-- a source file referenced in core.cljs
│   │       └── main.clj <-- the shim (entry point) of the app
│   └── cljc
│       └── foo
│           ├── schema.cljc
│           └── utils.cljc
└── target
    └── project.jar

First, include the src directories in resource-paths within build.boot:

(set-env!
 :resource-paths #{"src/cljc" "src/clj"}
 ...)

core.clj looks something like the following (and notice :gen-class is not present, as it goes in main.clj):

(ns foo.core
  (:require [clojure.tools.cli :as cli]
            [foo.bar :refer [quux]]))

(defn -main [& argv]
  ...)

And main.clj:

(ns foo.main
  (:gen-class))

(defn -main [& args]
  (require 'foo.core)
  (apply (resolve 'foo.core/-main) args))

The time consuming problem with building is aot if it is applied to the whole source tree. With the method just described, the aot task can only be applied to main.clj. More from build.boot:

(task-options!
 aot {:namespace '#{foo.main}} ;; the only namespace touched
 jar {:main 'foo.main} ;; the entry point
)

Now, from the command line boot aot uber jar target builds the project. To leave only project.jar in the target directory, add sift: boot aot uber jar sift --include '\.jar$' target.

Or fashion a boot task:

(deftask bundle []
  (task-options!
   sift {:include #{#"\.jar$"}})
  (comp (aot) (uber) (jar) (sift) (target)))

(deftask dev []
  (comp (watch) (repl) (bundle)))

The latter task enables recompilation if a file is changed in the source directories.

Clone this wiki locally