Planck Macros AOT

February 3, 2016

Planck ships with a few macro namespaces which are now AOT compiled using Planck.

A little background: Planck ships with its requisite namespaces bundled in its binary. For minimizing loading latency, most of this code is AOT compiled down to JavaScript.

But, this has not been the case for the macro namespaces that ship with Planck. One example of such a namespace is the planck.core macro namespace which provides a with-open macro.

The relevant *.clj source files are bundled in the binary, but they are dynamically compiled to JavaScript when first required. While these macro namespaces are rather small, they could grow over time, and I wanted them to be AOT compiled just like the regular namespaces that ship with Planck.

Non-macro namespaces are AOT compiled using the regular (JVM-based) ClojureScript compiler. But, during that part of the build phase, macros are compiled and expanded using Clojure—no JavaScript representing the compiled form of the macros is ever needed nor generated.

What you really need to do in order to generate JavaScript for macro namespaces is to compile them using cljs.js. I suppose you could arrange to do this during the build using a JavaScript interpreter—Nashorn perhaps.

But… there is another approach. Planck supports the caching capability of cljs.js, which ultimately results in the compiled form of namespaces to be written out to disk. This caching also works for macro namespaces that you might author and load with Planck.

So, to AOT compile Planck's shipping macro namespaces, Planck itself is used during its build, essentially repurposing the caching capability to use Planck as a bootstrapped ClojureScript compiler for the limited purpose of AOT compiling its macro namespaces.

How does Planck use itself during the build? Its build is now a 2-stage process. The first stage just produces a Planck binary which can then be used to compile the macro namespaces (really, by causing them to be required and cached). Planck is then built again in a second stage with the main difference being that it bundles the JavaScript associated with the compiled macro namespaces.

Like I said, there are probably other ways to accomplish this. But, I think it is interesting to just stick with Planck for building these artifacts. For now it is simple and gets the job done.

Tags: Planck ClojureScript Bootstrap