May 25, 2021 Gradle
Projects and tasks are the two most important concepts in Gradle.
Any Gradle build consists of one or more projects. E ach project includes many buildable components. I t all depends on what you're building. F or example, each project might be a jar package or a web app, or it could be a zip compression package made up of jars generated in many other projects. A project does not have to describe that it can only be built. I t can also deploy your app or build your environment. D on't worry about it being as big as it sounds. Gradle's build-by-convention lets you define exactly what a project should do.
Each project consists of multiple tasks. E ach task represents an atomic operation during the build execution process. Such as compiling, packaging, generating javadoc, publishing to a warehouse, and so on.
So far, we've found that we can define some simple tasks in one project, and subsequent chapters will cover multi-project building and multi-project multitasing.
You can execute the build by running the gradle command on the command line, which looks for the build.gradle file from the current directory. W e call the build.gradle file a build script. Strictly speaking, this is actually a build configuration script, and you'll learn later that the build script defines a project and some default tasks.
You can create the following script to build.gradle in To try this out, create the following build script named build.gradle.
build.gradle
task hello {
doLast {
println 'Hello world!'
}
}
The gradle -q hello is then executed in the directory where the file is located
-q What is the role of the parameters?
Many of the examples in this document add -q parameters when calling the gradle command. T his parameter controls the log level of the gradle and guarantees that only what we need is output. You can refer to the Chapter 18 log in this document for more parameters and information.
Output of gradle -q hello
> gradle -q hello
Hello world!
The script above defines a task called hello and adds an action to it. W hen the gradle hello is executed, Gralde calls the hello task to perform the given action. These operations are actually a closure written in groovy.
If you think it looks like targets in Ant, you're right. G radle's tasks are equivalent to targets in Ant. B ut you'll find him more powerful. W e just changed another term that's more graphic than target. U nfortunately, this happens to conflict with the terminology in Ant. T here are such things as javac, copy, tasks in the ant command. S o when tasks are mentioned in the document, unless the ant task is specifically specified. Otherwise, it refers to the tasks in Gradle.
Define the hello task above in a more concise way.
build.gradle
task hello {
println 'Hello world!'
}
Once again, the above script defines a task called hello in a closed-pack manner, which we will define more in subsequent chapters of this document.
Note: Deprecated in Gradle 4.x and removed in Gradle 5.0, see: Gradle 4.x.com
Example: Task slt;lt;?println 'Hello world!': Remove or use doLast to solve.
The Gradle script is written in Groovy as an appetizer, and here's an example.
build.gradle
task upper << {
String someString = 'mY_nAmE'
println "Original: " + someString
println "Upper case: " + someString.toUpperCase()
}
Output of gradle -q upper
> gradle -q upper
Original: mY_nAmE
Upper case: MY_NAME
Or
build.gradle
task count << {
4.times { print "$it " }
}
Output of gradle -q count
> gradle -q count
0 1 2 3
You can create dependencies between tasks as follows
build.gradle
task hello << {
println 'Hello world!'
}
task intro(dependsOn: hello) << {
println "I'm Gradle"
}
The output of the gradle -q intro
Output of gradle -q intro
\> gradle -q intro
Hello world!
I'm Gradle
Adding a dependent task also does not have to declare the dependent task first.
build.gradle
task taskX(dependsOn: 'taskY') << {
println 'taskX'
}
task taskY << {
println 'taskY'
}
Output of gradle -q taskX
\> gradle -q taskX
taskY
taskX
As you can see, taskX was defined before taskY, which is useful in multi-project builds.
Note: You cannot run a task using a short tag method when the referenced task is not yet defined.
With Groovy's power, you can define simple tasks and do more. For example, you can define tasks dynamically.
build.gradle
4.times { counter ->
task "task$counter" << {
println "I'm task number $counter"
}
}
The output of gradle -q task1.
Output of gradle -q task1
\> gradle -q task1
I'm task number 1
Once a task is created, the tasks can access each other through the API. T his is also different from Ant. For example, you can add some dependencies.
build.gradle
4.times { counter ->
task "task$counter" << {
println "I'm task number $counter"
}
}
task0.dependsOn task2, task3
The output of the gradle -q task0.
Output of gradle -q task0
\> gradle -q task0
I'm task number 2
I'm task number 3
I'm task number 0
Add behavior to existing tasks.
build.gradle
task hello << {
println 'Hello Earth'
}
hello.doFirst {
println 'Hello Venus'
}
hello.doLast {
println 'Hello Mars'
}
hello << {
println 'Hello Jupiter'
}
Output of gradle -q hello
> gradle -q hello
Hello Venus
Hello Earth
Hello Mars
Hello Jupiter
DoFirst and doLast can make multiple calls. T hey are added at the beginning and end of the task, respectively. T hese actions are performed in a given order when the task begins to execute. Where the operator is a short-form of doLast.
You've noticed for a long time, yes, each task is a script property that you can access:
build.gradle
task hello << {
println 'Hello world!'
}
hello.doLast {
println "Greetings from the $hello.name task."
}
The output of the gradle -q hello
Output of gradle -q hello
\> gradle -q hello
Hello world!
Greetings from the hello task.
Built-in tasks provided for plug-ins. This is particularly convenient (e.g. complie)
You can add additional properties to a task. F or example, add a property called myProperty and give him an initial value in the form of ext.myProperty. This adds a custom property.
build.gradle
task myTask {
ext.myProperty = "myValue"
}
task printTaskProperties << {
println myTask.myProperty
}
The output of the gradle -q printTaskProperties
Output of gradle -q printTaskProperties
\> gradle -q printTaskProperties
myValue
Custom properties aren't limited to tasks, they can do more.
The Ant task is a first-class citizen in Gradle. G radle uses Groovy to integrate Ant tasks well. G radle brings its own AntBuilder, which makes it easier and more powerful to call Ant tasks in Gradle than in .xml in build. The following example lets you learn how to invoke an Ant task and how to communicate with properties in Ant.
build.gradle
task loadfile << {
def files = file('../antLoadfileResources').listFiles().sort()
files.each { File file ->
if (file.isFile()) {
ant.loadfile(srcFile: file, property: file.name)
println " *** $file.name ***"
println "${ant.properties[file.name]}"
}
}
}
The output of the gradle -q loadfile
Output of gradle -q loadfile
\> gradle -q loadfile
*** agile.manifesto.txt ***
Individuals and interactions over processes and tools
Working software over comprehensive documentation
Customer collaboration over contract negotiation
Responding to change over following a plan
*** gradle.manifesto.txt ***
Make the impossible possible, make the possible easy and make the easy elegant.
(inspired by Moshe Feldenkrais)
You can also do more with Ant in your script. For more information, see Call Ant in Gradle.
The power of Gradle depends on how you write scripting logic. For the above example, the first thing to do is to extract the method.
build.gradle
task checksum << {
fileList('../antLoadfileResources').each {File file ->
ant.checksum(file: file, property: "cs_$file.name")
println "$file.name Checksum: ${ant.properties["cs_$file.name"]}"
}
}
task loadfile << {
fileList('../antLoadfileResources').each {File file ->
ant.loadfile(srcFile: file, property: file.name)
println "I'm fond of $file.name"
}
}
File[] fileList(String dir) {
file(dir).listFiles({file -> file.isFile() } as FileFilter).sort()
}
The output of the gradle -q loadfile
Output of gradle -q loadfile
\> gradle -q loadfile
I'm fond of agile.manifesto.txt
I'm fond of gradle.manifesto.txt
In a later section you'll see that methods like this can be called in sub-projects in multi-project builds. No matter how complex the build logic is, Gradle can provide you with an easy way to organize them.
Gradle allows you to define multiple default tasks in a script.
build.gradle
defaultTasks 'clean', 'run'
task clean << {
println 'Default Cleaning!'
}
task run << {
println 'Default Running!'
}
task other << {
println "I'm not a default task!"
}
The output of gradle -q.
Output of gradle -q
\> gradle -q
Default Cleaning!
Default Running!
This is the same as calling the gradle clean run effect directly. I n a multi-project build, each sub-project can specify a separate default task. If the child item is not specified, the default task specified by the parent project is called.
After you've detailed the configuration phase and the run phase of Gradle later, Gradle understands that all the tasks to be performed, Gradle, provides a hook to capture this information. A n example is the possible check to see if any of the tasks that have been performed have been released. From this, you can give different values to some variables.
In the following example, different version values are given for distribution and release tasks.
build.gradle
task distribution << {
println "We build the zip with version=$version"
}
task release(dependsOn: 'distribution') << {
println 'We release now'
}
gradle.taskGraph.whenReady {taskGraph ->
if (taskGraph.hasTask(release)) {
version = '1.0'
} else {
version = '1.0-SNAPSHOT'
}
}
The output of the gradle -q distribution
Output of gradle -q distribution
\> gradle -q distribution
We build the zip with version=1.0-SNAPSHOT
The output of the gradle -q release
Output of gradle -q release
\> gradle -q release
We build the zip with version=1.0
We release now
WhenReady affects the execution of published tasks before they are published. Even if the published task is not the primary task (that is, even if the task is not called directly from the command line)
In this chapter, we learned what a task is, but it's not detailed enough. For more information, see chapter Task Details.
In addition, you can continue to learn about Java Build Getting Started and relying on the management foundation.