`
wensong
  • 浏览: 125199 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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的实现类的类名
   工程结构如下


  • 打包发布到资源库,可以是本地,也可以是maven库中
  • 使用插件
    • 在build.gradle引入插件
      • apply plugin: ‘xxxx’
        
         
    • 在build.gradle 里引入buildscript

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,并完成输出


 

 

  • 大小: 44.1 KB
  • 大小: 36.4 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics