Reputation: 1354
Is it legitimate to compile Clojure from Java using clojure.lang.Compiler.compile
?
Our Java application used to create instances of Clojure objects by using clojure.lang.Compiler.load
on a .clj source which had a proxy
macro.
Now we want to AOT compile these objects using gen-class
rather than proxy
. This is so the .class files can be moved around and we instantiate the objects later on.
The best I’ve managed so far is to convince clojure.lang.Compiler.compile
to produce me the loader classfile (“my/domain/lib__init.class”). But I didn’t seem to get the accompanying .class files, one per function in the namespace (“my/domain/lib$fnname__1234.class”) and a stub class file for each gen-class
. This is in a sandbox using the very simple first example at http://clojure.org/compilation. I thought I’d correctly set compile-path, and set it to something in the classpath, but maybe there’s still an issue there.
In any case, our actual application is RCP (Eclipse) based, which probably means they'll be more to figure out in terms of OSGI classloader classpath. In the meantime I’m just wondering if using clojure.lang.Compiler.compile
directly is even a valid approach?
Edit: So I've now got it producing all the .class files, but it needed various bits of undocumented initializing which suggests to me that methods on clojure.lang.Compiler
are meant to be internal. I had to set *compile-path* appropriately and *compile-files* to true, e.g.
RT.var("clojure.core", "*compile-files*").bindRoot(true);
Upvotes: 5
Views: 624
Reputation: 2579
Here is an example of driving the Clojure compiler directly from Java.
String clojureScript = "(ns user) (def hello (fn [] \"Hello world\"))";
String notionalScriptFileName="hello.clj";
String outputDirectory="/my/output/dir";
Var compilePath = RT.var("clojure.core", "*compile-path*");
Var compileFiles = RT.var("clojure.core", "*compile-files*");
Var.pushThreadBindings(RT.map(compilePath, outputDirectory, compileFiles, Boolean.TRUE));
Compiler.compile(new StringReader(clojureScript), notionalScriptFileName, notionalScriptFileName);
Var.popThreadBindings();
I've tested this with Clojure 1.4.0... your mileage may vary with other versions.
As the API stands you need to provide a "notional" file name. This only seems to be used to generate the .class file names. The class files it generates are written to the outputDirectory.
Upvotes: 1
Reputation: 33657
You should try to use clojure.core/compile
function. Also you can check out how lein handles the :aot
param to do aot compilation.
Upvotes: 2