Chapter 6. Build Script Basics

6.1. Projects and tasks

Everything in Gradle sits on top of two basic concepts: projects and tasks.

Every Gradle build is made up of one or more projects. What a project represents depends on what it is that you are doing with Gradle. For example, a project might represent a library JAR or a web application. It might represent a distribution ZIP assembled from the JARs produced by other projects. A project does not necessarily represent a thing to be built. It might represent a thing to be done, such as deploying your application to staging or production environments. Don't worry if this seems a little vague for now. Gradle's build-by-convention support adds a more concrete definition for what a project is.

Each project is made up of one or more tasks. A task represents some atomic piece of work which a build performs. This might be compiling some classes, creating a JAR, generating javadoc, or publishing some archives to a repository.

For now, we will look at defining some simple tasks in a build with one project. Later chapters will look at working with multiple projects and more about working with projects and tasks.

6.2. Hello world

You run a Gradle build using the gradle command. The gradle command looks for a file called build.gradle in the current directory. [2] We call this build.gradle file a build script, although strictly speaking it is a build configuration script, as we will see later. The build script defines a project and its tasks.

To try this out, create the following build script named build.gradle.

Example 6.1. Your first build script

build.gradle

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

In a command-line shell, move to the containing directory and execute the build script with gradle -q hello:

What does -q do?

Most of the examples in this user guide are run with the -q command-line option. This suppresses Gradle's log messages, so that only the output of the tasks is shown. This keeps the example output in this user guide a little clearer. You don't need to use this option if you don't want. See Chapter 18, Logging for more details about the command-line options which affect Gradle's output.

Example 6.2. Execution of a build script

Output of gradle -q hello

> gradle -q hello
Hello world!

What's going on here? This build script defines a single task, called hello, and adds an action to it. When you rungradle hello, Gradle executes the hello task, which in turn executes the action you've provided. The action is simply a closure containing some Groovy code to execute.

If you think this looks similar to Ant's targets, you would be right. Gradle tasks are the equivalent to Ant targets, but as you will see, they are much more powerful. We have used a different terminology than Ant as we think the word task is more expressive than the word target. Unfortunately this introduces a terminology clash with Ant, as Ant calls its commands, such as javac or copy, tasks. So when we talk about tasks, wealways mean Gradle tasks, which are the equivalent to Ant's targets. If we talk about Ant tasks (Ant commands), we explicitly say ant task.

6.3. A shortcut task definition

There is a shorthand way to define a task like our hello task above, which is more concise.

Example 6.3. A task definition shortcut

build.gradle

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

Again, this defines a task called hello with a single closure to execute. We will use this task definition style throughout the user guide.

6.4. Build scripts are code

Gradle's build scripts give you the full power of Groovy. As an appetizer, have a look at this:

Example 6.4. Using Groovy in Gradle's tasks

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

Example 6.5. Using Groovy in Gradle's tasks

build.gradle

task count << {
4.times { print "$it " }
}

Output of gradle -q count

> gradle -q count
0 1 2 3

6.5. Task dependencies

As you probably have guessed, you can declare tasks that depend on other tasks.

Example 6.6. Declaration of task that depends on other task

build.gradle

task hello << {
println 'Hello world!'
}
task intro(dependsOn: hello) << {
println "I'm Gradle"
}

Output of gradle -q intro

> gradle -q intro
Hello world!
I'm Gradle

To add a dependency, the corresponding task does not need to exist.

Example 6.7. Lazy dependsOn - the other task does not exist (yet)

build.gradle

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

Output of gradle -q taskX

> gradle -q taskX
taskY
taskX

The dependency of taskX to taskY is declared before taskY is defined. This is very important for multi-project builds. Task dependencies are discussed in more detail in Section 15.4, “Adding dependencies to a task”.

Please notice that you can't use shortcut notation (see Section 6.8, “Shortcut notations”) when referring to a task that is not yet defined.

6.6. Dynamic tasks

The power of Groovy can be used for more than defining what a task does. For example, you can also use it to dynamically create tasks.

Example 6.8. Dynamic creation of a task

build.gradle

4.times { counter ->
task "task$counter" << {
println "I'm task number $counter"
}
}

Output of gradle -q task1

> gradle -q task1
I'm task number 1

6.7. Manipulating existing tasks

Once tasks are created they can be accessed via an API. For instance, you could use this to dynamically add dependencies to a task, at runtime. Ant doesn't allow anything like this.

Example 6.9. Accessing a task via API - adding a dependency

build.gradle

4.times { counter ->
task "task$counter" << {
println "I'm task number $counter"
}
}
task0.dependsOn task2, task3

Output of gradle -q task0

> gradle -q task0
I'm task number 2
I'm task number 3
I'm task number 0

Or you can add behavior to an existing task.

Example 6.10. Accessing a task via API - adding behaviour

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

The calls doFirst and doLast can be executed multiple times. They add an action to the beginning or the end of the task's actions list. When the task executes, the actions in the action list are executed in order. The << operator is simply an alias for doLast.

6.8. Shortcut notations

As you might have noticed in the previous examples, there is a convenient notation for accessing an existing task. Each task is available as a property of the build script:

Example 6.11. Accessing task as a property of the build script

build.gradle

task hello << {
println 'Hello world!'
}
hello.doLast {
println "Greetings from the $hello.name task."
}

Output of gradle -q hello

> gradle -q hello
Hello world!
Greetings from the hello task.

This enables very readable code, especially when using the tasks provided by the plugins, like the compile task.

6.9. Extra task properties

You can add your own properties to a task. To add a property named myProperty, set ext.myProperty to an initial value. From that point on, the property can be read and set like a predefined task property.

Example 6.12. Adding extra properties to a task

build.gradle

task myTask {
ext.myProperty = "myValue"
} task printTaskProperties << {
println myTask.myProperty
}

Output of gradle -q printTaskProperties

> gradle -q printTaskProperties
myValue

Extra properties aren't limited to tasks. You can read more about them in Section 13.4.2, “Extra properties”.

6.10. Using Ant Tasks

Ant tasks are first-class citizens in Gradle. Gradle provides excellent integration for Ant tasks by simply relying on Groovy. Groovy is shipped with the fantastic AntBuilder. Using Ant tasks from Gradle is as convenient and more powerful than using Ant tasks from a build.xml file. From the example below, you can learn how to execute ant tasks and how to access ant properties:

Example 6.13. Using AntBuilder to execute ant.loadfile target

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]}"
}
}
}

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)

There is lots more you can do with Ant in your build scripts. You can find out more in Chapter 17, Using Ant from Gradle.

6.11. Using methods

Gradle scales in how you can organize your build logic. The first level of organizing your build logic for the example above, is extracting a method.

Example 6.14. Using methods to organize your build logic

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()
}

Output of gradle -q loadfile

> gradle -q loadfile
I'm fond of agile.manifesto.txt
I'm fond of gradle.manifesto.txt

Later you will see that such methods can be shared among subprojects in multi-project builds. If your build logic becomes more complex, Gradle offers you other very convenient ways to organize it. We have devoted a whole chapter to this. See Chapter 60, Organizing Build Logic.

6.12. Default tasks

Gradle allows you to define one or more default tasks for your build.

Example 6.15. Defining a default tasks

build.gradle

defaultTasks 'clean', 'run'

task clean << {
println 'Default Cleaning!'
} task run << {
println 'Default Running!'
} task other << {
println "I'm not a default task!"
}

Output of gradle -q

> gradle -q
Default Cleaning!
Default Running!

This is equivalent to running gradle clean run. In a multi-project build every subproject can have its own specific default tasks. If a subproject does not specify default tasks, the default tasks of the parent project are used (if defined).

6.13. Configure by DAG

As we later describe in full detail (see Chapter 56, The Build Lifecycle), Gradle has a configuration phase and an execution phase. After the configuration phase, Gradle knows all tasks that should be executed. Gradle offers you a hook to make use of this information. A use-case for this would be to check if the release task is among the tasks to be executed. Depending on this, you can assign different values to some variables.

In the following example, execution of the distribution and release tasks results in different value of the version variable.

Example 6.16. Different outcomes of build depending on chosen 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'
}
}

Output of gradle -q distribution

> gradle -q distribution
We build the zip with version=1.0-SNAPSHOT

Output of gradle -q release

> gradle -q release
We build the zip with version=1.0
We release now

The important thing is that whenReady affects the release task before the release task is executed. This works even when the release task is not the primary task (i.e., the task passed to thegradle command).

6.14. Where to next?

In this chapter, we have had a first look at tasks. But this is not the end of the story for tasks. If you want to jump into more of the details, have a look at Chapter 15, More about Tasks.

Otherwise, continue on to the tutorials in Chapter 7, Java Quickstart and Chapter 8, Dependency Management Basics.




[2] There are command line switches to change this behavior. See Appendix D, Gradle Command Line)

Chapter 6. Build Script Basics的更多相关文章

  1. Chapter 7. Dependency Management Basics 依赖管理基础

    This chapter introduces some of the basics of dependency management in Gradle. 7.1. What is dependen ...

  2. Android - 警告:it is always overridden by the value specified in the Gradle build script

    警告:it is always overridden by the value specified in the Gradle build script 本文地址: http://blog.csdn. ...

  3. Gradle Goodness: Run a Build Script With a Different Name

    Normally Gradle looks for a build script file with the name build.gradle in the current directory to ...

  4. gradle中的build script详解

    目录 简介 project和task 一个例子 task详细讲解 task脚本 task依赖 动态task 默认task build script的外部依赖 gradle中的build script详 ...

  5. Shell Script Basics

    https://developer.apple.com/library/mac/documentation/OpenSource/Conceptual/ShellScripting/shell_scr ...

  6. Chapter 2 Build Caffe

    Caffe for windows 的build药按照一定的顺序进行. ============================================================ 先以b ...

  7. 使用MingGW-w64 Build Script 3.6.7搭建ffmpeg编译环境

    在Linux下编译的Windows版本ffmpeg没有其他的依赖库 使用的是centos 1.脚本下载 wget http://zeranoe.com/scripts/mingw_w64_build/ ...

  8. build script和all projects作用和区别

    buildscript中的声明是gradle脚本自身需要使用的资源.可以声明的资源包括依赖项.第三方插件.maven仓库地址等.而在build.gradle文件中直接声明的依赖项.仓库地址等信息是项目 ...

  9. kernel jenkins build script

    #!/bin/bash #gcc: site="https://releases.linaro.org" #https://releases.linaro.org/componen ...

  10. Gradle2.0用户指南翻译——第三章. 教程

    翻译项目请关注Github上的地址:https://github.com/msdx/gradledoc本文翻译所在分支:https://github.com/msdx/gradledoc/tree/2 ...

随机推荐

  1. 在线免费ChatGPT,官方api

    作为一款强大的语言模型,ChatGPT在自然语言处理领域享有较高声誉.现在,您可以在我们的在线平台上免费体验ChatGPT的功能了! 经过不断地优化和改进,我们的在线聊天机器人已经能够针对各种话题展示 ...

  2. 02-面试必会-SSM框架篇

    01-什么是 Spring IOC 和 DI ? IOC : 控制翻转 , 它把传统上由程序代码直接操控的对象的调用权交给容 器,通过容器来实现对象组件的装配和管理.所谓的"控制反转&quo ...

  3. 怎么把 session 中的实体类转换回来

    例子 : 如上比如user user1=new user(): user1.id=1: user1.name="张三": session["user1"]=us ...

  4. 使用GoEasy快速实现Android原生app中的websocket消息推送

    摘要: GoEasy带来了一项令开发者振奋的消息:全面支持Android原生平台!现在,您可以在Android应用中使用最酷炫的实时通信功能,借助GoEasy轻松实现消息的发送和接收.本文将带您领略G ...

  5. 学习C++这一篇就够了(提升篇)

    C++中除了面向对象的编程思想外,还有另一种就是泛型编程 主要用到的技术就是模板 模板机制的分类: 函数模板 类模板 函数模板 作用:建立一个通用函数,其函数返回值类型和形参类型可以不具体定制,用虚拟 ...

  6. vue和servlet 前后端分离 (复习)

    一.vue复习 1.vue的使用步骤: (1)导入vue.js (2)创建除body以外最大的div标签,给定id值 (3)创建vue对象 new Vue({ el:"#app", ...

  7. vue基本操作[2] 续更----让世界感知你的存在

    Vue文件解析 什么是<template/>标签 template是html5新元素,主要用于保存客户端中的内容,表现为浏览器解析该内容但不渲染出来,可以将一个模板视为正在被存储以供随后在 ...

  8. 2.融合进阶:Stacking与Blending

    1 堆叠法Stacking 1.1 堆叠法的基本思想 堆叠法Stacking是近年来模型融合领域最为热门的方法,它不仅是竞赛冠军队最常采用的融合方法之一,也是工业中实际落地人工智能时会考虑的方案之一. ...

  9. Unity UGUI的RectMask2D(2D遮罩)组件的介绍及使用

    Unity UGUI的RectMask2D(2D遮罩)组件的介绍及使用 1. 什么是RectMask2D组件? RectMask2D是Unity UGUI中的一个组件,用于实现2D遮罩效果.它可以限制 ...

  10. DataGridView 控件分页

    在使用Winform开发桌面应用时,工具箱预先提供了丰富的基础控件,利用这些基础控件可以开展各类项目的开发.但是或多或少都会出现既有控件无法满足功能需求的情况,或者在开发类似项目时,我们希望将具有相同 ...