2017-02-04 121 views
7

我想有以下工作gradle这个脚本语言任意foo如何在gradle插件中添加新的语言源目录?

sourceSets { 
    main { 
     java { 
      srcDir "${project.buildDir}/generated-sources/gen-java" 
     } 
     foo { 
      srcDir "${project.buildDir}/generated-sources/gen-foo" 
     } 
    } 
    test { 
     java { 
      srcDir "${project.buildDir}/generated-sources/gen-test-java" 
     } 
     foo { 
      srcDir "${project.buildDir}/generated-sources/gen-test-foo" 
     } 
    } 
} 

我也想有标准foo源目录在src/main/foosrc/test/foo

如何编写gradle插件来实现此功能?有没有可能做到这一点?

我有一个类似于解决方案的解决方法,可以满足我在下面发布的需求,但仍想了解添加新语言源目录的正确方法。

回答

2

为了实现这样的功能,应该扩展现有源集(或至少maintest源集)。它看起来像maintest来源集are defined in JavaPlugin。通过Convention对象可以扩展。

public class FooPlugin implements Plugin<ProjectInternal> { 
    @Override 
    public void apply(ProjectInternal project) { 
     project.getPluginManager().apply(JavaPlugin.class); 
     FooExtension ext = project.getExtensions().create(
      "foo", 
      FooExtension.class, 
      project, 
      project.getFileResolver() 
     ); 
     SourceSetContainer cont = (SourceSetContainer) project.getProperties().get("sourceSets"); 
     cont.all((SourceSet ss) -> { 
      String name = ss.getName(); 
      File sources = project.file("src/" + name + "/foo"); 
      FooSourceSet fss = ext.getSourceSetsContainer().maybeCreate(name); 
      SourceDirectorySet sds = fss.getFoo(); 
      sds.srcDir(sources); 
      Convention sourceSetConvention = (Convention) InvokerHelper.getProperty(ss, "convention"); 
      sourceSetConvention.getPlugins().put("foo", fss); 
     }); 
     project.task("compileFoo"); 
    } 
} 

public class FooExtension { 

    private final NamedDomainObjectContainer<FooSourceSet> sourceSetsContainer; 

    public FooExtension(Project project, FileResolver fileResolver) { 
     sourceSetsContainer = project.container(
      FooSourceSet.class, 
      new FooSourceSetFactory(fileResolver) 
     ); 
    } 

    public NamedDomainObjectContainer<FooSourceSet> getSourceSetsContainer() { 
     return sourceSetsContainer; 
    } 

    public void srcDir(String file) { 
     sourceSetsContainer.getByName("main").getFoo().srcDir(file); 
    } 
} 

public class FooSourceSetFactory implements NamedDomainObjectFactory<FooSourceSet> { 

    private final FileResolver fileResolver; 

    public FooSourceSetFactory(FileResolver fileResolver) { 
     this.fileResolver = fileResolver; 
    } 

    @Override 
    public FooSourceSet create(String name) { 
     return new DefaultFooSourceSet(name, fileResolver); 
    } 
} 

public interface FooSourceSet { 
    public String getName(); 
    public SourceDirectorySet getFoo(); 
    public FooSourceSet foo(Closure clsr); 
} 

public class DefaultFooSourceSet implements FooSourceSet { 

    final String name; 
    final SourceDirectorySet foo; 

    public DefaultFooSourceSet(String displayName, FileResolver fileResolver) { 
     this.name = displayName; 
     DefaultDirectoryFileTreeFactory ddftf = new DefaultDirectoryFileTreeFactory(); 
     foo = new DefaultSourceDirectorySet(name, fileResolver, ddftf); 
    } 

    @Override 
    public String getName() { 
     return name; 
    } 

    @Override 
    public SourceDirectorySet getFoo() { 
     return foo; 
    } 

    @Override 
    public FooSourceSet foo(Closure clsr) { 
     ConfigureUtil.configure(clsr, foo); 
     return this; 
    } 
} 

public class CompileFooTask extends DefaultTask { 

    @TaskAction 
    public void compileFoo() { 
     SourceSetContainer cont = (SourceSetContainer) getProject().getProperties().get("sourceSets"); 
     cont.all((SourceSet ss) -> { 
      FooSourceSet fss = getProject() 
       .getExtensions() 
       .getByType(FooExtension.class) 
       .getSourceSetsContainer() 
       .maybeCreate(ss.getName()); 
      System.out.println("directories under " + ss.getName() 
       + ": " + fss.getFoo().getSrcDirs()); 
     }); 
    } 
} 

任务compileFoo表明该插件实际工作。鉴于构建脚本片段从问题它打印这样的线:

directories under main: [<root>/src/main/foo, <root>/build/generated-sources/gen-foo] 
directories under test: [<root>/src/test/foo, <root>/build/generated-sources/gen-test-foo] 
+0

使用@ sm4更新代码[answer](http://stackoverflow.com/a/42335494/2933541) –

3

为您的使用情况下,源代码将是相当长的,但这里有几个三分球,希望能得到你要的。

看看Scala Plugin。它完全符合你的需求(因为它看起来像遵循Java约定的源代码),还有更多。如果您正在尝试编写任何插件,我建议查看整个gradle源代码。

你想看到确切的地方是:

  1. ScalaBasePlugin#configureSourceSetDefaults - 这是最高级别的配置情况
  2. DefaultScalaSourceSet - 实际的源集合类

在你的情况,你的可能只是想将所有scala字符串重命名为foo并删除所有不需要的配置(例如实际编译)。

插件示出如何添加默认源目录和方法:

public ScalaSourceSet scala(Closure configureClosure) { 
    configure(configureClosure, getScala()); 
    return this; 
} 

需要添加的生成源的护理。基本上它只需要默认的源目录工厂并使用它。您可以使用注入来添加所有默认的Gradle工厂(请参阅Scala插件,仅使用javax.inject.Inject作品)。

您还可以检查groovy插件。请注意,例如DefaultGroovySourceSet看起来像scala插件中的一个。

相关问题