Random musings from my awakening dementia...
07.02.2004  
Ant's Apply Task
 

I've been a computer geek since a boy, and thoughts related to computers and software engineering get dropped here for the benefit of humanity and my own hubris.

© 2004-2005, Howard Abrams



Except where otherwise noted, all original content is licensed under a Creative Commons License.
See details.

I wanted to have an Ant task that took some files and ran them through a Perl script as a filter. Seems like a job for the apply task… give it a directory of files and a mapper to link the source files with the resulting destination files. But I ran into a snag…

Let me first show you the section from my build.xml file that illustrates what I want:

<apply dest="${dist}" executable="perl" parallel="false">
    <arg file="${src.support}/Markdown.pl" />
    <fileset dir="${src.docs}">
        <include name="**/*.txt"/>
    </fileset>
    <mapper type="glob" from="*.txt" to="*.htm" />
</apply>

Seems fairly simple enough… In the ${src.docs} directory, find all of the files ending in txt and compare them with files that end in htm in the ${dist} directory. For each file, execute perl with an option specifying the script file. This script file will read from stdin and write a new file on stdout.

But therein lies the problem You would think that the apply task would use the mapper to not only compare what files need to be regen’d, but also the name of the files to write to… but it doesn’t work that way. The output from the filter goes to stdout unless you specify an output attribute to the apply task.

But what should the value of this output attribute be? If you specify the name of a file, each iteration of the process will over-write the work of the previous one (or append it to the same file). Not what I want.

After spending a great deal of time in Google looking for the answer, it appears that no one thought about an executable that acted like this. All of the examples that I could find assume that the executable can take something like a “-o” option for specifying the output file.

If my script could handle something like that, then I would, instead, write the following:

<apply dest="${dist}" executable="perl" parallel="false">
    <arg file="${src.support}/Markdown.pl" />
    <arg value="-o" />
    <targetfile />
    <fileset dir="${src.docs}">
        <include name="**/*.txt"/>
    </fileset>
    <mapper type="glob" from="*.txt" to="*.htm" />
</apply>

The thinking here is that each original file is given to the script that looks like this:

perl support/Markdown.pl -o file1.htm

<sigh> It took me longer to hunt through Google looking for an answer than it took for me to hack the perl script to add an “-o” option to it.

But I still want to know the answer, so if you, gentle reader, know the answer, please let me know. And if you want to know the answer, keep checking back to this page, for when I find it, I’m gonna post it.

A comment to this from jw

I do believe, as of Ant 1.6.2, the I/O redirector will solve the problem for you.

See the ant manual (http://ant.apache.org/manual/index.html) and the Apply/ExecOn task

Towards the bottom, I/O redirectors are discussed. To quote the page: “This grants the user the capacity to receive input from, and send output to, different files for each sourcefile

see the example at the very very bottom (the fictitious “processfile” command)

Comment posted on Sunday, 14 November 2004