Matthew Kime
Matthew Kime

Reputation: 754

How can I generate Ant targets?

I want to be able to generate a number of Ant targets something like this:

<property name="grunt_tasks" value="jsp,css,js,img" />
<foreach list="${grunt_tasks}" param="task">
    <target name="${task}">
        <exec executable="grunt" failonerror="true">
            <arg line="${task}" />
        </exec>
    </target>
</foreach>

allowing me to run ant jsp or ant js.

However, this code fails because a target tag cannot be placed in a foreach tag.

How can I accomplish this?

Upvotes: 3

Views: 126

Answers (1)

martin clayton
martin clayton

Reputation: 78135

There's a number of ways you might add targets on the fly. Here's one suggestion:

<property name="mybuild" value="mybuild.xml" />

<property name="grunt_tasks" value="jsp,css,js,img" />

<echo message="&lt;project&gt;" file="${mybuild}" />
<for list="${grunt_tasks}" param="task">
    <sequential>
    <echo file="${mybuild}" append="yes"><![CDATA[
    <target name="@{task}">
        <exec executable="grunt" failonerror="true">
            <arg line="@{task}" />
        </exec>
    </target>
    ]]></echo>
    </sequential>
</for>
<echo message="&lt;/project&gt;" file="${mybuild}" append="yes"/>

<import file="${mybuild}" />

Explanation:

  • Use the antcontrib <for> task in preference to <foreach>, else you have to have a separate target for the body of the loop.
  • Create a second buildfile, here called mybuild.xml, to contain your targets.
  • The buildfile content has to be within a <project> element.
  • Import the buildfile.

You can then invoke the on-the-fly targets in the way you wish.

You might alternatively use a <script> task to create the targets if you prefer, which would remove the need for the separate buildfile and import, something like this:

<for list="${grunt_tasks}" param="task">
    <sequential>
    <script language="javascript"><![CDATA[
        importClass(org.apache.tools.ant.Target);

        var exec = project.createTask( "exec" );
        exec.setExecutable( "grunt" );
        exec.setFailonerror( true );
        var arg = exec.createArg( );
        arg.setValue( "@{task}" );

        var target = new Target();
        target.addTask( exec );
        target.setName( "@{task}" );

        project.addOrReplaceTarget( target );
    ]]></script>
    </sequential>
</for>

Upvotes: 1

Related Questions