Create standalone Gradle plugin by example

通过一个简单的实例,学习如何创建Gradle插件。

Gradle plugin

一个插件就是一个实现了Plugin接口的Class而已。所以开发一个插件其实
就是创建一个实现了Plugin接口的Class。

Gradle插件有三种实现方式:

  1. 直接把Class放到build.gradle脚本中
  2. 在project的根目录下创建一个名为buildSrc的工程作为插件的实现,
    Gradle在build时会自动关注这个工程
  3. 一个独立的project,它会将插件打包成一个.jar文件

创建一个独立的Gradle插件

一个插件就是一个实现了Plugin接口的Class而已。

一个独立的Gradle插件其实就是一个普通的.jar文件,而且Gradle并不关心
这个jar文件是通过什么语言实现的,可以用Java,也可以用Groovy,甚至可以用
Scala,都可以。所以说开发Gradle插件并没有语言限制。

每个插件都有一个id,这才是Gradle关心的,Gradle会根据plugin id以及plugin version
在classpath中寻找<plugin id>-<plugin version>.jar这个文件,找到该文件之后,
Gradle怎么知道jar文件中哪个Class实现了Plugin接口呢?

答案是:META-INF。Gradle会查找该jar文件的META-INF/gradle-plugins/<plugin id>.properties
文件,该文件里面记录了实现Plugin接口的Class,

1
implementation-class=com.example.greetings.GreetingPlugin

注意,plugin id一般是group.name这种格式,如com.google.android,但是这并不是
强制的,完全可以用abc来作为plugin id,由此观之,plugin id里面的group,name
与代码里的package是没啥关系的。

既然如此,我们在一个jar里面放置多个<plugin id>.properties文件,让它们的内容完全
一样,这样我们的插件就可以拥有多个plugin id了,是否可行呢?当然可以!

一般,我们用Groovy来开发插件,所以可以把META-INF/gradle-plugins/<plugin id>.properties
放到src/main/resources/目录下,这样生成jar文件时它就会被打包进去了。

剩下的就是正常开发Groovy项目的步骤,不必多说。

build.gradle
1
2
3
4
5
6
7
8
apply plugin: 'groovy'

version = '1.0'

dependencies {
compile gradleApi()
compile localGroovy()
}
GreetingPlugin.groovy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.example.greetings

import org.gradle.api.Plugin;
import org.gradle.api.Project;

class GreetingPlugin implements Plugin<Project> {
void apply(Project project) {
project.extensions.create("greeting", GreetingPluginExtension)
project.task('hello') << {
println "${project.greeting.message} from ${project.greeting.greeter}"
}
}
}

class GreetingPluginExtension {
String message
String greeter
}

最后,gradle jar生成jar文件即可。

应用插件

build.gradle of another project
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
buildscript {
repositories {
maven {
url uri('path/to/your/jar/related/to/project/dir')
}
}

dependencies {
// 用于查找.jar文件
classpath 'com.ybin:greetings:1.0'
}
}

// .jar文件中包含多个<plugin id>.properties文件,
// 则该插件就有多个id
//apply plugin: 'greetings'
apply plugin: 'com.ybin.greetings'

greeting {
message = 'Hi'
greeter = 'Gradle'
}