CAustin
CAustin

Reputation: 4614

Is there an elegant way to achieve target dependency ordering in Ant?

Suppose I have a simple build script with the following 4 targets:

  1. build - Compile's the project's code, depends on init
  2. init - Sets up the build environment, depends on nothing
  3. clean - Deletes all files generated by build and init, depends on nothing
  4. all - Simply cleans and then builds, depends on clean and build

    <project>
        <target name="build" depends="init">
            <echo>Building the project</echo>
        </target>
    
        <target name="init">
            <echo>Setting up the build environment</echo>
        </target>
    
        <target name="clean">
            <echo>Deleting all generated files</echo>
        </target>
    
        <target name="all" depends="build,clean">
            <echo>Full build complete!</echo>
        </target>
    </project>
    

The problem here is that the order of init and clean is ambiguous in Ant. If clean is called, it needs to run before all other targets, including init. However, init cannot have depends="clean" because we don't always want to run clean.

I realize that reversing the order of build and clean in the all target's dependencies (i.e. depends="clean,build") would technically get them to run in that order, however I don't consider this to be a satisfactory solution. Ant will still consider these targets to be siblings on the dependency tree, and will not actually enforce this order at all.

Another "solution" of course is to just hard code the ordering by using sequential <antcall/> tasks. This might be what I have to eventually fall back on, but it's something I'm trying to avoid (for multiple reasons that probably aren't worth expanding on).

Also, I'm aware that Gradle has exactly this feature built in (believe me, I'm jealous of it), but at this point my company's project is deeply entrenched in Ant, so switching really isn't an option.

EDIT - To give a better idea of the sort of thing I'm looking for, here's an example using features that I wish Ant had:

<condition property="init.depends.list" value="clean" else="">
    <contains string="${ant.project.call-graph}" substring="clean" />
</condition>

<target name="clean" />

<target name="init" depends="${init.depends.list}" />

After reading the manual page on Ant's bindtargets task, I'm starting to think Ant's target dependency list is immutable as part of its core design philosophy, so there might actually be no good answer to this question.

Upvotes: 1

Views: 883

Answers (2)

David St Denis
David St Denis

Reputation: 903

From the Ant Targets documentation:

Ant tries to execute the targets in the depends attribute in the order they appear (from left to right). Keep in mind that it is possible that a target can get executed earlier when an earlier target depends on it.

So unless your init and clean targets become more complex with additional dependencies, you can count on the ordering to be in order. So depends="clean,build" would work reliably.

Upvotes: 0

Chad Nouis
Chad Nouis

Reputation: 7051

If you want to ensure that init never runs before clean. Then you can use a property to serve as a flag:

<target name="init">
    <property name="init-called" value="true"/>
</target>

<target name="clean">
    <fail if="init-called" message="init ran before clean"/>
</target>

If init runs before clean, the init-called property will be set and the <fail> task will fail the build.

Another option is to have all depend on two targets: enable-clean-target and init. enable-clean-target would set a property that would be used by the if attribute of the clean target:

<target name="enable-clean-target">
    <property="run-clean" value="true"/>
</target>

<target name="clean" if="run-clean">
    <!-- ... -->
</target>

<target name="init" depends="clean">
    <!-- ... -->
</target>

<target name="all" depends="enable-clean-target, init">
    <!-- ... -->
</target>

The init target explicitly depends on clean, but clean will only run if enable-clean-target ran earlier in the build.

Upvotes: 1

Related Questions