How to extend the behavior of a Gradle task for a new task type?

倾然丶 夕夏残阳落幕 提交于 2020-05-14 17:20:12

问题


I would like to set a few things for a few test tasks. More specifically, I would like to add a few environment variables and a few system properties, maybe a few other things such as "dependencies" or "workingDir". With the regular Test task I can do this,

task test1(type:Test, dependsOn:[testPrep,testPrep1]){
     workingDir testWorkingPath
     systemProperty 'property','abs'
     environment.find { it.key ==~ /(?i)PATH/ }.value += (System.properties['path.separator'] + myLibPath)
     environment.LD_LIBRARY_PATH = "/usr/lib64:/lib64:${myLibPath}:" + environment.LD_LIBRARY_PATH
 }

task test2(type:Test, dependsOn:[testPrep]){
     workingDir testWorkingPath
     systemProperty 'property','abs'
     environment.find { it.key ==~ /(?i)PATH/ }.value += (System.properties['path.separator'] + myLibPath)
     environment.LD_LIBRARY_PATH = "/usr/lib64:/lib64:${myLibPath}:" + environment.LD_LIBRARY_PATH
     systemPropety 'newProperty','fdsjfkd'
 }

It would be nice to have a new task type MyTestType extending the regular Test task type, where the common definition is defined.

task test1(type:MyTestType){
     dependsOn testPrep1
 }

task test2(type:MyTestType){
     systemPropety 'newProperty','fdsjfkd'
 } 

What would be best way to do this? It seems that the execute() method is final and cannot be extended. I will need to do something like the doFirst to set those properties. Should I add all the extra values in the constructor? Is there any other hook I can use? Thanks.


回答1:


In general you can extend the 'Test' task and implement your customizations

task test1(type:MyTestType){
}

task test2(type:MyTestType){
     systemProperty 'newProperty','fdsjfkd'
}

class MyTestType extends Test {
    public MyTestType(){
        systemProperty 'property','abs'
    }
}

Alternatively you can configure all tasks of type Test with less boilerplate:

// will apply to all tasks of type test. 
// regardless the task was created before this snippet or after
tasks.withType(Test) {
   systemProperty 'newProperty','fdsjfkd'   
}



回答2:


you can do it the following ways

task TestExt{ Test { systemPropety 'newProperty','fdsjfkd' } }

note: this just adds to the configure method of Test source: https://docs.gradle.org/current/dsl/org.gradle.api.Task.html#N18D18




回答3:


It is also possible to specify the behavior of a particular superclass setting. Say for example you want to centralize the environment.find block, but allow setting myLibPath per task like this:

task test1(type: MyTestType) {
}
task test2(type: MyTestType) {
  libPath = '/foo/bar'
}

You could do that by overriding the configure method:

class MyTestType {
  @Input def String libPath

  @Override
  public Task configure(Closure configureClosure) {
    return super.configure(configureClosure >> {
      environment.find { it.key ==~ /(?i)PATH/ }.value += (System.properties['path.separator'] + (libPath ?: myLibPath))
    })
  }
}

Here we use the closure composition operator >> to combine the passed-in closure with our overridden behavior. The user-specified configureClosure will be run first, possibly setting the libPath property, and then we run the environment.find block after that. This can also be combined with soft defaults in the constructor, as in Rene Groeschke's answer

Note that this particular use case might break if you configure the task more than one, since the environment.find statement transforms existing state instead of replacing it.



来源:https://stackoverflow.com/questions/29948381/how-to-extend-the-behavior-of-a-gradle-task-for-a-new-task-type

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!