Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

antcontrib foreach executed in parallel does not raise errors

I have the following ant script that I can't seem to find a way to make fail when parallel is set to true for antcontrib's foreach task. Any ideas?

<project name="asdf" >
    <taskdef resource="net/sf/antcontrib/antcontrib.properties">
        <classpath>
            <pathelement location="../lib/ant/ant-contrib-1.0b3.jar" />
        </classpath>
    </taskdef>
    <target name="build">
        <foreach target="exex-subant" param="foreach.dir" parallel="true" maxthreads="4" inheritall="true" list="1,2,3">
            <param name="target" value="build" />
        </foreach>
    </target>

    <target name="exex-subant">
        <fail>test</fail>
    </target>
</project>
like image 964
Clintm Avatar asked Jun 15 '11 20:06

Clintm


1 Answers

This occurs because when executed in parallel, <foreach> uses the <parallel> task, but does not set the "failonany" property, or give any way to say that the task should fail if any iteration failed.

Fortunately, there is a relatively easy workaround, which is to use <for> instead of <foreach>. In your example, that would look like this:

<target name="build">
    <for param="foreach.dir" parallel="true" list="1,2,3">
        <sequential>
            <antcall target="exex-subant" inheritall="true">
                <param name="target" value="build" />
                <param name="foreach.dir" value="@{foreach.dir}" />
            </antcall>
        </sequential>
    </for>
</target>

Note that you have to explicitly pass in the foreach.dir property, which will then be accessible in the exex-subant target as ${foreach.dir}.

This will execute all iterations in parallel, but the script will fail if any one of them fails (it will not execute anything beyond the for task).

Note that in order to use the for task, you'll need ant 1.6 or higher, and will need to change your taskdef to:

<taskdef resource="net/sf/antcontrib/antlib.xml">
    <classpath>
        <pathelement location="../lib/ant/ant-contrib-1.0b3.jar" />
    </classpath>
</taskdef>

If for some reason you need to support older versions of ant, then you would have to change the exex-subant target slightly, so that it changed something when it failed. For example, you could wrap the current logic in exex-subant within a try/catch, and in the catch block it could create a file. Then after the foreach terminates you can check to see if that file exists, and fail the build if it does. That way, if any execution of the foreach fails, the ant script will fail after the foreach finishes.

Note that you can't just set a property in exex-subant on failure, since the property won't propagate back to the foreach loop (which is why I suggested creating a file). But I'd strongly recommend just using the for task and requiring ant 1.6 or higher.

like image 136
Laepdjek Avatar answered Nov 19 '22 06:11

Laepdjek