I took a stab at writing a static compiler class, i.e. a main() that
just compiles all the .clj files on the command line and saves the
.class files. Patch attached.
It almost works. The only thing that seems to be missing is creating
the class for the namespace itself, like "clojure/core.class". Not
sure what needs to be added to make that work.
-Stuart Sierra
> Since it only requires main, might I suggest you write this in
> Clojure instead?
I gave that a try.
Here's a simple version of a driver for the compiler, stored in src/
clj/clojure/compile.clj:
(ns clojure.compile)
(defn main
"Compiles libs into class files stored at compile-path.
All args are strings"
[compile-path & libs]
(printf "Compiling %d libs to %s\n" (count libs) compile-path)
(flush)
(binding [*compile-path* compile-path]
(doseq [lib libs]
(compile (symbol lib)))))
It works when run from within the Clojure repl:
% ls build/classes/clojure/hello*
ls: build/classes/clojure/*hello*: No such file or directory
% java -cp clojure.jar:src/clj/ clojure.lang.Repl
Clojure
user=> (require 'clojure.compile)
nil
user=> (clojure.compile/main "build/classes" "clojure.hello")
Compiling 1 libs to build/classes
nil
user=>
% ls build/classes/clojure/hello*
build/classes/clojure/hello$main__8.class build/classes/clojure/
hello.class
but when run as a standalone main, it gives an exception that appears
to be related to static initializers:
% java -cp clojure.jar:src/clj/ clojure.compile build/classes
clojure.hello
Compiling 1 libs to build/classes
Exception in thread "main" java.lang.IllegalStateException: Var null/
null is unbound. (hello.clj:3)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:4067)
at clojure.lang.Compiler.analyze(Compiler.java:3896)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:4050)
at clojure.lang.Compiler.analyze(Compiler.java:3896)
at clojure.lang.Compiler.access$100(Compiler.java:38)
at clojure.lang.Compiler$DefExpr$Parser.parse(Compiler.java:365)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:4060)
at clojure.lang.Compiler.analyze(Compiler.java:3896)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:4050)
at clojure.lang.Compiler.analyze(Compiler.java:3896)
at clojure.lang.Compiler.analyze(Compiler.java:3869)
at clojure.lang.Compiler.compile(Compiler.java:4498)
at clojure.lang.RT.compile(RT.java:408)
at clojure.lang.RT.load(RT.java:450)
at clojure.lang.RT.load(RT.java:422)
at clojure.core$load__4423$fn__4425.invoke(core.clj:3343)
at clojure.core$load__4423.doInvoke(core.clj:3342)
at clojure.lang.RestFn.invoke(RestFn.java:413)
at clojure.core$load_one__4386.invoke(core.clj:3189)
at clojure.core$compile__4429.invoke(core.clj:3347)
at clojure.compile$main__5162.doInvoke(compile.clj:23)
at clojure.lang.RestFn.invoke(RestFn.java:428)
at clojure.lang.Var.invoke(Var.java:323)
at clojure.lang.AFn.applyToHelper(AFn.java:195)
at clojure.lang.Var.applyTo(Var.java:436)
at clojure.compile.main(Unknown Source)
Caused by: java.lang.IllegalStateException: Var null/null is unbound.
at clojure.lang.Var.get(Var.java:129)
at clojure.lang.Compiler$FnExpr.parse(Compiler.java:2947)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:4058)
... 25 more
%
For reference, here is the test compilee: src/clj/clojure/hello.clj:
(ns clojure.hello)
(defn main
[greetee]
(printf "Hello, %s wow\n" greetee)
(flush))
I'd appreciate help in getting a standalone invocation of something
like compile.clj above (i.e., using it's own main without Repl or
Script) to work.
In working through this, I also found that a compiler driver written
in Java may be preferable for use via build.xml because of a bootstrap
problem. Until we compile (something like) "compile.clj", we can't
call it as a standalone main. (One could add a step that builds the
compiler driver via a clojure.lang.Script invocation.)
--Steve
I'm at SVN 1106 which doesn't appear to have any changes relative to
1104 in this area. My compiled "hello.clj" works with its function
called simply "main".
--Steve
main now needs to be called -main, as all methods will be defined with leading -.
Fixed (SVN 1108) - thanks for the report.
It seems there's something not quite right, though. I did a fresh checkout of 1108 and built with "ant" and ran with "java -jar clojure.jar" and got an exception:
Fixed - thanks.
Rich