ant-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jeffrey Bacon <>
Subject Re: Thinking in Ant...
Date Mon, 04 Oct 2004 14:25:03 GMT
it's not just you.  Ant tends to be a pain in the butt if you have to do 
a lot of scripting (ok, almost any scripting) work in your build system. 
  If your build system consists of essentially a batch execution of a 
linear path of steps, Ant works great.  As soon as you have to have some 
indeterminate information that is discovered during the build (like 
having to repeat tasks or loop over lists, etc.) Ant becomes difficult 
to fit in.

I often end up writing shell scripts that do work and calling them from 
Ant or using the ant-contrib libs which make a HUGE ease-of-use 
improvment (looping !!).  I also wrote a recursive property handler as 
that is a definate ease-of-use improvment... though I hear that may be 
built into a future version of Ant?

Anyway, no build tool is the be-all-and-end-all, if your builds requires 
a lot of scripting, another tool may benefit you more than Ant.

Richard Russell wrote:
> Hi all,
> Firstly, please excuse the crufty formatting of this email -- my employer
> makes me use Notes. If people would prefer, I can paste this into a public
> Twiki somewhere... Just let me know the general preference.
> Secondly, I'm hoping that this email does not come across overly critical
> or negative -- I'm not having a go at ant, I honestly just want to get my
> head around these problems better.
> Finally, thanks for your patience if you manage to read the whole email. I
> wanted to keep it short, but decided that the length was necessary to
> illustrate the problem that I've been having. Those interested, but
> pressed for time could just read the first part, up to the example...
> OK, now to the actual content:
> I'm having ongoing problems getting along with Ant. I keep wanting to do
> things that it appears that Ant can't do, despite trying to use what I
> would consider fairly basic constructs. I run into these issues so
> regularly that I cannot help but assume that I am simply not 'thinking in
> Ant', and am therefore fighting against its design rather than working
> with it. I occasionally come across snippets of documentation that seem to
> confirm this. Specific examples of things I keep butting my head against
> include:
> properties being "immutable" (except in some cases -- see propertycopy)
> not being able to double-dereference properties (eg ${${propertyname}}),
> or use arrays (not comma-separated lists -- indexable arrays)
> lack of 'if', 'for' and similar logic constructs (yes, I am aware of
> ant-contrib, but much documentation seems to indicate that this is a
> concession rather than an ideal)
> inflexibility of certain tasks/containers etc -- eg below, I want to set
> up a bunch of filters, and would like to use a construct like this within
> a loop:
>                 <filterchain id="${filtername}">
>                         <replacetokens>
>                                 <for param="propertyname"
> list="parameterlist">
>                                         <propertycopy name="propertyvalue"
> from="${prefix}.@{propertyname}"/>
>                                         <token key="@{propertyname}"
> value="${propertyvalue}"/>
>                                 </for>
>                         </replacetokens>
>                 </filterchain>
> As you can see, this illustrates a couple of my problems -- I'm using
> propertycopy to get around the lack of double-dereferencing, and also
> taking advantage of the way propertycopy can mutate values of "immutable"
> properties. Then, I'm using a for loop (which requires mutable properties)
> to set up multiple tokens in the replacetokens filter (actually, I can't
> do this, as replacetokens doesn't support the nested 'for' element).
> Another example of this is the (to my mind) strange duplication between
> filterchains and filtersets. They seem to do basically the same thing, but
> in different places and with different limitations.
> My frustration here is because Ant isn't procedural. Or perhaps it's
> because I think of my build process in a procedural manner (hence why I
> call it a build *process* and not a build *declaration*). Perhaps this is
> because I've always used make, but I'm not sure how else to think about
> it, at least at the low level. Eventually, I have battled through, and
> have created new tasks, macros, or used other people's libraries to make
> it all happen, but no matter what, it all takes so long, and I don't see
> life getting much better as I grow in familiarity with it.
> ------------------------------------------------
> Here's a longer example of something that I would normally consider
> simple. I want to append each of the files in one directory to the
> same-named file in another directory, filtering some tokens as I go. It's
> possibly expressed simplest as a shell script:
> ----
> for file in `ls ${dir1}/*.DAT`; do
>   cat ${dir1}/${file} | sed -e 's/@parameter@/value/' >> ${dir2}/${file}
> done
> ----
> As an aside, I wrote that particular line in about two minutes, including
> fixing the one error I made in the sed script (I missed the trailing /).
> Obviously, there would be more sed parts for the different tokens, and
> it's not exactly an elegant solution. But the point is that it took me two
> minutes, didn't require me consulting any API documentation, and doesn't
> require compilation. I'm sure there's more elegant, perhaps easier ways of
> doing it, in Perl, or even still in shell, but this is just a trivial
> example.
> Now, to do the same in Ant, I first tried to combine the for and concat
> tasks, with a filter, in the obvious (to me) manner. For various reasons
> this wouldn't work -- mostly to do with immutable properties, and not
> being able to separate the filename from the directoryname in a fileset
> and so on. If anyone knows of a way to replicate this functionality
> without writing a new Task, let me know.  As it was, I had to create the
> following Task:
> ----
> package mypackage;
> import;
> import;
> import;
> import;
> import;
> public class AppendCopy extends Concat
> {
>         private String destDir=null;
>         private File srcFile=null;
>         public void execute() throws BuildException
>         {
>                 if (destDir==null)
>                         throw new BuildException("AppendCopy: destdir
> attribute not set");
>                 if (srcFile==null)
>                         throw new BuildException("AppendCopy: srcfile
> attribute not set");
>                 try
>                 {
>                         File destinationFile=new
> File(destDir+System.getProperty("file.separator")+srcFile.getName());
>                         super.setDestfile(destinationFile);
>                         FileSet sourceFileSet=new FileSet();
>                         sourceFileSet.setFile(srcFile);
>                         super.addFileset(sourceFileSet);
>                         super.setAppend(true);
>                         super.execute();
>                 }
>                 catch (Exception exception)
>                 {
>                         throw new BuildException("AppendCopy: something
> went wrong\n" + exception);
>                 }
>         }
>         public String toString() {
>                 return
> super.toString()+"\ntoDir="+destDir+"\nfromFile="+srcFile+"\n";
>         }
>         public void setDestdir(String string)
>         {
>                 destDir=string;
>         }
>         public void setSrcfile(File file)
>         {
>                 srcFile=file;
>         }
>         public void setDestfile(File destinationFile) throws
> BuildException {
>                 throw new BuildException("AppendCopy: destFile attribute
> disallowed");
>         }
>         public void setAppend(boolean append) throws BuildException {
>                 throw new BuildException("AppendCopy: Append attribute
> disallowed");
>         }
>         public void addFileset(FileSet set) throws BuildException {
>                 throw new BuildException("AppendCopy: Nested FileSet
> element disallowed");
>         }
>         public void addFilelist(FileList list) throws BuildException {
>                 throw new BuildException("AppendCopy: Nested FileList
> element disallowed");
>         }
> }
> ----
> And then, I use it in my build.xml like this:
> ----
> <taskdef name="appendcopy" classname="mypackage.AppendCopy"/>
> ...
> <for param="filename">
>         <fileset dir="${dir1}/" includes="*.DAT"/>
>         <sequential>
>                 <appendcopy srcfile="@{filename}" destdir="${dir2}"
> fixlastline="true">
>                         <filterchain refid="myfilter"/>
>                 </appendcopy>
>         </sequential>
> </for>
> ----
> Plus, of course, the setting up of the filterchain "myfilter".
> Now, when I look at the result, it's far from elegant, and without knowing
> what appendcopy really did, I would be hard pressed to understand what the
> ant snippet did. I could remove the for loop, and create a task that did
> the whole operation, and was called like this:
> ----
> <appendcopydirectory todir="${dir2}">
>         <fileset dir="${dir1}/" includes="*.DAT"/>
>         <filterchain refid="myfilter"/>
> </appendcopydirectory>
> ----
> But I suspect that would be even more work. It's also (to my mind) less
> clear and less re-usable (though I could name it
> appendcopyeachfileinfilesettosamenamedfileintodir, but that's got its own
> problems). I could subclass copy, adding an "append" attribute, but,
> having read the source to Copy
> (

> <>),

> I decided that discretion was the better part of valour, and there had to
> be an easier way. Note that while I can code Java, I'm not a developer,
> and have no desire to become one. Certainly, I challenge even a top
> developer to come up with some sort of append attribute for Copy in the
> time it took me to write the equivalent shell script above.
> -------------------------------------------
> So, what is it that I'm doing wrong here? Why am I always battling against
> Ant, and finding that the things I wish to do, things which I find simple
> to express in english, in psuedocode, or in shell, are so darned complex
> to do in Ant? Am I just not getting it? Am I driving in nails with a
> screwdriver?
> Cheers,
> Richard Russell
> Deutsche Bank AG London
> Global Markets Customer Solutions
> Office: +44 (0)20 7545 8060
> Mobile: +44 (0)79 0661 2237
> ---------------------------------------------------------------------
> To unsubscribe, e-mail:
> For additional commands, e-mail:

Jeffrey Bacon
Creative Developer

To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message