Search code examples
antmacrodef

Ant: how to write optional nested elements


Say that I need to do something like:

<copy todir="${DEPLOYMENT_DIR}" overwrite="true">
    <fileset dir="dir1" />
    <fileset dir="dir2" />
    <fileset dir="dir3" />
    ...
    <if>
        <equals arg1="${SPECIAL_BUILD}" arg2="true"/>
        <then>
            <fileset dir="dir7" />
            <fileset dir="dir8" />
            ...
        </then>
    </if>
</copy>

(The real task is not copy, I'm just using it to illustrate the point.)

Ant will complain that my task doesn't support nested <if> which is fair enough. I've been thinking along these lines:

I could add a macrodef with an "element" attribute like this:

<macrodef name="myCopy">
    <element name="additional-path" />
    <sequential>
        <copy todir="${DEPLOYMENT_DIR}" overwrite="true">
            <fileset dir="dir1" />
            <fileset dir="dir2" />
            <fileset dir="dir3" />
            ...

            <additional-path/>
        </copy>
    </sequential>
</macrodef>

But that would mean that the caller (target) must specify the additional path which I want to avoid (if many targets call this task, they would have to repeat the fileset definitions in the additional-path element).

How to code the additional filesets inside the macrodef so that Ant doesn't complain?


Solution

  • One way (not sure if a good one) to achieve that is to create two macrodefs - one "public" for general use and one "internal" that does the real work and is intended to be called only from the "public" macro. Like this:

    <macrodef name="task-for-public-use">
        <sequential>
            <if>
                <equal arg1="${SPECIAL_BUILD}" arg2="true" />
                <then>
                    <internal-task>
                        <additional-path>
                            ...
                        </additional-path>
                    </internal-task>
                </then>
                <else>
                    <internal-task ... />
                </else>
            </if>
        </sequential>
    </macrodef>
    
    
    <macrodef name="internal-task">
        <element name="additional-path" />
        <sequential>
            <copy ...>
                ...
                <additional-path/>
            </copy>
        </sequential>
    </macrodef>
    

    I don't like it much though and hope there's a better way.