How do I learn Gradle?

Hi,

As I mentioned in my other post I am very new to Gradle and I have found it pretty tough going.

Part of it is the Groovy syntax which is probably just a familiarity issue. It’s hard when learning a new language and a build system at the same time. The main problem I have is that there so many different ways of doing the same thing. That just makes the learning curve so much harder. Part of this is syntax but I don’t think it all is. A really strict linter might help in this regard if one exists?

The Gradle DSL is also quite hard to work out. Everything looks deceptively similar but that similarity doesn’t help because things aren’t the same. Like at the top level there are the methods on the project plus a few other things like the build script and plugins. Then there are tasks which kind of look like the other top level things but aren’t. Then the splattering of objects (?) and closures. This is likely completely wrong.

Which brings me to my main point, how do you know what to pass to a closure? The docs don’t say much other than it must be a closure and neither does the source code. The only way I have managed this far is by copying examples and pure luck. I much prefer having a good reference to go to, that way I can figure out on my own without an example and go beyond what the example would show me.

This isn’t really a criticism of Gradle just my frustrations as a beginner. I come from the Scala/sbt ecosystem so we have similar issues over there. Any pointers to help me to help myself would be much appreciated.

Cheers

3 Likes

Understanding these Groovy features helped me greatly in deciphering the Gradle DSL:

  1. Closures specifically scoping
  2. Omitting parentheses
  3. Getter and Setters

Together they allow Domain Specific Languages that bypass the noisy syntax you’d inherit if building a DSL on Java, but at times does make it seem symbols are being pulled out of thin air. Understanding that conceptually the build file’s default scope is Project aids greatly in looking up “the syntax”.

Given a Gradle snippet and using Project as the starting point you can usually locate the specification. This Groovy copy example:

task copyReport(type: Copy) {
    from file("$buildDir/reports/my-report.pdf")
    into file("$buildDir/toArchive")
}

would lead you to this reading order (Javadoc direct links might be flaky):

  1. Project.file(Object path)
  2. Project.task​(Map<java.lang.String,?> args, String name, Closure configureClosure
  3. Copy task and the into and from methods

When encountering a symbol like task in a script, start with the Project JavaDoc and look for these names:

  1. task in case it’s just calling a method with omitted parentheses
  2. task with a closure if there’s braces immediately following it
  3. getTask or setTask if there’s an = immediately following it and it’s assigning a property
  4. getTask and see if it’s a method returning a Handler type

Following that process for the dependencies block in a build script should take you down this research path:

  1. Project.getDependencies
  2. DependencyHandler

Hope that’s a good starting point to help you get over the “everything is magic” hurdle.

If you get confused about a symbol’s availability or spec, using reflection to dump the class name and properties should help you get back to the right docs.

1 Like

Learning Gradle besides hello-world examples is extremely hard.

I’d recommend get familiar with Groovy first: http://groovy-lang.org/syntax.html

Then you need to run existing examples: https://github.com/gradle/gradle/tree/master/subprojects/docs/src/samples

and add a lot of println(). Try on every object getClass() or println it.metaClass.methods*.name.sort().unique() to explore objects.

Download Gradle binary distro with sources and make sure your IDE can jump into Gradle sources!!! Javadoc and implementation uncover a lot that official documentation is missing.

Official documentation has good quality but it is not pleasant for cover to cover reading (( Check https://docs.gradle.org/current/dsl/index.html and read concepts when you miss something: https://docs.gradle.org/current/userguide/userguide.html

Remember that Gradle is a moving project and each major version has breaking changes. Read release notes: https://gradle.org/releases/

1 Like

Do println(it.getClass()) (or similar) and check class source code, study methods + javadoc, look for super class methods, check known overriding/implementing classes.

For example from Project source code:

Task task(String name, Closure configureClosure);
Task task(String name, Action<? super Task> configureAction);

It gives example how to create task with Closure and Action.

Source code for DefaultProject:

@Override
public Task task(String task, Closure configureClosure) {
    return taskContainer.create(task).configure(configureClosure);
}

and javadoc for:

/**
 * <p>Applies the statements of the closure against this task object. The delegate object for the closure is set to
 * this task.</p>
 */
Task configure(Closure configureClosure);

So when you use Clousure it is set to Task!

1 Like

I totally agree with it. I have been breaking my head over the same.
learning/using gradle, being comfortable with it, has been tough.
most of the things I am unsure about. have read through the documentation. however, still lack a basic picture of what anything does, for eg, java plugin produces artifacts. I would like to end-to-end picture of taking sources, resources, compiling, test etc to artifact, ship artifact to maven repo etc.

I want to use kotlin-dsl. however, intellij still lacks debugging build.gradle.kts. How do I see/become comfortable without knowing end-to-end flow ?

documentation at docs.gradle.org is overall good. however, it seems unsettling that there aint many deep dive tutorials, awesome lists in github about gradle. And a general lack of help in stackoverflow.

My point is not to criticize. I would love to learn about it but its harder to do than it should be.

2 Likes

This is definitely a concern of mine and is one reason why I added a Groovy DSL Primer. Have you seen that? If so, did it help at all? How do you think it could be improved (because it certainly can be)?

With regard to the specific question of what to pass to a closure, I’m not sure what you mean by that. I suspect the primer sections on Block method signatures and Delegation hold the information you need. Basically, the API docs should tell you. Methods that correspond to blocks in the Gradle build should have an argument of the parameterised type Action. The parameter type tells you what type is “passed” to the closure.

2 Likes

@amit-handa Do the Build Java libraries and Publishing Java libraries guides not help? What about the user manual chapter on Build Java & JVM projects?

I would be interested to know what you think of those, even if it’s simply the fact you hadn’t seen them. We want to make sure that the documentation is not only helpful, but also easily discovered.

Hello @pledbrook , Thanks so much for replying. I am using kotlin DSL for learning gradle (for static typing autocompletion). below is my understanding of current limitations in learning gradle. I am open to your feedback so that my learning can be expedited. don’t want to go back to maven :slight_smile:

For understanding/mastering a plugin, say java plugin, there is nice documentation in gradle docs.
However, I still am unsure about the java plugin and how to customize. docs lists things as a reference.

IMO, in order to master, below would help:

  1. IDE debugging, so that I can poke around in the build.gradle.kts and learn about the state of the build.

  2. In my limited understanding, gradle constructs DAG of tasks and executes them in topologically sorted order. Tasks have inputs and outputs.

compilejava : inputs <files, params etc.>, output
testCompile: … ditto …
test: … ditto …
artifacts: input< configuration, compilejava.output > , output < jar file etc.>

This would probably help me in how different components of java plugin (properties, extensions, configurations, conventions, sourcesets, tasks etc. fit with each other and when I need to update to get my desired setup, where can I customize.

1 Like

The Building Java & JVM projects chapter linked in my previous reply should give some much needed context and information for what the Java Plugin does. The chapter on Testing in Java & JVM projects is also very useful, particularly as it gives a concrete example of creating a new source set (for integration tests).

Specific forms of customisation should be covered in other parts of the user manual, but they are not necessarily easy to find. If you want to change some sort of behaviour of a specific task, such as compileJava of type JavaCompile, then the API docs are worth looking at as they provide all the available properties of the various task types. That includes files paths, collections of files, and so on.

If you need to influence the behaviour of dependency management, then you will want to look at the dependency management chapters of the user manual. They also explain dependencies, repositories and dependency configurations, which should make it easier to understand what the Java Plugin provides in that area.

We don’t really have a good explanation of how to affect the wiring of tasks and I desperately want to rewrite the introductory chapters so users such as yourself get a better grounding in the fundamental Gradle concepts.

One final thing: the Working with tasks chapter contains a lot of information about customising tasks. And the section in that chapter on up-to-date checks is a must read. It will give you much needed information about task inputs and outputs.

thanks for your kind response. as I said earlier, of all the docs I could find, the ones on gradle.org are definitely the best, IMO.
I did go through the links you mentioned. However, I wished to take a look at following (for any plugin, viz base, application, java-base, java, kotlin etc.)

  • flow of the plugin tasks, t1 -> t2,t3 -> t4 … -> tn
  • For each task, task type, input params (with values), output params (with values).

since I am unable to debug the build.gradle.kts (intellij doesnt support its debugging yet), its hard to poke into the build tool. I am sure there must be a way to do it, hence, my post to this thread.
Thanks again for your precious time ! if there is any other way to learn gradle, please suggest.

Build scans can give you insight into the order that tasks run, including any that run in parallel. They do not provide access to the input and output values though, sorry. That definitely sounds like something that would be useful!

I also think a visualisation of the task dependency graph would be handy. This old forum post has a couple of links to community plugins that may help. Hopefully they have been kept up to date and work with whatever version of Gradle you are using.

Actually maybe it’s due to English is not my mother tongue. Comparing to the tutorials of Baeldung’s ( which delivers those spring mainly ) , the documentation of gradle is more difficult to understand. Not only just because its extensive terminologies but also the way it expresses.

For example I am reading Kotlin DSL Primer, I’m not sure what is “model elements”.

And for this sentence (same page) , "For all other containers than tasks, accessors for elements are of type NamedDomainObjectProvider and provide the same behavior.
".
I’ve checked detailed implementation of the container(“dependencies”). I couldn’t find where is the “NamedDomainObjectProvider”.

1 Like