I am playing around with using Clojure to control Ant, something along
the lines of Groovy's Gant. I don't know how far I will take this--
right now it is serving as a code example for the book.
Two questions:
(1) Anybody interested in seeing lancet carried forward into a real
project?
(2) Below is an example of lancet syntax (compare with Clojure's own
build.xml). Any big likes/dislikes?
Cheers,
Stuart
(project {:name "clojure" :default "jar"}
(properties :src "src"
:jsrc (i :src "/jvm")
:cljsrc (i :src "/clj")
:build "classes"
:clojure_jar "clojure.jar"
:bootclj (i :cljsrc "/clojure/boot.clj"))
(target {:name "test"}
(echo {:message "init target"}))
(target {:name "compile" :depends "init"
:description "Compile Java sources."}
(javac {:srcdir (i :jsrc) :destdir (i :build)
:includejavaruntime "yes"
:debug "true"
:target "1.5"}))
(target {:name "init"}
(tstamp)
(mkdir {:dir (i :build)}))
(target {:name "clean"
:description "Remove autogenerated files and directories"}
(delete {:dir (i :build)}))
)
Hi all,
I am playing around with using Clojure to control Ant, something along
the lines of Groovy's Gant. I don't know how far I will take this--
right now it is serving as a code example for the book.
Two questions:
(1) Anybody interested in seeing lancet carried forward into a real
project?
(2) Below is an example of lancet syntax (compare with Clojure's own
build.xml). Any big likes/dislikes?
Oh yes please! I had started playing around with something like this, got
far enough to compile some Java source (a static base for some Clojure code
of course), and haven't really touched it sense.
> (2) Below is an example of lancet syntax (compare with Clojure's own
> build.xml). Any big likes/dislikes?
I've never liked XML DSLs because they lack standard general purpose
language features and go on to invent their own ad-hoc versions.
Is a property not just a 'def' ?
Is a target not a just function? (which only performs its actions if needed)
Isn't a project just a mapping from target names to functions, and dynamic
bindings during the build process?
; properties
(def src "src")
(def jsrc (str src "/jvm"))
(def cljsrc (str src "/clj"))
(def target "classes")
(def clojure.jar "clojure.jar")
(def bootclj (str cljsrc "/clojure/boot.clj"))
; deftarget is like defn but takes no args, and wraps the body in machinery
; that will only call it once per session.
(deftarget clean
"Remove autogenerated files and directories"
(delete :dir target))
(deftarget init
(tstamp)
(mkdir :dir target))
(deftarget compile-java
"Compile java sources"
(init)
(javac :srcdir jsrc :destdir target
:includejavaruntime true
:debug true
:target "1.5"))
A project could be defined explicitly, or could be created through
reflection (deftarget would also add some metadata in that case)
This syntax seems Clojurish rather than happens-to-be-on-Clojure. I think it
shows off both the cognitive simplicity of FP and the powerful incremental
nature of a Lisp based internal DSL.
Regards,
Steve
You are absolutely right, and I hope to have all your syntax
suggestions implemented tomorrow.
By way of background: When I started, it seemed there were three
obvious avenues to pursue:
(1) write a Clojure DSL that generates the Ant XML
(2) write a Clojure DSL that sticks close to the underlying Ant object
model
(3) stick to Clojure idioms and use individual Ant classes when they
fit in
I rejected #1 out of hand--I don't think that the Ant XML has value,
and so wrapping it (and having it leak in the form of error messages)
was unappealing.
I picked #2 because I thought there were a ton of objects in the Ant
model I would end up wanting, and that they would be so intertwined
that I would need to use most of them in order to use any of them.
A few hours working on #2 was enough to convince me that there not
much in Ant that I wanted to keep. In particular targets, properties,
and subtask elements aren't worth their weight. That leaves only tasks
(and a stubbed-out project object).
So now I am proceeding through door #3. The work on #2 wasn't a total
waste -- I now know enough of the Ant object model to fake out the few
things I need (so far).
Cheers,
Stuart
I went down a similar road once before, using a Ruby DSL to generate
the XML for Spring DI. This approach may offer the quickest initial
return, but it hits a ceiling very quickly. You end up having two APIs
with a totally unnecessary XML layer in between. Worse, the XML layer
spews error messages that are totally meaningless in terms of the new
object model.
I am going to skip the XML entirely and program against the parts of
the Ant object model I want to keep. It may be worthwhile to write a
tool that goes in the other direction, reading XML and emitting
lancet, for people porting existing buildfiles.
Cheers,
Stuart
Given this is my first post here, a bit of disclosure: I am an Ant
committer and have been for more than eight years. I'm a total newbie
when it comes to Clojure but have been doing Lisp (mostly Emacs Lisp
but dabbled a bit with CL) for longer than I'm using Java.
On Thu, 6 Nov 2008, Stuart Halloway <stuart....@gmail.com> wrote:
> (1) Anybody interested in seeing lancet carried forward into a real
> project?
Given this is something I wanted to look into myself in order to get
my feet wet, I'd like to see this going for forward. If only to
educate me.
If you need help finding your way through the historical cruft that
hides Ant's real model, I'll be happy to lend advice (I doubt I'd be
much help on the Clojure side right now).
Using a fake project probably is the easiest approach, but there are