vlambda博客
学习文章列表

读书笔记《gradle-effective-implementations-guide-second-edition》从Gradle开始

Chapter 1. Starting with Gradle

当我们开发软件时,我们编写、编译、测试、打包,最后分发代码。我们可以通过使用构建系统来自动化这些步骤。最大的优势是我们有一个可重复的步骤序列。构建系统将始终遵循我们定义的步骤,因此我们可以专注于编写实际代码,而不必担心其他步骤。

Gradle 就是这样一种构建系统。

在本章中,我们将介绍以下主题:

  • Gradle 入门

  • 编写我们的第一个构建脚本

  • 查看默认任务

  • 了解命令行选项

  • 讨论 Gradle 图形用户界面

Gradle 是一个构建自动化的工具。使用 Gradle,我们可以自动编译、测试、打包和部署我们的软件或任何其他类型的项目。 Gradle 很灵活,但对大多数项目都有合理的默认值。这意味着如果我们不想要一些特殊的东西,我们可以依赖默认值,但我们仍然可以使用灵活性来调整构建以适应某些自定义需求。

Gradle 已被 Spring、Hibernate 和 Grails 等大型开源项目使用。 LinkedIn 和 Netflix 等企业公司也使用 Gradle。

在本章中,我们将解释 Gradle 是什么以及如何在我们的开发项目中使用它。

让我们看一下 Gradle 的一些特性。

Declarative builds and convention over configuration


Gradle 使用基于 Groovy 的 Domain Specific Language (DSL)声明构建。 DSL 提供了一种灵活的语言,我们可以对其进行扩展。由于 DSL 基于 Groovy,我们可以编写 Groovy 代码来描述构建并使用 Groovy 语言的强大功能和表现力。 Groovy 是一种用于 Java 虚拟机 (JVM ),例如 Java 和 Scala。 Groovy 使使用集合变得容易,具有闭包和许多有用的特性。语法与Java 语法密切相关。事实上,我们可以用 Java 语法编写一个 Groovy 类文件,它会编译。然而,使用 Groovy 语法更容易表达代码意图,而且我们需要的样板代码比使用 Java 的要少。要充分利用 Gradle,最好同时学习 Groovy 语言的基础知识,但不必开始编写 Gradle 脚本。

Gradle 被设计成一种构建语言,而不是一个死板的框架。 Gradle 核心本身是用 Java 和 Groovy 编写的。要扩展 Gradle,我们可以使用 Java 和 Groovy 编写我们的自定义代码。如果我们愿意,我们甚至可以在 Scala 中编写我们的自定义代码。

Gradle 为 Java、Groovy、Scala、web 和 OSGi 项目提供开箱即用的支持。这些项目具有我们自己可能已经使用的合理的约定优于配置的设置。但是,如果我们的项目需要,我们可以灵活地更改这些配置设置。

Support for Ant Tasks and Maven repositories

Gradle 支持 Ant 任务 和项目。我们可以导入 Ant 构建并重用所有任务。但是,我们也可以编写依赖于 Ant Tasks 的 Gradle 任务。集成也适用于属性、路径等。

支持 Maven 和 Ivy 存储库发布或获取依赖项。因此,我们可以继续使用我们已经拥有的任何存储库基础设施。

Incremental builds

使用 Gradle,我们可以进行增量构建。这意味着构建中的任务仅在必要时执行。例如,编译源代码的任务将首先检查自上次执行任务以来源代码是否发生了变化。如果源已更改,则执行任务;但如果源未更改,则跳过任务的执行并将任务标记为最新。

Gradle 为许多提供的任务支持这种机制。但是,我们也可以将它用于我们自己编写的任务。

Multi-project builds

Gradle 对多项目构建有很好的支持。一个项目可以简单地依赖于其他项目,也可以是其他项目的依赖项。我们可以定义项目之间的依赖关系图,Gradle 可以为我们解决这些依赖关系。我们可以根据需要灵活定义项目布局。

Gradle 支持部分构建。这意味着 Gradle 将确定我们的项目所依赖的项目是否需要重建。如果项目需要重新构建,Gradle 会在构建我们自己的项目之前执行此操作。

Gradle Wrapper

Gradle Wrapper 允许我们在计算机上未安装 Gradle 的情况下执行 Gradle 构建。这是分发源代码并为构建系统提供源代码以便构建源代码的好方法。

同样在企业环境中,我们可以为客户端计算机构建软件的零管理方式。我们可以使用包装器来强制使用某个 Gradle 版本,以便整个团队使用相同的版本。我们还可以更新包装器的 Gradle 版本,整个团队将使用更新的版本,因为包装器代码已签入到版本控制中。

Free and open source

Gradle 是一个开源项目,它根据 Apache License (ASL )。

Getting started


在本节中,我们将在编写第一个 Gradle 构建脚本之前下载并安装 Gradle。

在我们安装 Gradle 之前,我们必须确保我们的计算机上安装了 Java Development SE Kit (JDK)。 Gradle 需要 JDK 6 或更高版本。 Gradle 将使用在我们计算机路径上找到的 JDK。我们可以通过在命令行上运行以下命令来检查这一点:

$ java -version

虽然 Gradle 使用了 Groovy,但我们不必自己安装 Groovy。 Gradle 将 Groovy 库与发行版捆绑在一起,并将忽略我们计算机上已经可用的 Groovy 安装。

Gradle 位于 Gradle 网站 http://www.gradle.org/downloads。从这个页面,我们可以下载最新版本的 Gradle。如果需要,我们也可以下载旧版本。我们可以在三种不同的发行版中进行选择下载。我们可以下载包含二进制文件、源代码和文档的完整 Gradle 发行版;或者我们只能下载二进制文件;或者我们只能下载源代码。

要开始使用 Gradle,我们将下载包含二进制文件、源代码和文档的标准发行版。在编写本书时,当前版本是 2.12。

Installing Gradle

Gradle 被打包为三个发行版之一的 ZIP 文件。因此,当我们下载了 Gradle 全发行版 ZIP 文件后,我们必须解压缩该文件。解压 ZIP 文件后,我们有:

  •  bin 目录中的二进制文件

  •  doc 目录中包含用户指南、Groovy DSL 和 API 文档的文档

  •  samples目录下有很多样例

  •  src目录下Gradle的源码

  •  lib 目录下 Gradle 的支持库

  • 一个名为 init.d的目录,我们可以在其中存放每次运行Gradle时需要执行的Gradle脚本

一旦我们将 Gradle 发行版解压到一个目录,我们就可以打开一个命令提示符。我们转到安装 Gradle 的目录。为了检查我们的安装,我们运行 gradle -v 并使用所使用的 JDK 和库版本的 Gradle 获得输出,如下所示:

$ gradle -v
------------------------------------------------------------
Gradle 2.12
------------------------------------------------------------
Build time:   2016-03-14 08:32:03 UTC
Build number: none
Revision:     b29fbb64ad6b068cb3f05f7e40dc670472129bc0
Groovy:       2.4.4
Ant:          Apache Ant(TM) version 1.9.3 compiled on             December23 2013
JVM:          1.8.0_66 (Oracle Corporation 25.66-b17)
OS:           Mac OS X 10.11.3 x86_64

在这里,我们可以检查显示的版本是否与我们从 Gradle 网站下载的分发版本相同。

要在我们的计算机上运行 Gradle,我们只需将 $GRADLE_HOME/bin 添加到我们的 PATH 环境变量中。完成此操作后,我们可以从计算机上的每个目录运行 gradle 命令。

如果我们想在 Gradle 中添加 JVM options,我们可以使用  JAVA_OPTS 和   ;GRADLE_OPTS 环境变量。 JAVA_OPTS 是一个常用的环境变量名称,用于将额外参数传递给 Java 应用程序。 Gradle 还使用 GRADLE_OPTS 环境变量将额外的参数传递给 Gradle。两个环境变量都被使用了,所以我们甚至可以用不同的值来设置它们。这主要用于设置,例如,HTTP 代理或额外的内存选项。

Installing with SKDMAN!

Software Development Kit Manager (SDKMAN!) 是一个工具管理软件开发工具包的版本,例如 Gradle。一旦我们安装了 SKDMAN!,我们就可以简单地使用 install 命令和 SDKMAN!下载 Gradle 并确保将其添加到我们的$PATH 变量中。软件开发者!可用于类 Unix 系统,例如 Linux、Mac OSX 和 Cygwin(在 Windows 上)。

首先,我们需要安装 SDKMAN! 在我们的 shell 中使用以下命令:

$ curl -s get.sdkman.io | bash

接下来,我们可以使用 install 命令安装 Gradle:

$ sdk install gradle
Downloading: gradle 2.12
% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0   354    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100 42.6M  100 42.6M    0     0  1982k      0  0:00:22  0:00:22 --:--:-- 3872k
Installing: gradle 2.12
Done installing!
Do you want gradle 2.12 to be set as default? (Y/n): Y
Setting gradle 2.12 as default.

如果我们有多个版本的 Gradle,使用 use 命令很容易在版本之间切换:

$ sdk use gradle 2.12
Using gradle version 2.12 in this shell.

Writing our first build script


我们现在有一个正在运行的 Gradle 安装。是时候创建我们的第一个 Gradle 构建脚本了。 Gradle 使用项目的概念来定义一组相关的任务。一个 Gradle 构建可以有一个或多个项目。项目在 Gradle 中是一个非常广泛的概念,但它主要是我们想要为我们的应用程序构建的一组组件。

一个项目有一个或多个任务。任务是需要由构建执行的工作单元。任务示例包括编译源代码、将类文件打包成 JAR 文件、运行测试和部署应用程序。

我们现在知道任务是项目的一部分,所以要创建我们的第一个任务,我们还要创建我们的第一个 Gradle 项目。我们使用 gradle 命令来运行构建。 Gradle 将在当前目录中查找名为 build.gradle 的文件。该文件是我们项目的构建脚本。我们定义了需要在这个构建脚本文件中执行的任务。

我们创建一个新的 build.gradle 文件并在文本编辑器中打开它。我们输入以下代码来定义我们的第一个 Gradle 任务:

task helloWorld << { 
    println 'Hello world.' 
} 

使用此代码,我们将定义一个 helloWorld 任务。该任务会将单词 Hello world.打印到控制台。  println 是一种 Groovy 将文本打印到控制台的方法,基本上是一种速记 System.out.println Java 方法的版本。

括号之间的代码是 closure。闭包是可以分配给变量或传递给方法的代码块。 Java 不支持闭包,但 Groovy 支持。由于 Gradle 使用 Groovy 定义构建脚本,我们可以在构建脚本中使用闭包。

<< 语法从技术上讲是 leftShift()方法的运算符简写,实际上意味着  添加到。因此,在这里我们定义我们想要将闭包(使用 println 'Hello world' 语句)添加到我们的任务中,使用  helloWorld 名称。

首先,我们保存 build.gradle,并使用 gradle helloWorld 命令,执行我们的构建:

$ gradle helloWorld
:helloWorld
Hello world.
BUILD SUCCESSFUL
Total time: 2.384 secs
This build could be faster, please consider using the Gradle  Daemon: https://docs.gradle.org/2.12/userguide/gradle_daemon.html

输出的第一行显示了我们的行 Hello world。 Gradle 添加了更多输出,例如构建成功的事实和构建的总时间。由于 Gradle 在 JVM 中运行,每次我们运行 Gradle 构建时,也必须启动 JVM。输出的最后一行显示了一个提示,我们可以使用 Gradle 守护程序来运行我们的构建。稍后我们将讨论更多关于 Gradle 守护进程的信息,但它本质上是让 Gradle 在内存中运行,这样我们就不会因为每次运行 Gradle 时都启动 JVM 而受到惩罚。这大大加快了任务的执行速度。

我们可以再次运行相同的构建,但只能使用 Gradle --quiet 或 -q 输出我们的任务命令行选项。 Gradle 将抑制除错误消息之外的所有消息。当我们使用 --quiet(或 -q)选项时,我们得到以下输出:

$ gradle --quiet helloWorld
Hello world.

Default Gradle tasks


我们可以通过一项任务创建简单的构建脚本。我们可以让 Gradle 向我们展示我们项目的可用任务。 Gradle 有几个我们可以执行的内置任务。我们输入 gradle -q tasks 来查看我们项目的任务:

$ gradle -q tasks
------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------
Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]
Help tasks
----------
components - Displays the components produced by root project        'hello-world'. [incubating]
dependencies - Displays all dependencies declared in root project  'hello-world'.
dependencyInsight - Displays the insight into a specific n      dependency in root project 'hello-world'.
help - Displays a help message.
model - Displays the configuration model of root project   'hello-world'. [incubating]
projects - Displays the sub-projects of root project 'hello-world'.
properties - Displays the properties of root project 'hello-world'.
tasks - Displays the tasks runnable from root project 'hello-world'.
Other tasks
-----------
helloWorld
To see all tasks and more detail, run gradle tasks --all
To see more detail about a task, run gradle help --task <task>

在这里,我们在Other tasks部分看到了我们的helloWorld任务。 Gradle 内置任务显示在 帮助任务部分。例如,为了获取一些通用帮助信息,我们执行 help 任务:

$ gradle -q help
Welcome to Gradle 2.12.
To run a build, run gradle <task> ...
To see a list of available tasks, run gradle tasks
To see a list of command-line options, run gradle --help
To see more detail about a task, run gradle help --task <task>

properties 任务对于查看我们项目可用的属性非常有用。我们自己并没有在构建脚本中定义任何属性,但是 Gradle 提供了很多内置属性。以下输出显示了一些属性:

$ gradle -q properties
------------------------------------------------------------
Root project
------------------------------------------------------------
allprojects: [root project 'hello-world']
ant: org.gradle.api.internal.project.DefaultAntBuilder@3bd3d05e
antBuilderFactory: org.gradle.api.internal.project.DefaultAntBuilderFactory@6aba5d30
artifacts: org.gradle.api.internal.artifacts.dsl.DefaultArtifactHandler_Decorated@61d34b4
asDynamicObject: org.gradle.api.internal.ExtensibleDynamicObject@588307f7
baseClassLoaderScope: org.gradle.api.internal.initialization.DefaultClassLoaderScope@7df76d99

buildDir: /Users/mrhaki/Projects/gradle-effective-implementation-guide-2/gradle-impl-guide-2/src/docs/asciidoc/Chapter1/Code_Files/hello-world/build
buildFile: /Users/mrhaki/Projects/gradle-effective-implementation-guide-2/gradle-impl-guide-2/src/docs/asciidoc/Chapter1/Code_Files/hello-world/build.gradle
buildScriptSource: org.gradle.groovy.scripts.UriScriptSource@459cfcca
buildscript: org.gradle.api.internal.initialization.DefaultScriptHandler@2acbc859
childProjects: {}
class: class org.gradle.api.internal.project.DefaultProject_Decorated
classLoaderScope: org.gradle.api.internal.initialization.DefaultClassLoaderScope@6ab7ce48
components: []
configurationActions: org.gradle.configuration.project.DefaultProjectConfigurationActionContainer@2c6aed22
...

dependencies 任务将显示我们项目的依赖项(如果有的话)。我们的第一个项目没有任何依赖关系,正如我们运行任务时的输出所示:

$ gradle -q dependencies
------------------------------------------------------------
Root project
------------------------------------------------------------
No configurations

projects 任务将显示根项目的子项目(如果有)。我们的项目没有任何子项目。因此,当我们运行 projects 任务时,输出显示我们的项目没有子项目:

$ gradle -q projects
------------------------------------------------------------
Root project
------------------------------------------------------------
Root project 'hello-world'
No sub-projects
To see a list of the tasks of a project, run gradle <project-path>:tasks
For example, try running gradle :tasks

model 任务显示有关 Gradle 从我们的项目构建文件内部构建的模型的信息。此功能正在孵化中,这意味着该功能在 Gradle 的未来版本中可能会发生变化:

$ gradle -q model
------------------------------------------------------------
Root project
------------------------------------------------------------
+ model
+ tasks
     | Type:       org.gradle.model.ModelMap<org.gradle.api.Task>
        | Creator:     Project.<init>.tasks()
        + components
              | Type:       org.gradle.api.reporting.components.ComponentReport
              | Value:      task ':components'
              | Creator:     tasks.addPlaceholderAction(components)
              | Rules:
                ⤷ copyToTaskContainer
        + dependencies
              | Type:       org.gradle.api.tasks.diagnostics.DependencyReportTask
              | Value:      task ':dependencies'
              | Creator:     tasks.addPlaceholderAction(dependencies)
              | Rules:
...

我们将在本书中更多地讨论这些和其他任务。

Task name abbreviation


在我们查看更多 Gradle 命令行选项之前,最好先讨论一下 Gradle 的实时保存功能:任务名称缩写。使用任务名称缩写,我们不必在命令行中输入完整的任务名称。我们只需输入足够多的名称以使其在构建中唯一。

在我们的第一个构建中,我们只有一个任务,所以 gradle h 命令应该可以正常工作。但是,我们没有考虑内置 help 任务。因此,为了唯一标识我们的 helloWorld 任务,我们使用 hello 缩写:

$ gradle -q hello
Hello world.

我们还可以缩写 CamelCase 任务名称中的每个单词。比如我们的helloWorld任务名可以简写为 hW

$ gradle -q hW
Hello world.

此功能为我们节省了输入完整任务名称的时间,并且可以加快我们任务的执行速度。

Executing multiple tasks


通过一个简单的构建脚本,我们已经讨论了除了我们可以执行的我们自己的任务之外,我们还有几个默认任务。要执行多个任务,我们只需将每个任务名称添加到命令行。让我们执行我们的 helloWorld 自定义任务和内置 tasks 任务:

$ gradle helloWorld tasks
:helloWorld
Hello world.
:tasks
------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------
Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]
Help tasks
----------
 components - Displays the components produced by root project 'hello-world'. [incubating]
 dependencies - Displays all dependencies declared in root project 'hello-world'.
dependencyInsight - Displays the insight into a specific  dependency in root project 'hello-world'.
help - Displays a help message.
model - Displays the configuration model of root project 'hello-world'. [incubating]
projects - Displays the sub-projects of root project 'hello-world'.
properties - Displays the properties of root project 'hello-world'.
tasks - Displays the tasks runnable from root project 'hello-world'.
Other tasks
-----------
helloWorld
To see all tasks and more detail, run gradle tasks --all
To see more detail about a task, run gradle help --task <task>
BUILD SUCCESSFUL
Total time: 2.028 secs
This build could be faster, please consider using the Gradle Daemon: https://docs.gradle.org/2.12/userguide/gradle_daemon.html

我们看到了这两个任务的输出。首先,执行helloWorld,然后是 tasks。在输出中,我们看到任务名称前面有一个冒号 (:),输出在下一行。

Gradle 按照在命令行中定义的顺序执行任务。 Gradle 只会在构建期间执行一次任务。所以即使我们多次定义同一个任务,它也只会执行一次。当任务依赖于其他任务时,此规则也适用。 Gradle 将为我们优化任务执行,我们不必担心。

Command-line options


gradle 命令用于执行构建。此命令接受几个命令行选项。我们知道 --quiet(或 -q)选项可以减少构建的输出。如果我们使用 --help(或 -h或 -?< /code>) 选项,我们看到完整的选项列表,如下:

$ gradle --help
USAGE: gradle [option...] [task...]
-?, -h, --help          Shows this help message.
-a, --no-rebuild        Do not rebuild project dependencies.
-b, --build-file        Specifies the build file.
-c, --settings-file     Specifies the settings file.
--configure-on-demand   Only relevant projects are configured in this build run. This means faster build for large multi-project builds. [incubating]
--console               Specifies which type of console output to generate. Values are 'plain', 'auto' (default) or 'rich'.
--continue              Continues task execution after a task failure.
-D, --system-prop       Set system property of the JVM (e.g. -Dmyprop=myvalue).
-d, --debug             Log in debug mode (includes normal stacktrace).
--daemon                Uses the Gradle daemon to run the build. Starts the daemon if not running.
--foreground            Starts the Gradle daemon in the foreground. [incubating]
-g, --gradle-user-home  Specifies the gradle user home directory.
--gui                   Launches the Gradle GUI.
-I, --init-script       Specifies an initialization script.
-i, --info              Set log level to info.
-m, --dry-run           Runs the builds with all task actions disabled.
--max-workers           Configure the number of concurrent workers Gradle is allowed to use. [incubating]
--no-color              Do not use color in the console output. [deprecated - use --console=plain instead]
--no-daemon             Do not use the Gradle daemon to run the build.
--offline               The build should operate without accessing network resources.
-P, --project-prop      Set project property for the build script (e.g. -Pmyprop=myvalue).
-p, --project-dir       Specifies the start directory for Gradle. Defaults to current directory.
--parallel              Build projects in parallel. Gradle will attempt to determine the optimal number of executor threads to use. [incubating]
--parallel-threads      Build projects in parallel, using the specified number of executor threads. [deprecated - Please use --parallel, optionally in conjunction with --max-workers.] [incubating]
--profile               Profiles build execution time and generates a report in the <build_dir>/reports/profile directory.
--project-cache-dir     Specifies the project-specific cache directory. Defaults to .gradle in the root project directory.
-q, --quiet             Log errors only.
--recompile-scripts     Force build script recompiling.
--refresh-dependencies  Refresh the state of dependencies.
--rerun-tasks           Ignore previously cached task results.
-S, --full-stacktrace   Print out the full (very verbose) stacktrace for all exceptions.
-s, --stacktrace        Print out the stacktrace for all exceptions.
--stop                  Stops the Gradle daemon if it is running.
-t, --continuous        Enables continuous build. Gradle does not exit and will re-execute tasks when task file inputs change. [incubating]
-u, --no-search-upward  Don't search in parent folders for a settings.gradle file.
-v, --version           Print version info.
-x, --exclude-task      Specify a task to be excluded from execution.

Logging options

让我们更详细地看一些选项。 --quiet(或 -q), --debug (或 -d), --info(或 - i)、 --stacktrace(或-s)和 --full-stacktrace(或-S)选项控制我们在执行任务时看到的输出量。为了获得最详细的输出,我们使用 --debug(或 -d)选项。此选项提供大量输出,其中包含有关用于运行构建的步骤和类的信息。输出非常冗长,因此,我们不会使用太多。

为了更好地了解为我们的任务执行的步骤,我们可以使用 --info(或 -i) 选项。输出不像  --debug 那样冗长,但可以更好地理解构建步骤:

$ gradle --info helloworld
Starting Build
Settings evaluated using settings file '/master/settings.gradle'.
Projects loaded. Root project using build file '/Users/mrhaki/Projects/gradle-effective-implementation-guide-2/gradle-impl-guide-2/src/docs/asciidoc/Chapter1/Code_Files/hello-world/build.gradle'.
Included projects: [root project 'hello-world']
Evaluating root project 'hello-world' using build file '/Users/mrhaki/Projects/gradle-effective-implementation-guide-2/gradle-impl-guide-2/src/docs/asciidoc/Chapter1/Code_Files/hello-world/build.gradle'.
All projects evaluated.
Selected primary task 'helloWorld' from project :
Tasks to be executed: [task ':helloWorld']
:helloWorld (Thread[main,5,main]) started.
:helloWorld
Executing task ':helloWorld' (up-to-date check took 0.001 secs) due to:
  Task has not declared any outputs.
Hello world.
:helloWorld (Thread[main,5,main]) completed. Took 0.021 secs.
BUILD SUCCESSFUL
Total time: 1.325 secs
This build could be faster, please consider using the Gradle Daemon: https://docs.gradle.org/2.12/userguide/gradle_daemon.html

如果我们的构建抛出异常,我们可以使用 --stacktrace(或 -s)和  --full-stacktrace(或 -S)选项。后一个选项将输出最多的信息并且是最详细的。  --stacktrace 和 --full-stacktrace 选项可以与其他日志记录选项结合使用。

Changing the build file and directory

我们使用 build.gradle 名称创建了构建文件。这是构建文件的默认名称。 Gradle 将在当前目录中查找具有此名称的文件来执行构建。但是,我们可以使用 --build-file(或 -b)和 --project-dir(或 -p)命令行选项。

让我们从当前目录的父目录运行 gradle 命令:

$ cd ..
$ gradle --project-dir hello-world -q helloWorld
Hello world.

我们也可以将我们的 build.gradle 重命名为,例如, hello.build 并且仍然执行我们的构建:

$ mv build.gradle hello.build
$ gradle --build-file hello.build -q helloWorld
Hello world.

Running tasks without execution

使用 --dry-run (or -m) 选项,我们可以运行所有任务而不真正执行它们。当我们使用 dry-run 选项时,我们可以看到正在执行的任务,因此我们可以深入了解特定构建场景中涉及的任务。我们甚至不必担心任务是否真正执行。 Gradle 构建了一个 有向无环图 (DAG)执行任何任务之前的所有任务。构建 DAG 以便任务将按照依赖关系的顺序执行,并且一个任务只执行一次:

$ gradle --dry-run helloWorld
:helloWorld SKIPPED
BUILD SUCCESSFUL
Total time: 1.307 secs
This build could be faster, please consider using the Gradle Daemon: https://docs.gradle.org/2.12/userguide/gradle_daemon.html

Gradle daemon

我们已经讨论过 Gradle 在 JVM 中执行,每次调用 gradle 命令时,都会启动一个新的 JVM,加载 Gradle 类和库,然后执行构建.如果我们不必在每次执行构建时都加载 JVM 和 Gradle 类和库,我们可以减少构建执行时间。  --daemon 命令行选项启动一个新的 Java 进程,该进程将加载所有 Gradle 类和库,然后执行构建。下次当我们使用 --daemon 选项运行 Gradle 时,只会执行构建,因为具有所需 Gradle 类和库的 JVM 已经在运行。

我们第一次使用 --daemon 选项执行 Gradle 时,由于 Java 后台进程尚未启动,因此执行速度不会提高。但是,下一次,我们可以看到一个重大改进:

$ gradle --daemon helloWorld
Starting a new Gradle Daemon for this build (subsequent builds will be faster).
:helloWorld
Hello world.
BUILD SUCCESSFUL
Total time: 2.136 secs
$ gradle helloWorld
:helloWorld
Hello world.
BUILD SUCCESSFUL
Total time: 0.594 secs

即使启动了守护进程,我们仍然可以在不使用守护进程的情况下运行 Gradle 任务。我们使用 --no-daemon 命令行选项来运行 Gradle 构建,然后不使用守护进程:

$ gradle --no-daemon helloWorld
:helloWorld
Hello world.
BUILD SUCCESSFUL
Total time: 1.325 secs

要停止守护进程,我们使用 --stop 命令行选项:

$ gradle --stop
Stopping daemon(s).
Gradle daemon stopped.

这将完全停止 Java 后台进程。

始终使用 --daemon 命令行选项,但我们不想每次运行时都键入它 gradle 命令,如果我们的操作系统支持别名,我们可以创建一个别名。例如,在基于 Unix 的系统上,我们可以创建一个别名,然后使用该别名来运行 Gradle 构建:

$ alias gradled='gradle --daemon'
$ gradled helloWorld
:helloWorld
Hello world.
BUILD SUCCESSFUL
Total time: 0.572 secs

除了使用 --daemon 命令行选项,我们可以使用 org.gradle.daemon Java 系统属性来启用守护程序。我们可以将此属性添加到 GRADLE_OPTS 环境变量中,以便在我们运行 Gradle 构建时始终使用它:

$ export GRADLE_OPTS="-Dorg.gradle.daemon=true"
$ gradle helloWorld
:helloWorld
Hello world.
BUILD SUCCESSFUL
Total time: 0.575 secs

最后,我们可以在项目目录的根目录下添加一个 gradle.properties 文件。在该文件中,我们可以定义一个 org.gradle.daemon 属性并分配  true 值来启用 Gradle从此目录执行的所有构建的守护进程。

让我们创建一个 gradle.properties 文件,其内容如下:

org.gradle.daemon=true 

我们可以运行我们的示例任务 helloWorld,构建将使用 Gradle 守护进程:

$ gradle helloWorld
:helloWorld
Hello world.
BUILD SUCCESSFUL
Total time: 0.58 secs

Profiling

Gradle 还提供了 --profile 命令行选项。此选项记录完成某些任务所需的时间。数据保存在 build/reports/profile 目录中的 HTML 文件中。我们可以在 Web 浏览器中打开这个文件并检查构建过程中几个阶段所花费的时间。下图显示了配置文件报告的 HTML 内容:

读书笔记《gradle-effective-implementations-guide-second-edition》从Gradle开始

带有分析信息的 HTML 页面

Offline usage

如果我们无法访问某个位置的网络,我们可能会从 Gradle 构建中收到错误,例如,当任务需要从 Internet 下载某些内容时。我们可以使用 --offline 命令行选项来指示 Gradle 在构建期间不要访问任何网络。这样,如果所有必要的文件都已经离线可用并且我们没有收到错误,我们仍然可以执行构建。

Understanding the Gradle graphical user interface


最后,我们看一下 --gui 命令行选项。使用这个选项,我们为我们的 Gradle 构建启动了一个图形 shell。到目前为止,我们使用命令行来启动任务。使用 Gradle GUI,我们可以对项目中的任务进行图形化概览,只需单击鼠标即可执行它们。

要启动 GUI,我们调用以下命令:

$ gradle --gui

打开一个窗口,其中包含我们的任务树的图形概览。我们只有一个任务,它显示在任务树中,如下面的截图所示:

读书笔记《gradle-effective-implementations-guide-second-edition》从Gradle开始

Gradle GUI 中的任务概述

运行任务的输出显示在窗口底部。当我们第一次启动 GUI 时,tasks 任务被执行,我们在窗口中看到了输出。

Task tree

任务树选项卡显示在我们的构建项目中找到的项目和任务。我们可以通过双击任务名称来执行任务。

默认情况下会显示所有任务,但我们可以应用过滤器来显示或隐藏某些项目和任务。 Edit filter 按钮打开一个新的对话框窗口,我们可以在其中定义属于过滤器的任务和属性。  切换过滤器按钮使过滤器处于活动或非活动状态。

我们也可以右键单击项目和任务名称。这将打开一个上下文菜单,我们可以在其中选择执行任务、将其添加到收藏夹、隐藏它(将其添加到过滤器中)或编辑构建文件。如果我们已将 .gradle 扩展名与我们操作系统中的文本编辑器相关联,则编辑器将使用构建脚本的内容打开。这些选项可以在以下屏幕截图中看到:

读书笔记《gradle-effective-implementations-guide-second-edition》从Gradle开始

Gradle GUI 中任务的可用操作

Favorites

收藏夹选项卡存储我们要定期执行的任务。我们可以通过在 任务树选项卡中右键单击任务并选择 < strong>添加到收藏夹菜单选项,或者如果我们打开了 收藏夹选项卡,我们可以选择  添加按钮并手动输入我们要添加到收藏夹列表的项目和任务名称。我们可以在以下屏幕截图中看到 添加收藏夹对话框窗口:

读书笔记《gradle-effective-implementations-guide-second-edition》从Gradle开始

在 Gradle GUI 中添加收藏夹

Command line

在命令行选项卡上,我们可以输入通常在命令提示符下输入的任何 Gradle 命令。该命令也可以添加到 收藏夹。我们在下图中看到命令行标签内容:

读书笔记《gradle-effective-implementations-guide-second-edition》从Gradle开始

使用命令行选项执行任务

Setup

最后一个选项卡是设置选项卡。在这里,我们可以更改项目目录,默认设置为当前目录。

我们在本章前面讨论了不同的日志记录级别作为命令行选项。使用 GUI,我们可以从 Log Level 选择框中选择不同日志级别的日志级别。我们可以选择 debug信息生命周期和 错误作为日志级别。错误日志级别只显示错误并且是最不详细的,而调试是最详细的日志级别。生命周期日志级别是默认日志级别。

在这里,我们还可以设置异常堆栈跟踪信息的详细程度。在 Stack Trace Output 部分,我们可以从以下三个选项中进行选择:

  • Exceptions Only:这是为了只在异常发生时显示异常,这是默认值

  • 标准堆栈跟踪 (-s):用于显示更多异常堆栈跟踪信息

  • -S):这是针对异常的最详细的堆栈跟踪信息

如果我们启用 Only Show Output When Error Occurs 选项,那么我们只会在构建失败时从构建过程中获取输出。否则,我们不会得到任何输出。

最后,我们可以使用 Use Custom Gradle Executor 选项定义一种不同的方式来为构建启动 Gradle。例如,我们可以使用额外的设置信息定义不同的批处理或脚本文件来运行构建过程。以下屏幕截图显示了 设置标签页以及我们可以设置的所有选项:

读书笔记《gradle-effective-implementations-guide-second-edition》从Gradle开始

在 Gradle GUI 中设置 Gradle 选项

Summary


所以,现在我们已经讨论了如何在我们的计算机上安装 Gradle。我们用一个简单的任务编写了我们的第一个 Gradle 构建脚本。

我们还看到了如何使用 Gradle 的内置任务来获取有关项目的更多信息。我们讨论了如何使用命令行选项来帮助我们运行构建脚本。我们已经查看了 Gradle GUI 以及我们如何使用它来运行 Gradle 构建脚本。

在下一章中,我们将进一步研究任务。我们将讨论如何向任务添加操作。我们编写更复杂的任务,这些任务将依赖于其他任务。我们还将讨论 Gradle 如何在内部构建任务图以及如何在我们的项目中使用它。