Gradle 在它的核心中有意地提供了一些小但有用的功能,用于在真实世界中的自动化。所有有用的功能,例如以能够编译 Java 代码为例,都是通过 插件 进行添加的。插件添加了新任务(例如
JavaCompile
),域对象(例如
SourceSet
),约定(例如主要的 Java 源代码是位于
src/main/java
),以及扩展的核心对象和其他插件的对象。
Gradle at its core intentionally provides little useful functionality for real world automation. All of the useful
features, such as the ability to compile Java code for example, are added by
plugins
.
Plugins add new tasks (e.g.
JavaCompile
), domain objects (e.g.
SourceSet
), conventions (e.g. main Java source is located at
src/main/java
) as well as extending core objects and objects from other plugins.
在这一章中,我们将讨论如何使用插件以及术语和插件相关的概念。
In this chapter we will discuss how to use plugins and the terminology and concepts surrounding plugins.
插件都认为是被
应用
,通过
Project.apply()
方法来完成。
Plugins are said to be
applied
, which is done via the
Project.apply()
method.
插件都有表示它们自己的一个短名称。. 在上述例子中,我们使用短名称
java
去应用
JavaPlugin
。
Plugins advertise a short name for themselves. In the above case, we are using the short name ‘
java
’ to apply
the
JavaPlugin
.
我们还可以使用下面的语法:
We could also have used the following syntax:
示例 21.2. 通过类型应用插件
Example 21.2. Applying a plugin by type
build.gradle
apply plugin: org.gradle.api.plugins.JavaPlugin
由于 Gradle 的默认导入 (见
附录 E,
现有的 IDE 支持和如何应对不支持的情况),您还可以这样写:
Thanks to Gradle's default imports (see
Appendix E, Existing IDE Support and how to cope without it
) you could also write:
插件的应用是
幂等的
。也就是说,一个插件可以被应用多次。如果以前已应用了该插件,任何进一步的应用都不会再有任何效果。
The application of plugins is
idempotent
. That is, a plugin can be applied multiple times. If the plugin
has previously been applied, any further applications will have no effect.
一个插件是任何实现了
Plugin
接口的简单的类。Gradle
提供了核心插件作为其发行包的一部分,所以简单地应用如上插件是你所需要做的。然而,对于第三方插件,你需要进行配置以使插件在构建类路径中可用。有关如何进行此操作的详细信息,请参阅
59.5章节,“构建脚本的外部依赖”。
A plugin is simply any class that implements the
Plugin
interface. Gradle provides
the core plugins as part of its distribution so simply applying the plugin as above is all you need to do.
For 3rd party plugins however, you need to make the plugins available to the build classpath. For more information
on how to do this, see
Section 59.5, “External dependencies for the build script”
.
关于编写自己的插件的详细信息,请参阅
58章节,
编写自定义插件。
For more on writing your own plugins, see
Chapter 58, Writing Custom Plugins
.
把插件应用到项目中可以让插件来扩展项目的功能。它可以做的事情如:
Applying a plugin to the project allows the plugin to extend the project's capabilities. It can do things
such as:
让我们来看看:
Let's check this out:
示例 21.4. 通过插件添加任务
Example 21.4. Tasks added by a plugin
build.gradle
apply plugin: 'java'
task show << {
println relativePath(compileJava.destinationDir)
println relativePath(processResources.destinationDir)
}
gradle -q show
的输出结果
Output of gradle -q show
> gradle -q show build/classes/main build/resources/main
Java 插件已经向项目添加了
compileJava
任务和
processResources
任务,并且配置了这两个任务的
destinationDir
属性。
The Java plugin has added a
compileJava
task and a
processResources
task
to the project and configured the
destinationDir
property of both of these tasks.
插件可以通过智能的方法对项目进行预配置以支持约定优于配置。Gradle
对此提供了机制和完善的支持,而它是强大-然而-简洁的构建脚本中的一个关键因素。
Plugins can pre-configure the project in smart ways to support convention-over-configuration. Gradle
provides mechanisms and sophisticated support and it's a key ingredient in powerful-yet-concise build scripts.
在上面的示例中我们看到,Java 插件添加了一个任务,名字为
compileJava
,有一个名为
destinationDir
的属性(即配置编译的 Java 代码存放的地方)。Java
插件默认此属性指向项目目录中的
build/classes/main
。这是通过一个
合理的默认
的约定优于配置的例子。
We saw in the example above that the Java plugins adds a task named
compileJava
that has
a property named
destinationDir
(that configures where the compiled Java source should be placed).
The Java plugin defaults this property to point to
build/classes/main
in the project directory.
This is an example of convention-over-configuration via a
reasonable default
.
我们可以简单地通过给它一个新的值来更改此属性。
We can change this property simply by giving it a new value.
示例 21.5. 更改插件的默认设置
Example 21.5. Changing plugin defaults
build.gradle
apply plugin: 'java' compileJava.destinationDir = file("$buildDir/output/classes") task show << { println relativePath(compileJava.destinationDir) }
gradle -q show
的输出结果
Output of gradle -q show
> gradle -q show build/output/classes
然而,
compileJava
任务很可能不是唯 一需要知道类文件在哪里的任务。
However, the
compileJava
task is likely to not be the only task that needs to know where
the class files are.
Java 插件添加了
source sets
的概念 (见
SourceSet
)
来描述的源文件集的各个方面,其中一个方面是在编译的时候这些类文件应该被写到哪个地方。Java
插件将
compileJava
任务的
destinationDir
属性映射到源文件集的这一个方面。
The Java plugin adds the concept of
source sets
(see
SourceSet
)
to describe the aspects of a set of source, one aspect being where the class files should be written to when it is compiled.
The Java plugin maps the
destinationDir
property of the
compileJava
task to this aspect of the source set.
我们可以通过这个源码集修改写入类文件的位置。
We can change where the class files are written via the source set.
示例 21.6. 插件中的约定对象
Example 21.6. Plugin convention object
build.gradle
apply plugin: 'java' sourceSets.main.output.classesDir = file("$buildDir/output/classes") task show << { println relativePath(compileJava.destinationDir) }
gradle -q show
的输出结果
Output of
gradle -q show
> gradle -q show build/output/classes
在上面的示例中,我们应用 Java 插件,除其他外,还做了下列操作:
In the example above, we applied the Java plugin which, among other things, did the following:
所有这一切都发生在
apply plugin:
"java"
这一步过程中。在上面例子中,我们在约定配置被执行之后,
修改了
类文件所需的位置。在上面的示例中可以注意到,
compileJava.destinationDir
的值也被修改了,以反映出配置的修改。
All of this happened during the
apply plugin: "java"
step. In the example above, we
changed
the desired location of the class files after this conventional configuration had been performed. Notice by the output with the example
that the value for
compileJava.destinationDir
also changed to reflect the configuration change.
考虑一下另一种消费类文件的任务的情况。如果这个任务使用
sourceSets.main.output.classesDir
的值来配置,那么修改了这个位置的值,无论它是什么时候被修改,将同时更新
compileJava
任务和这一个消费者任务。
Consider the case where another task is to consume the classes files. If this task is configured to use the value from
sourceSets.main.output.classesDir
, then changing it in this location will update both the
compileJava
task and this other consumer task whenever it is changed.
这种配置对象的属性以在所有时间内(甚至当它更改的时候)反映另一个对象的任务的值的能力被称为“
映射约定
”。它可以令 Gradle
通过约定优于配置及合理的默认值来实现简洁的配置方式。而且,如果默认约定需要进行修改时,也不需要进行完全的重新配置。如果没有这一点,在上面的例子中,我们将不得不重新配置需要使用类文件的每个对象。
This ability to configure properties of objects to reflect the value of another object's task at all times (i.e. even when it changes) is
known as “
convention mapping
”. It allows Gradle to provide conciseness through convention-over-configuration and
sensible defaults yet not require complete reconfiguration if a conventional default needs to be changed. Without this, in the example above,
we would have had to reconfigure every object that needs to work with the class files.
这一章旨在作为对插件和 Gradle
及他们扮演的角色的导言。关于插件的内部运作的详细信息,请参阅
第 58 章,
编写自定义插件。
This chapter aims to serve as an introduction to plugins and Gradle and the role they play. For more information on the inner workings
of plugins, see
Chapter 58,
Writing Custom Plugins
.