How do I optimize the jar task when input is from a zipTree?

We have a few places in our build where we have something like this:

jar {

from (zipTree(file(‘some.jar’))) {

exclude ‘foo/**’

exclude ‘other/thing/Log*.class’

} }

On repeated builds, the jar task expands some.jar each time to determine whether the task is up-to-date. I can of course improve upon this by introducing a new task that unzips some.jar into a temp directory and then having the jar task depend on that task and have from set to the temp dir. This solves the issue nicely, however, it is a bit verbose, and I either have to repeat the pattern each time I want to use it or introduce a new bit of code or plugin/task that all occurrences can share.

My first thought was that if jar allowed you to explicitly set inputs.file to some.jar, that it could have the smarts to do this optimization itself, but that is not the case.

(I’ve seen other related postings on the forum that suggests this is a pattern that others use as well, that is specifying a zipTree(some.jar) in the from closure of the jar task.)

Any suggestions?



I use a helper task to determine if there are changes to the input zip file. And then execute the zipTree-using task, iff the helper task was executed. It looks like this:

ext {

bootstrapIncludePatterns = ["/bootstrap/*", "/localcache/*", “META-INF/**/”]

bootstrapOutputJarName = “${}.bootstrap-${project.version}.jar”

bootstrapOutputJar = new File(project.jarsArtifactsDir, bootstrapOutputJarName)

bootstrapIncludeFlat = fileTree(dir: project.ivyRetrieveFolderPath, includes: [‘*’])

bootstrapIncludeSources = fileTree(dir: “src/main/groovy”, includes: bootstrapIncludePatterns)

bootstrapIncludeClasses = fileTree(dir: sourceSets.main.output.classesDir, includes: bootstrapIncludePatterns)


task makeBootstrapJarQuickDeps() {




outputs.upToDateWhen { bootstrapOutputJar.exists() }

doLast {




task makeBootstrapJar(type: Jar, dependsOn: [classes, makeBootstrapJarQuickDeps]) {

onlyIf { dependsOnTaskDidWork() }

destinationDir = project.jarsArtifactsDir

archiveName = bootstrapOutputJarName

into("") {

from { bootstrapIncludeClasses }

from { bootstrapIncludeFlat.collect { zipTree(it) }}


manifest {

attributes(“Implementation-Version”: project.version)



Thanks. I’ve done something similar.

This seems like a fairly common thing to have to do. It would be good if gradle could perform this bit of optimization out of the box.