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="<project>" 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="</project>" 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>