如果 Gradle 或 Gradle 社区没有提供您的项目所需的特定功能,创建您自己的插件可能是一个解决方案。
此外,如果您发现自己在子项目中重复构建逻辑,并且需要更好的方式来组织它,自定义插件可以提供帮助。
自定义插件
插件是实现该Plugin
接口的任何类。下面的例子是最简单的插件,一个“hello world”插件:
import org.gradle.api.Plugin
import org.gradle.api.Project
abstract class SamplePlugin : Plugin<Project> {
override fun apply(project: Project) {
project.tasks.create("SampleTask") {
println("Hello world!")
}
}
}
脚本插件
许多插件都是以构建脚本中编码的脚本插件开始的。这提供了一种在构建插件时快速原型化和实验的简单方法。让我们看一个例子:
// Define a task
abstract class CreateFileTask : DefaultTask() { (1)
@get:Input
abstract val fileText: Property<String> (2)
@Input
val fileName = "myfile.txt"
@OutputFile
val myFile: File = File(fileName)
@TaskAction
fun action() {
myFile.createNewFile()
myFile.writeText(fileText.get())
}
}
// Define a plugin
abstract class MyPlugin : Plugin<Project> { (3)
override fun apply(project: Project) {
tasks {
register("createFileTask", CreateFileTask::class) {
group = "from my plugin"
description = "Create myfile.txt in the current directory"
fileText.set("HELLO FROM MY PLUGIN")
}
}
}
}
// Apply the local plugin
apply<MyPlugin>() (4)
1 | 子类DefaultTask() . |
2 | 在任务中使用惰性配置。 |
3 | 扩展org.gradle.api.Plugin 接口。 |
4 | 应用脚本插件。 |
1. 子类DefaultTask()
首先,通过子类化来构建任务DefaultTask()
。
abstract class CreateFileTask : DefaultTask() { }
这个简单的任务将一个文件添加到我们应用程序的根目录中。
2.使用惰性配置
Gradle 有一个称为惰性配置的概念,它允许任务输入和输出在实际设置之前被引用。这是通过Property
类类型完成的。
abstract val fileText: Property<String>
这种机制的一个优点是,您可以将一个任务的输出文件链接到另一个任务的输入文件,所有这些都在文件名确定之前进行。该类Property
还知道它链接到哪个任务,从而使 Gradle 能够自动添加所需的任务依赖项。
3.扩展org.gradle.api.Plugin
接口
接下来,创建一个扩展该接口的新类org.gradle.api.Plugin
。
abstract class MyPlugin : Plugin<Project> {
override fun apply() {}
}
您可以在apply()
方法中添加任务和其他逻辑。
4.应用脚本插件
最后,在构建脚本中应用本地插件。
apply<MyPlugin>()
当MyPlugin
在构建脚本中应用时,Gradle 会调用fun apply() {}
自定义类中定义的方法MyPlugin
。
这使得该插件可供应用程序使用。
不推荐使用脚本插件。脚本插件提供了一种快速原型构建逻辑的简单方法,然后将其迁移到更永久的解决方案(例如约定插件或二进制插件)。 |
约定插件
约定插件是一种在 Gradle 中封装和重用常见构建逻辑的方法。它们允许您为项目定义一组约定,然后将这些约定应用到其他项目或模块。
上面的示例已被重写为存储在的约定插件buildSrc
:
import org.gradle.api.DefaultTask
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import java.io.File
abstract class CreateFileTask : DefaultTask() {
@get:Input
abstract val fileText: Property<String>
@Input
val fileName = project.rootDir.toString() + "/myfile.txt"
@OutputFile
val myFile: File = File(fileName)
@TaskAction
fun action() {
myFile.createNewFile()
myFile.writeText(fileText.get())
}
}
class MyConventionPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.tasks.register("createFileTask", CreateFileTask::class.java) {
group = "from my plugin"
description = "Create myfile.txt in the current directory"
fileText.set("HELLO FROM MY PLUGIN")
}
}
}
可以给插件一个id
usinggradlePlugin{}
块,以便可以在根中引用它:
gradlePlugin {
plugins {
create("my-convention-plugin") {
id = "com.gradle.plugin.my-convention-plugin"
implementationClass = "com.gradle.plugin.MyConventionPlugin"
}
}
}
该gradlePlugin{}
块定义了项目正在构建的插件。使用新创建的id
,该插件可以相应地应用到其他构建脚本中:
plugins {
application
id("com.gradle.plugin.my-convention-plugin") // Apply the new plugin
}