Run grade tasks inside a task without dependsOn

2019-08-22 01:28发布

问题:

Assume that I have set of tasks executed from the cmd line and it works:

gradle processReleaseManifest compileReleaseSources run assembleRelease

Here run is the task which I Defined.

So My requirement is that I need to create a task which executes the above mentioned 4 tasks, like say new task abc, runs the above mentioned tasks in the same order,

I know I cannot use dependsOn in this case because,processReleaseManifest compileReleaseSource when used in the build gradle it shows,

Could not get unknown property 'assembleRelease' for project ':app' of type org.gradle.api.Project.

So what is the solution?

回答1:

You can, as @lu.koerfer's answer indicates use strings in the dependsOn list to refer to tasks that are defined further down in the build file.

In other words, this works:

task foo {}
task bar(dependsOn: [foo]) {}

and this also works:

task bar(dependsOn: ['foo']) {}
task foo {} 

Now as for getting the tasks to run in the order you want things are not quite as straight forward. The dependsOn property only tells the task which tasks need to run before the task itself runs. It does not tell gradle to run the tasks in the order defined in the dependsOn clause.

An example:

task one {}
task two {} 
task three {} 
task run(dependsOn: [one, two, three]) {}

results in the following output when run:

~> gradle run
:one UP-TO-DATE
:three UP-TO-DATE
:two UP-TO-DATE
:run UP-TO-DATE

BUILD SUCCESSFUL

...note the fact that we are not running in the order one, two, three, run.

In other words, the command line invocation forces the tasks to run in the order defined whereas the dependsOn is a set and has no ordering.

There are a few ways you can get the tasks to run in the order you want. One is to define dependencies on the tasks (this is probably the common path):

task one {}
task two(dependsOn: ['one']) {} 
task three(dependsOn: ['two']) {} 
task run(dependsOn: [one, two, three]) {}

which results in:

~> gradle run
:one UP-TO-DATE
:two UP-TO-DATE
:three UP-TO-DATE
:run UP-TO-DATE

BUILD SUCCESSFUL

another is to use the task ordering constructs added in later versions of gradle.

Also, if you need to add a task dependency to a task which was defined somewhere earlier in the file, you can do so via:

task foo {}
someTaskDefinedFurtherUp.dependsOn 'foo'

which adds the task foo to the dependencies of someTaskDefinedFurtherUp.



回答2:

You need to pass the task names as strings to the dependsOn method, because at the time you call it, the task objects haven't been created yet. However, if you pass strings, the task names will be evaluated later:

task abc {
    dependsOn 'processReleaseManifest', 'compileReleaseSources', 'run', 'assembleRelease'
}


回答3:

As it may be possible but very complicated to specify the task dependencies and ordering via dependsOn and mustRunAfter / shouldRunAfter, I'll propose another possible solution:

You can invoke Gradle from Gradle and specify the tasks in same way you would via command line:

task abc(type: GradleBuild) {
    tasks = ['processReleaseManifest', 'compileReleaseSources', 'run', 'assembleRelease']
}

This will call Gradle again from the current build and execute the tasks in the specified order.