tags:

views:

391

answers:

4

In his article The Nature of Lisp, Slava Akhmechet introduces people to lisp by using Ant/NAnt as an example. Is there an implementation of Ant/NAnt in lisp? Where you can use actual lisp code, instead of xml, for defining things? I've had to deal with creating additions to NAnt, and have long for a way to bypass the xml system in the way Slava shows could be done.

+1  A: 

Perhaps you could define things in lisp and convert them to XML at the point you pass them to NAnt.

Something like XMLisp makes it easier to go back and forth between the two representations.

Edit: Actually, xml-emitter would make more sense.

justinhj
The thing that the article brought up was that xml was a meta language, which really prevented you from being able to use the implementation language. If Ant/NAnt was implemented using lisp, you could use all of the power of lisp in every node... which sounds SO appealing!
Daniel
That's true, and I guess Scons is an example of this, since you can run arbitary python in that build system.On the other hand I think the mature build systems like make, and jam, which have evolved concise and expressive languages for building code make the idea of a lisp Ant less useful.
justinhj
+1  A: 

Common Lisp's ASDF (Another System Definition Facility) is analogous to Make/Ant (but not a full analogue — it is aimed at building lisp programs, not generic systems like make or ant). It is extensible with Lisp code (subclassing systems, components, adding operations to systems). E.g., there is an asdf-ecs extensions that allows including (and compiling) C source files into system.

dmitry_vk
+9  A: 

Ant is a program that interprets commands written in some XML language. You can, as justinhj mentioned in his answer use some XML parser (like the mentioned XMLisp) and convert the XML description in some kind of Lisp data and then write additional code in Lisp. You need to reimplement also some of the Ant interpretation.

Much of the primitive stuff in Ant is not needed in Lisp. Some file operations are built-in in Lisp (delete-file, rename-file, probe-file, ...). Some are missing and need to be implemented - alternative you can use one of the existing libraries. Also note that you can LOAD Lisp files into Lisp and execute code - there is also the REPL - so it comes already with an interactive frontend (unlike Java).

Higher level build systems in Common Lisp usually are implementing an abstraction called 'SYSTEM'. There are several of those. ASDF is a popular choice, but there are others. A system has subsystems and files. A system has also a few options. Its components also have options. A system has either a structural description of the components, a description of the dependencies, or a kind descriptions of 'actions' and their dependencies. Typically these things are implemented in an object-oriented way and you can implement 'actions' as Lisp (generic) functions. Lisp also brings functions like COMPILE-FILE, which will use the Lisp compiler to compile a file. If your code has, say, C files - you would need to call a C compiler - usually through some implementation specific function that allows to call external programs (here the C compiler).

As, mentioned by dmitry-vk, ASDF is a popular choice. LispWorks provides Common Defsystem. Allegro CL has their own DEFSYSTEM. Its DEFSYSTEM manual describes also how to extend it.

All the Lisp solution are using some kind of Lisp syntax (not XML syntax), usually implemented by a macro to describe the system. Once that is read into Lisp, it turns into a data representation - often with CLOS instances for the system, modules, etc.. The actions then are also Lisp functions. Some higher-order functions then walk over the component graph/tree and execute actions of necessary. Some other tools walk over the component graph/tree and return a representation for actions - which is then a proposed plan - the user then can let Lisp execute the whole plan, or parts of the plan.

On a Lisp Machine a simple system description looks like this:

(sct:defsystem scigraph
    (:default-pathname "sys:scigraph;"
     :required-systems "DWIM")
   (:serial "package" "copy" "dump" "duplicate" "random"
            "menu-tools" "basic-classes" "draw" "mouse"
            "color" "basic-graph" "graph-mixins" "axis"
            "moving-object" "symbol" "graph-data" "legend"
            "graph-classes" "present" "annotations" "annotated-graph"
            "contour" "equation" "popup-accept" "popup-accept-methods"
            "duplicate-methods" "frame" "export" "demo-frame"))

Above defines a system SCIGRAPH and all files should be compiled and load in serial order.

Now I can see what the Lisp Machine would do to update the compiled code:

Command: Compile System (a system [default Scigraph]) Scigraph (keywords)
                        :Simulate (compiling [default Yes]) Yes

  The plan for constructing Scigraph version Newest for the Compile 
      operation is:
  Compile RJNXP:>software>scigraph>scigraph>popup-accept-methods.lisp.newest
  Load RJNXP:>software>scigraph>scigraph>popup-accept-methods.ibin.newest

It would compile one file and load it - I have the software loaded and changed only this file so far.

For ASDF see the documentation mentioned on the CLIKI page - it works a bit different.

Rainer Joswig
Thanks for spending the time to answer! I guess my biggest beef with Ant is that since it is using XML, I cannot use the power of the underlying language directly to perform some operations. Only operations (functions) that have been "ported" to the xml side are available. The beauty I see in a system implemented with Lisp is that all of lisp would be available, no need to create XML wrappers for native functions.
Daniel
+3  A: 

Stuart Halloway's upcoming book Programming Clojure goes through the construction of Lancet throughout the book as an example app. Lancet is a Clojure build system which (optionally) integrates directly with Ant. Source code and examples are available.

If all you want to do is generate Ant XML files using Lisp code, you could use something like clj-html for Clojure or CL-WHO for Common Lisp. Generating XML from Lisp s-exps is fun and easy.

Brian Carper