Gradle's withType usage - gradle

Like this other user, I have problems to understand the withType usage, example
tasks.withType(JavaCompile) {
options.compilerArgs.add("-Xbootclasspath/p:${file}")
}
... and differently from him, I have found official docs, as always, completely unuseful. Can you tell me what withType exactly does?

It finds all defined tasks in the current project that are of given type. You can have multiple tasks named and configured differently, but sharing the same type (and implementation details).
E.g. there is one task type JavaCompile that is then added as two tasks in standard Java project: compileJava and testCompileJava.
More could be found in Gradle docs. The syntax you ask about will give you possibility to set common config for all such tasks.

Related

Gradle configurations integration

I've found this code at work in build.gradle
configurations {
all {
resolutionStrategy {
cacheDynamicVersionsFor 0, 'seconds'
}
}
integration
}
I can't find anywhere what integration keyword stands for. Can you explain to me?
In this example, the build is declaring a new configuration called integration. And a configuration can for the most part be thought of as a bucket or collection of dependencies. If a plugin or the Gradle core new about a particular configuration, there would usually be no need to declare it as it would already exist to begin with.
Let's assume that 'integration' is short for 'integration test'. Then what's going on here is that your build is saying: "Hey, I need a bunch of dependencies for running my integration test, but I don't want to pollute the classpath for the other kinds of runtime environments. So please make me a bucket of dependencies to isolate the integration test".
Later in the build file (which you didn't show), you will then find a dependencies block where the integration configuration is populated with the modules needed for running the test. And lastly, some task that actually uses it, presumably for setting the classpath.
It could be used for a number of other things of cause. But whatever it is, it is probably something custom and you could rename it (and all references to it) to 'aCollectionOfAwesomeDependenciesUsedForRunningOurIntegrationTest' if you like.

Alternative way to define bootRun task in Gradle doesn't work

I usually define tasks in Gradle (using Groovy) like tasks.withType(Type); e.g.: tasks.withType(JavaCompile), tasks.withType(Test), etc.
Now, I want to do the same with some provided Spring Boot tasks, namely: bootRun and bootStartScripts, but Gradle cannot find it.
I know it's silly and I could get away just by using bootRun and bootStartScripts, but I would like to understand why those cannot be configured/defined in such way.
I guess with define you mean configure, because withType can only be used to configure existing tasks. It takes a task type (a class) and a closure that can be used to configure all available tasks of that type. This needs to be considered, because a project may contain multiple tasks of the same type that should actually do completely different things. Whether to configure all those tasks or just a specific one is important!
To pass the task type to the method withType you need to know the name of the class implementing the task type. This name is not necessarily related to the name(s) of the actual task(s). For the tasks test and compileJava of the Gradle Java Plugin those classes are org.gradle.api.tasks.testing.Test and org.gradle.api.tasks.compile.JavaCompile. Since those classes are provided by Gradle, they are automatically imported and can be referenced via their simple names Test and JavaCompile. But the Spring Boot Plugin is a third-party plugin, so the classes need to be referenced by their full names.
The task bootStartScripts from your question is of type CreateStartScript, that is provided by Gradle. Therefore it can be configured like this:
tasks.withType(CreateStartScripts) {
// configure
}
The task bootRun is of type org.springframework.boot.gradle.tasks.run.BootRun, that is provided by the Spring Boot Plugin. So you need to specify the full name:
tasks.withType(org.springframework.boot.gradle.tasks.run.BootRun) {
// configure
}

Where are the docs for tasks.withType()?

Gradle is a well documented project, but when I search for the docs for tasks.withType(), I only find the API docs.
Isn't this an official part of Gradle?
One of the fundamental concepts in Gradle is that everything is executed against a Project instance. Once you know that, you can work through the javadoc to find what you want. There's a bit of "magic" to be wary of too (a topic for another conversation) and also groovy syntax to understand .
So tasks.withType(...) can be looked up in the javadocs as Project.getTasks().withType(...).
You'll notice that Project.getTasks() returns a TaskCollection (which you found in your googling)
* edit *
There's a mention here in the docs which links to the TaskContainer javadocs
A project is essentially a collection of Task objects. Each task performs some basic piece of work, such as compiling classes, or running unit tests, or zipping up a WAR file. You add tasks to a project using one of the create() methods on TaskContainer, such as TaskContainer.create(java.lang.String). You can locate existing tasks using one of the lookup methods on TaskContainer, such as TaskCollection.getByName(java.lang.String)

What is the difference between concepts Custom Task and Enhanced Task in Gradle?

I often meet in Gradle documentation these concepts. What is the difference between them?
From what I know custom task is class that encapsulates some logic, but what is enhanced task and what is the difference between them?
A simple task in Gradle is an instance of DefaultTask and does not do anything out of the box. To make it do something you have to add code to the task definition in your build script.
An enhanced task is an instance of a different class (for example a Copy task is an instance of Copy) and has some behaviour out of the box. You just need to configure that behaviour in your build script (eg tell it where to copy from and to)
A custom task is an enhanced task that is an instance of a class you wrote yourself.
An enhanced task is defined in the Gradle manual as:
Gradle supports enhanced tasks, that is, tasks which have their own properties and methods. This is really different to what you are used to with Ant targets. Such enhanced tasks are either provided by you or are provided by Gradle.
It also says:
Gradle supports two types of task. One such type is the simple task, where you define the task with an action closure. We have seen these in Chapter 6, Build Script Basics. For this type of task, the action closure determines the behaviour of the task. This type of task is good for implementing one-off tasks in your build script.
The other type of task is the enhanced task, where the behaviour is built into the task, and the task provides some properties which you can use to configure the behaviour. We have seen these in Chapter 15, More about Tasks. Most Gradle plugins use enhanced tasks. With enhanced tasks, you don't need to implement the task behaviour as you do with simple tasks. You simply declare the task and configure the task using its properties. In this way, enhanced tasks let you reuse a piece of behaviour in many different places, possibly across different builds.
The behaviour and properties of an enhanced task is defined by the task's class. When you declare an enhanced task, you specify the type, or class of the task.

Timely Gradle task inputs/outputs configuration

I'm having ordering issues with Gradle task configuration.
I'm writing a plugin that creates a task based on information that is only available when supplied via the build script. I can create the task in the plugin's apply() method, and configure it in its doFirst() method (by which time the necessary information is available). However, I also want to make sure that the task is only executed when necessary via the inputs/outputs properties.
This is problematic, because I have to do this in the apply() method (as far as I can tell), but at that point the information required to specify the inputs/outputs property values isn't available.
I tried using a convention object but that's not available under after apply() has completed.
Is there any way around this that won't make me feel dirty?
For those parts of the task configuration that need to be deferred, you can either use a hook like project.afterEvaluate {} or gradle.projectsEvaluated {}, or use convention mapping. The latter is used extensively by Gradle's own plugins, but isn't currently considered a public API.

Resources