Ant tasks are executed with wrong order

gradle-3510

(chuan shen) #1

Gradle Version: 2.14.1
Operating System: Windows 7 (64bit)

We are porting a large ant based build system into gradle and are using ‘ant.importBuild build.xml’, as the first step, to import all ant targets as gradle tasks as is. We found a couple of issues though, one of which has been captured into a minimal code snippet and presented here.

build.gradle

ant.importBuild 'build.xml'

build.xml:

<?xml version="1.0" encoding="utf-8"?>
<project name="Test" default="build" >
    <target name="build" depends="init, a, c"/>
    <target name="init"/>
	<target name="a"/>
	<target name="b" />
	<target name="c" depends="b"/>
	<target name="x" depends="b,a"/>
</project>

run gradle build produces following output:

:b
:init
:a
:c
:build

which is different from the expected result generated by ant build:

init:
a:
b:
c:
build:

The ant reference document(https://ant.apache.org/manual/targets.html) says that 'Ant tries to execute the targets in the depends attribute in the order they appear (from left to right). ’ And we don’t see that this basic rule is respected in this particular case.

Other observations

  • If we remove the “x” target from build.xml, the output matches the expected output.
    *If we rename the ‘init’ task to ‘Init’, the output matches the expected output.

(Mark Vieira) #2

Your observation is correct. Ant “tries” to execute targets in the specified order. Gradle has no such guarantee. If you require these targets run in a particular order than you should add an ordering rule. Adding the following to your build.gradle file will result in Ant-like behavior.

c.shouldRunAfter a
a.shouldRunAfter init

(chuan shen) #3

Thanks Mark, for the prompt reply and providing the workaround here.

However, the purpose of this post is not to seek help to make a particular build script work but to bring up a issue that might have a big impact on gradle’s ant compatibility(which according to the user guide is excellent). If ‘ant.importBuild’ import ANT build script in this way ( not respecting the dependency order like ANT does), it breaks many existing valid ANT build scripts. What makes it worse is the fact that renaming a task or adding an unrelated task will affect the task execution order of existing tasks.

My point is that ‘ant.importBuild’ should not relies on developers to add those ‘shouldRunAftter’ statements, it should call those statements automatically while importing the ANT tasks.


(Mark Vieira) #4

The problem is that this isn’t always a reliable solutions, and therefore it wouldn’t be correct to do this be default. The reason is that Gradle ordering rules are global, and in Ant, the order of depends is within the context of that target. There just simply isn’t an equivalent Gradle mechanism for this.


(chuan shen) #5

I understand you that from implementation standpoint, it is hard to solve. However, it is also not practical for developers to identify those patterns from a big ANT script and maintain them when the ANT script itself is updated.

I think this issue deserves to hava a JIRA assigned regardless of its complicity or implemnetation effort.

The ability to import ANT script as is gives gradle a lot of credit when convincing people migrating from legacy build systems to gradle, and should be functional as promised.


(Mark Vieira) #6

Absolutely, I’ve opened up GRADLE-3510 to track this and discuss how we might solve this problem.

Indeed, although admittedly this is not quite a 100% solution. We should do a better job of enumerating the discrepancies though. There is probably some room for improvement in the documentation regarding this.


(Luke Daley) #7

We actually do this implicitly already.

This has been the case since Gradle 1.12: https://docs.gradle.org/1.12/release-notes#ordering-of-dependencies-in-imported-ant-builds

If this isn’t working in your circumstance there’s likely another factor.


(Mark Vieira) #8

Thanks for pointing this out, Luke.

My guess is it’s exactly the situation I described. There is likely another target with conflicting ordering. My assumption is that Ant only takes this into account for a given target execution. In the Gradle case we should probably only add the ordering rules when the execution graph includes this task.