构建块
每个 Gradle 构建都包含三个基本构建块:projects、tasks 和 properties。 每个构建至少包含一个 project,而该 project 又包含一个或多个 task。 project 和 task 公开可用于控制构建的 property。 图 4.1 说明了 Gradle 核心组件之间的依赖关系。
Gradle 应用领域驱动设计 (DDD) 的原理来建模自己的领域构建软件。 因此,项目和任务在 Gradle 的 API 中具有直接的类表示。 让我们仔细看看每个组件及其 API 对应部分。
Projects
在 Gradle 的术语中,项目代表您尝试构建的组件(例如 JAR 文件),或者您尝试实现的目标,例如部署应用程序。 如果您来自 Maven,这个概念听起来应该很熟悉。 Gradle 相当于 Maven 的 pom.xml 是 build.gradle 文件。 每个 Gradle 构建脚本至少定义一个项目。 当开始构建过程时,Gradle 根据您在 build.gradle 中的配置实例化 org.gradle.api.Project 类,并通过项目变量使其隐式可用。 图 4.2 显示了 API 接口及其最重要的方法。


项目可以创建新任务、添加依赖项和配置以及应用插件和其他构建脚本。 它的许多属性,如 name 和 description,都可以通过 getter 和 setter 方法访问。
那么为什么我们一开始就谈论 Gradle 的 API 呢? 您会发现,在了解 Gradle 的基础知识后,您会想要进一步了解这些概念,并将这些概念应用到您的实际项目中。 API 是充分利用 Gradle 的关键。
Project 实例使您能够以编程方式访问构建中的所有 Gradle 功能,例如任务创建和依赖项管理。 在本书中,您将通过调用相应的 API 方法来使用其中的许多功能。 请记住,访问项目(Project 实例)的属性和方法时不需要使用 project 变量。 以下代码片段说明了 Project 实例上的有效方法调用:
setDescription("myProject") // 在不显式使用项目变量的情况下设置项目的描述
// 使用 Groovy 语法在使用和不使用 project 变量的情况下访问 name 和 description 属性
println "Description of project $name: " + project.description
在前面的章节中,您只需处理单个项目的构建。 Gradle 还提供对多项目构建的支持。 软件开发最重要的原则之一是关注点分离。 软件系统变得越复杂,您就越想将其分解为模块化功能,其中模块可以相互依赖。 每个分解的部分都将表示为具有自己的 build.gradle 脚本的 Gradle 项目。 为了简单起见,我们在这里不再赘述。 如果您渴望了解更多信息,请随时跳转到第 6 章,该章完全致力于在 Gradle 中创建多项目构建。 接下来,我们将了解任务的特征,这是 Gradle 的另一个核心构建块。
Tasks
您已经在第 2 章中创建了一些简单的任务。尽管我介绍的用例很琐碎,但您必须了解任务的一些重要功能:任务操作 和 任务依赖性。 操作定义了任务运行时执行的原子工作单元。 这可以像打印 “Hello world!” 这样的文本一样简单。 或者像编译 Java 源代码一样复杂,如第 2 章所示。很多时候,一个任务需要先运行另一个任务。 如果任务依赖于另一个任务产生的输出作为输入来完成自己的操作,则尤其如此。 例如,您已经看到需要先编译 Java 源代码,然后才能将其打包到 JAR 文件中。 我们来看一下 Gradle 的任务 API 表示,接口 org.gradle.api.Task,如图 4.3 所示。
Task 接口提供的方法比图中显示的还要多。 当您将它们应用于整本书的具体示例时,您将一一使用它们。 现在我们已经讨论了项目和任务,让我们看看不同类型的属性。

Properties
Project 和 Task 的每个实例都提供可通过 getter 和 setter 方法访问的属性。 属性可以是任务的描述或项目的版本。 在本章后面,您将在实际示例中阅读和修改这些值。 通常,您需要定义自己的属性。 例如,您可能想要声明一个变量来引用在同一构建脚本中多次使用的文件。 Gradle 允许通过额外的属性定义用户定义的变量。
额外的属性
Gradle 的许多域模型类都提供对临时属性的支持。 在内部,这些属性作为键值对存储在 map 中。 要添加属性,您需要使用 ext 命名空间。 让我们看一个具体的例子。 以下代码片段演示了可以通过多种不同方式添加、读取和修改属性:
// 只有额外属性的初始声明需要使用 ext 命名空间
project.ext.myProp = 'myValue'
ext {
someOtherProp = 123
}
// 使用 ext 命名空间来访问额外的属性是可选的
assert myProp == 'myValue'
println project.someOtherProp
ext.someOtherProp = 567
同样,可以通过属性文件提供其他属性。
GRADLE 属性
通过在 <USER_HOME>/.gradle 目录或项目根目录下名为 gradle.properties 的属性文件中声明属性,可以将属性直接注入到您的项目中。 可以通过项目实例访问它们。 请记住,即使您正在处理多个项目,每个用户在 <USER_HOME>/.gradle 下只能有一个 Gradle 属性文件。 这是目前 Gradle 的一个限制。 属性文件中声明的任何属性都可用于您的所有项目。 假设您的 gradle.properties 文件中声明了以下属性:
exampleProp = myValue
someOtherProp = 455
您可以按如下方式访问项目中的这两个变量:
assert project.exampleProp == 'myValue'
task printGradleProperty << {
println "Second property: $someOtherProp"
}