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

用Java定义Gradle插件属性扩展的正确方法?,java,gradle,Java,Gradle,我正在尝试用Java创建一个Gradle插件,它具有属性扩展(而不是约定,因为这显然是一种方式)。作为记录,我正在Linux机器上使用Gradle1.6(Ubuntu 12.04) 我已经弄清楚了,这应该在插件类定义中完成。下面是一种添加扩展的方法。创建包含属性的扩展类: public class MyPluginExtensions { File sourceDir; File outputDir; public MyPluginExtensions(Project

我正在尝试用Java创建一个Gradle插件,它具有属性扩展(而不是约定,因为这显然是一种方式)。作为记录,我正在Linux机器上使用Gradle1.6(Ubuntu 12.04)

我已经弄清楚了,这应该在插件类定义中完成。下面是一种添加扩展的方法。创建包含属性的扩展类:

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");
    }

}
 myPluginName.sourceDir = file('the/main/src')
现在将这些扩展添加到主插件类中的项目中:

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);
    }
}
但是,当我将这些内容放入使用我的插件的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.
那么,在基于Java的Gradle插件中为任务添加属性扩展的正确方法是什么

编辑:

基于其他一些SO帖子,我尝试在一个快照中添加我的extensions对象:

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

// second attempt
myPluginTask.getExtensions().add("myPluginTask", extensions);
这似乎有效。但是,Gradle现在抱怨我添加了一个动态属性:

Deprecated dynamic property: "sourceDir" on "task ':myPluginTask'", value: "/Users/jfer...".
那么,添加插件扩展属性的正确方法是什么

编辑2

因此,再次尝试一下,我将扩展添加到项目对象中,并使用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);
然而,这失败的原因有两个:

  • 创建与任务同名的属性扩展(“myPluginTask”)会在任务名称和扩展名称之间产生冲突,导致任务从gradle的透视图中消失(并抛出倾斜错误,例如“无此类属性:类的dependsOn…myPluginTask”)
  • 如果我提供的名称与任务名称不冲突(例如,“myPluginPropExt”),create()方法可以工作,但不会按预期在其自己的命名空间中添加扩展(例如,
    project.myPluginPropExt.propertyName
    ,而是将其添加到项目命名空间中(例如,
    project.propertyName
    )这是不正确的,并导致Gradle抛出一堆“不推荐使用的动态属性”警告

  • 代码正在向任务(而不是项目)添加一个扩展名,这很少有用。之后,它尝试设置
    myPluginTask.sourceDir=file('The/main/src')
    ,这是不可能的,因为扩展名刚刚以相同的名称注册。

    因此,我的问题有一个解决方案:

    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);
        }
    }
    
    最后一个技巧是在我的插件任务中获得这个值:

    public class MyPluginTask extends DefaultTask {
        @TaskAction
        public void action() {
            MyPluginExtensions extensions = (MyPluginExtensions) getProject()
                    .getExtensions().findByName("myPluginName");
    
            System.out.println("sourceDir value: " + extensions.sourceDir);
        }
    }
    
    这是可行的,但这个解决方案让我恼火的是,我希望能够将扩展属性与我在基于groovy的插件中看到的任务(例如,
    myPluginTask.sourceDir
    )放在相同的命名空间中,但这显然不受支持或根本不起作用


    同时,希望这对其他人有所帮助。

    当您的任务和扩展名同名时,您可以在构建中执行此操作。gradle

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

    感谢第一个关于不将扩展添加到任务中的建议。现在,通过向项目对象添加扩展,我已经做了一些工作。但是,您误解了第二个要点:
    myPluginTask.sourceDir=file(/main/src')
    是我的gradle构建脚本的一部分,我试图为特定构建设置扩展值。我理解,但扩展不是这样工作的。客户端构建脚本配置扩展的属性,而不是扩展本身。仍然不太清楚:代码段(
    myPluginTask.sourceDir=file(/main/src')
    )来自使用我的插件的客户端/消费者生成脚本,该脚本正在尝试为特定生成设置该值。插件未正确使用扩展。扩展是一个对象,其属性将由客户端生成脚本配置。因此,它需要具有自定义类型,而不是不可变类型,如
    字符串
     例如,您可以执行
    project.getExtensions().create(“foo”,MyPluginExtensions.class)
    。然后构建脚本可以设置
    foo.sourceDir
    foo.outputDir
    。重要的是要理解扩展在其目标下创建了一个新的命名空间(在我的示例中是
    project.foo
    )。它不能“融入”就像一个惯例。啊哈!我骗你回答了我原来的问题!:)我认为
    project.getExtensions().create()
    方法看起来是正确的方法,但我尝试这样做的尝试到目前为止都失败了(请参阅我问题的编辑2)。我将再次尝试,并根据需要更新我的Q和a。
    myPluginTask.sourceDir = file('the/main/src')
    project.tasks.myPluginTask.dependsOn clean