35

I'm trying to learn Gradle. My preferred style of learning is to understand at a low level what is going on. To that end, I am trying to interpret what's happening in example 6.1 of the documentation with respect to the DSL reference:

task hello {
    doLast {
        println 'Hello world!'
    }
}

I understand that this script is executed in the context of a Project. So I can see from the Project documentation that there are a number of overloaded task(...) methods. Looking at the signatures, I need to chose one which has a closure as the final argument. And since we're not passing a Map here, I assume the method that's being called is task(String name, Closure closure).

However, the part I'm struggling with is how, in this script, the literal string hello gets mapped to a String.

Another example is example 6.7:

task taskX(dependsOn: 'taskY') << {
    println 'taskX'
}

task taskY << {
    println 'taskY'
}

Here, I assume we're calling the task(Map<String, ?> args, String name) form of the method. But,

  1. Again, how does the literal string taskX end up as a String?
  2. Given that parentheses are not used to construct a Map literal, how does the part in parentheses end up being a Map?
  3. If I've correctly figured out which method is being called, aren't the arguments given in the wrong order in the script compared to the DSL documentation?
  4. The syntax using parentheses looks for all the world like a method call. Which might indicate delegation to the Project object to resolve taskX as an unknown method. But, AFAIK, a method call wouldn't be syntactically valid at this point given the method call to task immediately preceding it.

As you can see I'm a bit confused as to how the example syntax maps down to the DSL reference guide, which is making it a bit tricky for me to really understand what's happening at a grass-roots level.

Thanks!

dty
  • 18,795
  • 6
  • 56
  • 82
  • 1
    I have the same confusion as you. And I really hope gradleware can provide some explanation. – peacepassion Sep 25 '14 at 05:04
  • This ask may be more detail. [groovy syntax in a gradle task definition](http://stackoverflow.com/questions/27584463/understanding-the-groovy-syntax-in-a-gradle-task-definition/27584555#27584555) – user3875388 Nov 24 '16 at 06:48
  • Possible duplicate of [Understanding the groovy syntax in a gradle task definition](https://stackoverflow.com/questions/27584463/understanding-the-groovy-syntax-in-a-gradle-task-definition) – tkruse Jan 29 '18 at 05:47

2 Answers2

24

The task foo variation of the task declaration syntax is special in that it's implemented using a Groovy compiler plugin. As far as I know, this is the only case where a compiler plugin is used to support a special syntax.

Peter Niederwieser
  • 121,412
  • 21
  • 324
  • 259
  • 8
    Interesting. I'm relatively new to Groovy and one of the things I'm not liking is how hard it is to figure out what's going on when people have done "clever" stuff like this - generally to make their DSLs easy to use/write. Do you have any specific advice on how I might go about translating (in my head) between a script and the DSL reference guide? – dty Sep 07 '12 at 22:58
  • 1
    The syntax is documented both in the user guide and in the DSL reference; note how they speak of the task *keyword*. In retrospect, it may be a bit over the top, although it does read nicer than the non-magic alternatives. As I said, it's a rare exception. Given how you analyzed that there must be something "wrong" here, you are well on your way to understanding everything else that's happening under the covers of Gradle's DSL. – Peter Niederwieser Sep 07 '12 at 23:09
  • Thanks Peter. One last question, if I may. Could you point me to the right place in th Gradle source to see this compiler plugin in action, please? – dty Sep 07 '12 at 23:25
  • 5
    `gradle/subprojects/core/src/main/groovy/org/gradle/groovy/scripts/internal/TaskDefinitionScriptTransformer.java` – Peter Niederwieser Sep 07 '12 at 23:45
2

This is a good doc: https://ouyi.github.io/post/2017/12/09/groovy-gradle.html

And here is written at the end:

"The syntax of a custom task is tricky. For example:

task myTask(type:Tar, dependsOn anotherTask) {
    // clousre
}

I could figure out that this was probably calling the method Task task(Map<String,?> args, String name, Closure configureClosure) defined on the project object, but I had no clue how to match the myTask() construct with the name parameter. And I am not alone, similar disussions are here and here.

It turns out that Gradle uses some advanced meta programming features of Groovy (compile-time metaprogramming) to transform the myTask() construct to the name parameter. To be honest, this is the part of Gradle that I do not like, because it seems to be too tricky to implement those syntax sugars (and too much sugar may not be healthy). Afterall, Gradle is just a build tool, which shall be easy to understand, to use, and to extend."

Dacian
  • 678
  • 6
  • 12