Gradle - only execute a task if code in a directory has changed

Viewed 3230

I have a Gradle task that creates a 100MB JAR. Now I only want it to be created as part of my gradle build if code within the project has changed (say a specific ./src directory).

So at the moment the build.gradle.kts looks like:

tasks {
    "shadowJar"(ShadowJar::class) {
        isZip64 = true
        archiveFileName.set("${project.name}.jar")
        dependencies {
            include(dependency(".*:.*:.*"))
            exclude(dependency("org.apache.spark:.*"))
        }
    }
}

tasks {
    "build" {
        dependsOn("shadowJar")
    }
}

Any ideas on how I can achieve this?

Thanks

p.s. And as a background I'm doing to improve the build time. I've already found 2 things for my gradle.properties:

org.gradle.parallel=true
org.gradle.caching=true
1 Answers

In general if you want to tell a task how to know whether it's up-to-date or not, you need to define inputs and outputs. These are what tells Gradle if a task is up-to-date or not. If nothing has changed in the inputs or outputs since the task was last run, Gradle knows it's up-to-date and will not re-execute the task.

In your case the inputs would be the source folder, and the outputs would be the jar. This is explained in the Gradle docs here. You can see an example in this article, which shows how Gradle can call Webpack, but only if something has changed.

So you could do something like this:

tasks {
    "shadowJar"(ShadowJar::class) {
        // all the stuff you already have, plus these two new lines:
        inputs.dir("... the source dir ...")
        outputs.file("... the generated jar ...")
    }
}

However, I presume the shadowTask task you're using is from here: https://github.com/johnrengelman/shadow ? If so, you might not actually need to set the inputs and outputs directly as the task already sets them itself. For example if you look at the source code for that plugin you can see it annotates one method with @InputFiles (see here). This, according to the docs:

Marks a property as specifying the input files for a task.

The outputs are also specified in one of the superclasses (AbstractArchiveTask.getArchiveFile).

Related