How to use Ant like 'make' for generic conversions

While I appreciate Ant for automating java projects build, I still often find cases where I go "jeez, it would have taken two lines in a Makefile and I can't see how to do that with Ant"

Last case I came across: I have a bunch of JPG files and I want to make GIF thumbnails from them. ImageMagick does the job pretty well, but I want to automate the operation so that only newly added or changed JPG are reprocessed at each build.

When you search for "ant up-to-date" or "ant timestamp", you almost immediately find the <uptodate> Task. At first, it seems to be exactly suited for that purpose, and it can take a <mapper> as destination files, so it can look for the correct GIF filename for each JPG. However, the problem of <uptodate> is its granularity : it takes a (set of) source file(s) and a (set of) destination file(s), and sets a flag if something is out of date. If no source has changed, all is well, but if only some files changed, the only thing you can do is reprocess all the source files. (Alternatively, you can put one <uptodate> Task per file of course, but it's completely static and is thus not an option)

Finally, after much reading, is seems <uptodate> is not suitable for that case and no specific construct is needed at all. All you need is a simple target calling the Apply task. Apply, contrary to Exec, only executes if its destination file is out-of-date.

It's still much longer than the make syntax, but at least it does the job perfectly :

   <target name="makelogos">
       <echo message='converting logos .jpg -> .gif thumbnails'/>
       <apply failonerror='true' executable='${imagemagick.dir}/convert' dest='${out.dir}'>
           <srcfile/>
           <arg value='-resize'/>
           <arg value='40x30>'/>
           <targetfile/>
           <fileset dir='${web.src.dir}'>
               <include name='${img.subdir}/*.jpg'/>
           </fileset>
           <mapper>
               <chainedmapper>
                 <mapper type="flatten"/>
                 <mapper type='glob' from='*.jpg' to='*.gif'/>
               </chainedmapper>
           </mapper>
       </apply>
   </target>

And well, once it works, it looks pretty simple, but I guess it's not that easy to find unless you have RTFM a few times

They posted on the same topic

Trackback URL : http://blog.deconinck.info/trackback/25

This post's comments feed