Nick Lee
Nick Lee

Reputation: 5959

How to append a Gradle Task without using `dependsOn`?

I am using Gradle to build a Java project involving native libraries. I have a task jniHeaders defined:

jniHeaders.dependsOn classes

so when I type gradle jniHeaders, it will compile the Java classes and generate JNI headers. So far so good.

But I feel that typing gradle jniHeaders is not very natural. And 99% of the time, if you compile Java classes successfully, you'd want to generate JNI headers as well. It would be nice if I could gradle classes to compile Java classes and generate JNI headers in one step.

In other words, I want to add the task jniHeaders to the end of the task classes, but only if classes is completed sucessfully and actually did some work.

classes.doLast comes to mind, but I am unable to tell it to execute another task. classes.finalizedBy jniHeaders works to an extent, but generates JNI headers regardless of the outcome of classes. I suppose I could add some Groovy logic to get the exact behavior I want, but I also suspect there must be an easier way.

Anyone has any suggestions?

Upvotes: 1

Views: 927

Answers (2)

Steinar
Steinar

Reputation: 5950

There are two parts to your question:

  1. Add the task jniHeaders to execute after successfully compiling java classes.
  2. Only perform jniHeaders task if any work was done.

Since classes task is an assembly of processResources and compileJava (see java plugin doc), I think it's better to hook into the compileJava task. As you've found yourself, this can be done with finalizedBy. In addition, you need to skip the task if no work was done, e.g. by adding an onlyIf statement to your jniHeaders task.

Example:

task jniHeaders {
    onlyIf { !sourceSets.main.allJava.empty }
    doLast {
        println "GENERATE JNI HEADERS for $project.name"
    }
}
compileJava.finalizedBy jniHeaders

Upvotes: 1

Raffaele
Raffaele

Reputation: 20885

The whole point of modelling a build as a graph of tasks is that there's a simple and robust execution model. I suggest you create a function compileJNIHeaders() and put it somewhere Gradle can access it (the build.gradle itself as well as buildSrc/src/main/groovy), so you can easily develop and test it.

This function can be executed in the most appropriate step:

  • classes.doFirst (if the headers are for your own code)
  • classes.doLast (if the headers are for dependent projects)
  • put in a task compileJNIHeaders that is a dependency of the task that you use to package your project in its deployment format

Upvotes: 1

Related Questions