首页 文章

使用Java创建Gradle自定义插件

提问于
浏览
33

我正在使用Gradle创建一个构建过程,我想提供一个使用Java代码的插件 . Gradle plugin documentation说这是可能的:

您可以使用您喜欢的任何语言实现自定义插件,前提是实现最终编译为字节码 . 对于这里的示例,我们将使用Groovy作为实现语言 . 如果需要,您可以使用Java或Scala .

但是,经过多个小时的谷歌搜索和阅读,我还没有找到任何解释如何使用Java创建Gradle自定义插件 . 看起来你可以在以下目录中为它创建代码:

<rootProjectDir>/buildSrc/src/main/java/
  MyGradlePlugin.java
  MyGradleTasks.java

但问题就变成了:

  • 如何在Java中实现插件类和任务以与Gradle兼容?

  • 如何让Gradle识别Java类和任务,以便在构建中使用它们?

你可以像引用Groovy一样引用插件类吗?

src/main/resources/META-INF/gradle-plugins/myjavaplugin.properties implementation-class=org.me.MyGradlePlugin

我意识到我可以用 project.javaexecJavaExec 调用Java代码,但我担心这会使我的构建过程不那么便携 .

3 回答

  • 23

    这是一个基本的,独立的,基于Java的Gradle插件以及使其工作的步骤:

    • 确保已安装Gradle 1.6或更高版本以及Java JDK

    • 使用指示的目录结构在下面创建这些文件

    • 将目录更改为 <projectRoot>/plugin 目录

    • 执行插件构建: $ gradle uploadArchives 这个(非常重要的)步骤编译Java代码并将其放入您当地的Maven仓库(../repo) .

    • 现在通过将目录更改为 <projectRoot>/consumer 来执行使用者脚本

    • 执行依赖于插件的脚本: $ gradle checkitout

    Java类

    projectRoot/plugin/src/main/java/org/joefernandez/gradle/MyJavaPlugin.java

    package org.joefernandez.gradle;
    
    import org.gradle.api.Project;
    import org.gradle.api.Plugin;
    
    public class MyJavaPlugin implements Plugin<Project> {
    
        @Override
        public void apply(Project target) {
            target.task("javaTask");
        }
    
    }
    

    projectRoot/plugin/src/main/java/org/joefernandez/gradle/MyJavaTask.java

    package org.joefernandez.gradle;
    
    import org.gradle.api.DefaultTask;
    import org.gradle.api.tasks.TaskAction;
    
    public class MyJavaTask extends DefaultTask {
    
        @TaskAction
        public void javaTask() {
            System.out.println("Hello from MyJavaTask");
        }
    
    }
    

    插件类声明

    projectRoot/plugin/src/main/resources/META-INF/gradle-plugins/test-plugin.properties

    implementation-class=org.joefernandez.gradle.MyJavaPlugin
    

    插件构建脚本

    请注意uploadArchives任务:您必须运行此任务才能使插件可供使用者脚本使用 .

    projectRoot/plugin/build.gradle

    apply plugin: 'java'
    
    dependencies {
        compile gradleApi()
    }
    
    apply plugin: 'maven'
    
    repositories {
        mavenCentral()
    }
    
    dependencies {
        testCompile 'junit:junit:4.11'
    }
    
    group = 'org.joefernandez'
    version = '1.0-SNAPSHOT'
    
    uploadArchives {
        repositories {
            mavenDeployer {
                repository(url: uri('../repo'))
            }
        }
    }
    

    插件的设置

    projectRoot/plugin/settings.gradle

    rootProject.name = 'MyJavaPlugin'
    

    根脚本

    projectRoot/build.gradle

    apply plugin: 'java'
    
    dependencies {
        compile gradleApi()
    }
    

    消费者脚本

    projectRoot/consumer/build.gradle

    buildscript {
        repositories {
            maven {
                url uri('../repo')
            }
        }
        dependencies {
            classpath group: 'org.joefernandez',
                       name: 'MyJavaPlugin',
                    version: '1.0-SNAPSHOT'
        }
    }
    apply plugin: 'test-plugin'
    
    task checkitout(type: org.joefernandez.gradle.MyJavaTask) {
        println("running consumer task!")
    }
    
  • 67

    我想对乔的伟大答案提出一些修正 .

    projectRoot/plugin/src/main/java/org/joefernandez/gradle/MyJavaPlugin.java

    此更改将任务连接到提供的项目,而无需对其进行子类化 .

    package org.joefernandez.gradle;
    
    import org.gradle.api.Project;
    import org.gradle.api.Plugin;
    
    public class MyJavaPlugin implements Plugin<Project> {
    
        @Override
        public void apply(Project target) {
            // CHANGE HERE
            target.getTasks().create("javaTask", MyJavaTask.class);
        }
    
    }
    

    消费者脚本

    projectRoot/consumer/build.gradle

    此更改将删除现在不必要的任务定义

    buildscript {
        repositories {
            maven {
                url uri('../repo')
            }
        }
        dependencies {
            classpath group: 'org.joefernandez',
                       name: 'MyJavaPlugin',
                    version: '1.0-SNAPSHOT'
        }
    }
    apply plugin: 'test-plugin'
    
    // CHANGE HERE
    

    他们将步骤6更改为:

    Execute the script that depends on the plugin: $ gradle javaTask

  • 3

    插件类必须实现 org.gradle.api.Plugin 接口 . 任务类通常扩展 org.gradle.api.DefaultTask 类 . 使用哪种(JVM)语言并不重要 . Gradle代码库包含许多用Java实现的插件和任务类 .

    如何构建和发布插件是另一个问题,再次与使用哪种语言无关 . 请参阅完整Gradle分布中的Gradle User Guidesamples/customPlugin .

相关问题