Gradle Plugin开发手记
最近手头需要开发一个Gradle插件,于是研究了几天,基本实现了一个Gradle插件。总结一下Gradle插件开发的步骤。
- 首先需要建一个gradle工程,需要添加以下依赖
dependencies { compile gradleApi() compile 'org.codehaus.groovy:groovy:2.1.5' }
- 例如:新建一个groovy工程testPlugin,build.gradle如***意我这里为了简单使用的本地的maven库,发布到本地文件,都可以改成maven资源库。
apply plugin: "groovy" apply plugin: "maven" group = "my.test" version = "1.0-SNAPSHOT" defaultTasks 'clean', 'jar' sourceSets { main { groovy { srcDirs = [ 'src/main/groovy', 'src/main/java' ] } // compile everything in src/ with groovy java { srcDirs = []} // no source dirs for the java compiler } } repositories { mavenLocal() } dependencies { tasks.withType(Compile) { options.encoding = "UTF-8" } compile 'org.codehaus.groovy:groovy:2.1.5' compile gradleApi() } // custom tasks for creating source jars task sourcesJar(type: Jar, dependsOn:classes) { classifier = 'sources' from sourceSets.main.allSource } // add source jar tasks as artifacts artifacts { archives sourcesJar } // upload to local uploadArchives { repositories { flatDir { name 'localRepository' } } repositories { localRepository { dirs '../local-repo' } } }
- 配置sourceSets
- 注意gradle编译时,先执行compileJava,后执行compileGroovy
- gradle源码中compileGroovy是dependsOn compileJava的
- 解决java&groovy混合编译的问题
- 当java执行需要groovy编译完的class时,可以通过设置sourceSets来解决这个问题,即把java对应的srcDirs置为空,把java的src放入groovy中的srcDirs中,如下代码所示
sourceSets { main { groovy { srcDirs = ['src/main/groovy','src/main/java']} // compile everything in src/ with groovy java { srcDirs = []} // no source dirs for the java compiler } }
- 实现Plugin接口,完成插件的实现
- 插件可以是用Groovy编写,也可以是Java来编写,参考各自API即可
- 例如,我这里写了个简单的插件,为了混编java和groovy,实现java里获得groovy(build.gradle)中的变量,这个插件用两种方式给工程建立了两个task,注意TestPluginConvention是个groovy编译后的class
package com.test.gradle;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.tasks.Copy;
import com.test.task.TestTask;
public class TestPlugin implements Plugin<Project> {
@Override
public void apply(final Project project) {
// 引用groovy扩展变量
final TestPluginConvention pluginConvention = new TestPluginConvention(project);
project.getConvention().getPlugins().put("testPlugin", pluginConvention);
// 创建hello任务
project.getTasks().add("hello", TestTask.class);
// 创建copyAll任务
Copy copyTask = project.getTasks().add("copyAll", Copy.class);
copyTask.dependsOn(project.getPath() + ":jar");
copyTask.from(project.getConfigurations().getByName("runtime"));
copyTask.from(project.getBuildDir().getPath() + "/classes/main");
copyTask.from(project.getBuildDir().getPath() + "/classes/resources");
copyTask.into(project.getBuildDir().getPath() + "/dist");
}
}
package com.test.task;
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.TaskAction;
import com.test.gradle.TestPluginConvention;
public class TestTask extends DefaultTask {
@TaskAction
public void test() {
System.out.println("hello " + getProject().getName());
System.out.println("TestPlugin ext testName:"
+ ((TestPluginConvention) getProject().getConvention().getPlugins()
.get("testPlugin")).getTestName());
}
public void test2(Object object) {
System.out.println("to object:" + object);
}
}
package com.test.gradle; import org.gradle.api.Project public class TestPluginConvention { String testName; final Project project; def TestPluginConvention(Project project){ this.project = project; testName = 'test'; } public String getTestName(){ return testName; } }
- 在gradle工程中配置gradle plugin配置文件
- 在src/main/resources源码目录下,新建文件夹META-INF/gradle-plugins/,在文件夹里新建一个xxxx.properties,文件里内容如下
implementation-class=com.test.gradle.TestPlugin
- 注意
- xxxx.properties的xxxx为插件的名字,即在gradle配置中可以apply plugin ‘xxxx'
- xxx.xxx.xxx为org.gradle.api.Plugin的实现类的类名
- 注意
- 在src/main/resources源码目录下,新建文件夹META-INF/gradle-plugins/,在文件夹里新建一个xxxx.properties,文件里内容如下
工程结构如下
- 打包发布到资源库,可以是本地,也可以是maven库中
- 使用插件
- 在build.gradle引入插件
-
apply plugin: ‘xxxx’
-
- 在build.gradle 里引入buildscript
- 在build.gradle引入插件
buildscript {
repositories { flatDir { name 'localRepository'
} }
repositories { localRepository { dirs '../local-repo'
} }
dependencies {
classpath group: 'my.test', name: 'testPlugin', version: '1.0-SNAPSHOT'
}
}
- 测试插件工程的gradle build.gradle如下
apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'maven' apply plugin: 'test' buildscript { repositories { flatDir { name 'localRepository' } } repositories { localRepository { dirs '../local-repo' } } dependencies { classpath group: 'my.test', name: 'testPlugin', version: '1.0-SNAPSHOT' } } testName = "wensong" group = "com.test" version = "1.0-SNAPSHOT"
- 测试结果,可以看到TestTask中成功的拿到了build.gradle中的testName,并完成输出