I've been asked to explain what I meant with "Macrodef - hopefully this is going to remove a bunch of <antcall> "abuses" present in Ant 1.5 build files."

Let me pick an example from Ant's own build file. Starting with Ant 1.6 optional.jar has been split into a bunch of smaller jars, one per external library required by the classes in it. I.e we now have ant-trax.jar for the classes that require TraX and ant-xalan1.jar for those that need Xalan-J 1.x and so on.

In Ant's build file this lead to

<jar destfile="${build.lib}/${optional.jars.prefix}-trax.jar"
     basedir="${build.classes}"
     manifest="${manifest.tmp}">
  <selector refid="needs.trax"/>
</jar>

<jar destfile="${build.lib}/${optional.jars.prefix}-xalan1.jar"
     basedir="${build.classes}"
     manifest="${manifest.tmp}">
  <selector refid="needs.xalan1"/>
</jar>
...
and a lot more of them. 25 <jar> tasks that were identical in structure.

The Ant 1.5 way of avoiding duplication like this would have been

  <antcall target="optional-jar">
    <param name="dep" value="trax"/>
  <antcall/>

  <antcall target="optional-jar">
    <param name="dep" value="xalan1"/>
  <antcall/>
  ...

<target name="optional-jar">
  <jar destfile="${build.lib}/${optional.jars.prefix}-${dep}.jar"
       basedir="${build.classes}"
       manifest="${manifest.tmp}">
    <selector refid="needs.${dep}"/>
  </jar>
</target>
leading to 25 <antcall>s in a row. This isn't more readable than the original version using separate jar tasks and in fact is a lot slower as <antcall> is a computational heavy operation in Ant. That's why we went back to the separate <jar>s after a few weeks.

And now the Ant 1.6 way:

<macrodef name="optional-jar">
  <attribute name="dep"/>
  <sequential>
    <jar destfile="${build.lib}/${optional.jars.prefix}-${dep}.jar"
      basedir="${build.classes}"
      manifest="${manifest.tmp}">
      <selector refid="needs.${dep}"/>
    </jar>
  </sequential>
</macrodef>

<optional-jar dep="trax"/>
<optional-jar dep="xalan1"/>
...

We have now defined a macro and use that macro repeatedly within the same build file execution. And on top of it, it's even more readable than the <antcall> approach.

Most if not all uses of <antcall> I've seen in build files can be replaced by <macrodef> (or by understanding <target>'s depends attribute). I'm not really sure that there is any use-case for <antcall> anymore.

path: /en/Apache/Ant | #

Dale Anson, founder of Antelope, has become a committer at the Ant-Contrib project.

Antelope and Ant-Contrib both host a bunch of similar tasks (if, trycatch, switch) and Dale plans to merge features from Antelope's versions with the existing Ant-Contrib tasks as well as bringing over some of Antelope's tasks.

path: /en/oss/antcontrib | #