【问题标题】:Creating a Gradle Custom Plugin with Java使用 Java 创建 Gradle 自定义插件
【发布时间】:2013-07-15 21:22:02
【问题描述】:

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

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

然而,经过几个小时的谷歌搜索和阅读,我还没有找到任何关于如何使用 Java 创建 Gradle 自定义插件的解释。似乎您可以在如下目录中为其创建代码:

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

但问题就变成了:

  1. 如何在Java中实现插件类和任务以兼容Gradle?
  2. 如何让 Gradle 识别 Java 类和任务,以便在构建中使用它们?

    您可以像对 Groovy 等效项那样引用插件类吗?

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

我意识到我可以使用 project.javaexecJavaExec 调用 Java 代码,但我担心这会降低我的构建过程的可移植性。

【问题讨论】:

    标签: java gradle


    【解决方案1】:

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

    1. 确保 Gradle 1.6 或更高版本以及 Java JDK 已安装
    2. 在下面使用指示的目录结构创建这些文件
    3. 将目录更改为&lt;projectRoot&gt;/plugin 目录
    4. 执行插件构建:$ gradle uploadArchives 这个(非常重要的)步骤编译 Java 代码并将其放入本地 Maven 存储库 (../repo)。
    5. 现在通过将目录更改为&lt;projectRoot&gt;/consumer 来执行消费者脚本
    6. 执行依赖插件的脚本:$ 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!")
    }
    

    【讨论】:

    • 指定repository(url: uri('../repo')) 是可选的。您可以改为导出到默认的本地存储库。并从 mavenLocal() 导入。
    • 我根据 Joe 在 github.com/AttwellBrian/SamplePlugin/tree/master 的描述创建了一个 Android Studio 项目。随意分叉或复制意大利面。
    • 不适合我。 Gradle 可能改变了一些东西
    【解决方案2】:

    我想对乔的好回答提出一些修改意见。

    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

      【讨论】:

      • 谢谢,彼得!这让我走上了正轨。我会尽快发布我的解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-13
      • 1970-01-01
      • 2022-10-18
      相关资源
      最近更新 更多