简体   繁体   English

使用Java定义Gradle插件属性扩展的正确方法?

[英]Correct way to define a Gradle plugin property extension with Java?

I'm trying to create a Gradle plugin in Java that has property extensions (not conventions, as this is apparently the old , wrong way). 我正在尝试在Java中创建一个具有属性扩展的Gradle插件(不是约定,因为这显然是旧的错误的方式)。 For the record, I'm working with Gradle 1.6 on a Linux machine (Ubuntu 12.04). 为了记录,我在Linux机器上使用Gradle 1.6(Ubuntu 12.04)。

I've gotten as far as figuring out that the this should be done in the Plugin class definition. 我已经知道这应该在Plugin类定义中完成。 Here is A way of adding an extension. 这是添加扩展的一种方法。 Create an extension class that contains your properties: 创建一个包含您的属性的扩展类:

public class MyPluginExtensions {

    File sourceDir;
    File outputDir;

    public MyPluginExtensions(Project project) {
        this.project = project;
        sourceDir = new File(project.getProjectDir(), "src");
        outputDir = new File(project.getBuildDir(), "out");
    }

}

Now add these extensions to the project in the main plugin class: 现在将这些扩展添加到主插件类中的项目:

public class MyPlugin implements Plugin<Project> {

    @Override
    public void apply(Project project) {

        Map<String,Object> taskInfo = new HashMap<String,Object>();
        taskInfo.put("type", MyPluginTask.class);
        taskInfo.put("description", "Generates blah from blah.");
        taskInfo.put("group", "Blah");
        Task myPluginTask = project.task(taskInfo, "myPluginTask");

        // Define conventions and attach them to tasks
        MyPluginExtensions extensions = new MyPluginExtensions(project);
        myPluginTask.getExtensions().add(
                "sourceDir", 
                extensions.sourceDir);
        myPluginTask.getExtensions().add(
                "outputDir", 
                extensions.outputDir);
    }
}

This approach, however, doesn't seem to be correct. 然而,这种方法似乎不正确。 A new project property is shows up in the project.ext namespace. project.ext命名空间中会显示一个新的项目属性。 I expect to be able to address the plugin extensions as: 我希望能够将插件扩展名解决为:

in my build.gradle:
myPluginTask.sourceDir = file('the/main/src')
myPluginTask.outputDir = file('the/output')

However, when I put such things in a gradle script that uses my plugin and try to set this property, gradle tells me I can't set it: 但是,当我将这些东西放在使用我的插件并尝试设置此属性的gradle脚本中时,gradle告诉我我无法设置它:

* What went wrong:
A problem occurred evaluating script.
> There's an extension registered with name 'sourceDir'. You should not reassign it via a property setter.

So, what's the right way to add property extensions for a task in a Java-based Gradle plugin? 那么,在基于Java的Gradle插件中为任务添加属性扩展的正确方法是什么?

EDIT: 编辑:

Based on some other SO posts, I tried just adding my extensions object in one shot: 基于其他一些SO帖子,我尝试只在一个镜头中添加我的扩展对象:

// first attempt:
//myPluginTask.getExtensions().add("sourceDir", extensions.sourceDir);
//myPluginTask.getExtensions().add("outputDir",extensions.outputDir);

// second attempt
myPluginTask.getExtensions().add("myPluginTask", extensions);

This appears to work. 这似乎有效。 However, Gradle is now complaining that I've added a dynamic property: 但是,Gradle现在抱怨我添加了一个动态属性:

Deprecated dynamic property: "sourceDir" on "task ':myPluginTask'", value: "/Users/jfer...".

So, again, what's the right way to add a plugin extension property? 那么,再次,添加插件扩展属性的正确方法是什么?

EDIT 2 编辑2

So, taking yet another shot at this, I'm adding the extension to the project object and using the create method instead: 因此,再次尝试这一点,我将扩展添加到项目对象并使用create方法:

// first attempt:
//myPluginTask.getExtensions().add("sourceDir", extensions.sourceDir);
//myPluginTask.getExtensions().add("outputDir",extensions.outputDir);

// second attempt
// myPluginTask.getExtensions().add("myPluginTask", extensions);

// third attempt
project.getExtensions().create("myPluginTask", MyPluginExtensions.class, project);

However, this fails for a couple of reasons: 但是,由于以下几个原因,这会失败:

  1. Creating a properties extension with the same name ("myPluginTask") as the task creates a collision between the task name and extension name, causing the task to disappear from gradle's perspective (and throw oblique errors, such as "No such property: dependsOn for class ...MyPluginExtensions"). 创建具有相同名称的属性扩展(“myPluginTask”)作为任务会在任务名称和扩展名之间创建冲突,导致任务从gradle的角度消失(并抛出倾斜错误,例如“No such property:dependsOn for class ... MyPluginExtensions“)。
  2. If I provide a name that does not collide with a task name (eg, "myPluginPropExt"), the create() method works, but DOES NOT add the extension in its own namespace as expected (eg, project.myPluginPropExt.propertyName and instead adds it in the project namespace (eg, project.propertyName ) which is not correct and causes Gradle to throw a bunch of "deprecated dynamic property" warnings. 如果我提供的名称不与任务名称冲突(例如,“myPluginPropExt”),则create()方法可以正常工作,但不要按预期在自己的命名空间中添加扩展名(例如, project.myPluginPropExt.propertyName ,而不是将它添加到项目命名空间(例如, project.propertyName )中,这是不正确的,并导致Gradle抛出一堆“已弃用的动态属性”警告。

So here is a solution to my problem: 所以这是我的问题解决方案:

public class MyPlugin implements Plugin<Project> {

    @Override
    public void apply(Project project) {

        Map<String,Object> taskInfo = new HashMap<String,Object>();
        taskInfo.put("type", MyPluginTask.class);
        taskInfo.put("description", "Generates blah from blah.");
        taskInfo.put("group", "Blah");
        Task myPluginTask = project.task(taskInfo, "myPluginTask");

        // Define conventions and attach them to tasks
        MyPluginExtensions extensions = new MyPluginExtensions(project);

        // the magic extension code:
        project.getExtensions().add("myPluginName", extensions);
    }
}

Now I can set a value for one of the extension properties in my gradle.build file like so (and I don't get a warning about adding deprecated dynamic properties): 现在我可以像我这样在gradle.build文件中为其中一个扩展属性设置一个值(并且我没有收到有关添加已弃用的动态属性的警告):

 myPluginName.sourceDir = file('the/main/src')

The final trick is to get this value in my Plugin's task: 最后一招是在我的插件任务中获取此值:

public class MyPluginTask extends DefaultTask {
    @TaskAction
    public void action() {
        MyPluginExtensions extensions = (MyPluginExtensions) getProject()
                .getExtensions().findByName("myPluginName");

        System.out.println("sourceDir value: " + extensions.sourceDir);
    }
}

This works, but what annoys me about this solution is that I want to be able to put the extension properties in the same namespace as the task (eg, myPluginTask.sourceDir ) which I have seen in groovy-based plugins, but this apparently is not supported or just doesn't work. 这是有效的,但令我烦恼的是这个解决方案是我希望能够将扩展属性放在与我在基于groovy的插件中看到的任务(例如, myPluginTask.sourceDir )相同的命名空间中,但这显然是不支持或只是不工作。

In the meantime, hope this helps someone else. 在此期间,希望这有助于其他人。

The code is adding an extension to a task (rather than a project), which is rarely useful. 代码是为任务(而不是项目)添加扩展,这很少有用。 After that, it tries to set myPluginTask.sourceDir = file('the/main/src') , which isn't possible because the extension was just registered under that same name. 之后,它尝试设置myPluginTask.sourceDir = file('the/main/src') ,这是不可能的,因为扩展名刚刚以相同的名称注册。

When your task and your extension have the same name, you can do this in your build.gradle : 当您的任务和扩展名具有相同名称时,您可以在build.gradle中执行此操作

myPluginTask.sourceDir = file('the/main/src')
project.tasks.myPluginTask.dependsOn clean

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM