Ant: how to write optional nested elements

2019-07-09 00:12发布

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?

标签: ant macrodef
2条回答
孤傲高冷的网名
2楼-- · 2019-07-09 00:47

AntContrib has an Ant FileSet object augmented with if and unless conditions.

http://ant-contrib.sourceforge.net/fileset.html

if Sets the property name for the 'if' condition. The fileset will be ignored unless the property is defined. The value of the property is insignificant, but values that would imply misinterpretation ("false", "no") will throw an exception when evaluated.

unless Set the property name for the 'unless' condition. If named property is set, the fileset will be ignored. The value of the property is insignificant, but values that would imply misinterpretation ("false", "no") of the behavior will throw an exception when evaluated.

You could use it like this:

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

</copy>
查看更多
不美不萌又怎样
3楼-- · 2019-07-09 01:03

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.

查看更多
登录 后发表回答