Depending on Java tasks to build tarball(s)

Based on the docs this seems like a straightforward use case, but I’m doing something wrong and unable to determine what is wrong. I’ve seen this in a few version of gradle so I’m pretty certain it’s my configuration:

subprojects {
      apply plugin: 'java'
    apply plugin: 'maven'
      ext.deployHome = relativePath("$buildDir/deploy")
      /** Distribution related tasks */
    task distCopyLibs(type: Copy, dependsOn: assemble) {
          into "$deployHome/lib"
        from configurations.runtime
        from jar.archivePath
        println "Within the child copyLibs"
    }
      task tarDist(dependsOn: distCopyLibs, type: Tar) {
        description = 'Creates the distribution gzip file'
        from deployHome
        compression = Compression.GZIP
        println "Within the child tarDist"
    }
}

When I run the tarDist task I see the following:

gradle-test/child1$ gradle tarDist
Within the child copyLibs
Within the child tarDist
The specified tar file TAR '/home/cschmidt/dev/projects/gradle-test/child1/build/distributions/child1.tgz' does not exist and will be silently ignored. This behaviour has been deprecated and will cause an error in the next version of Gradle.
[]
:child1:compileJava
:child1:processResources UP-TO-DATE
:child1:classes
:child1:jar
:child1:assemble
:child1:distCopyLibs
:child1:tarDist
  BUILD SUCCESSFUL
  Total time: 4.341 secs

It seems like the java assembly task is not being done until after the tar distribution task has completed. Is there a different form that I should be using to bind my custom tasks to the standard tasks provided by the Java plugin? Once I’ve run the task once, the custom tasks work properly:

Within the child copyLibs
Within the child tarDist
[/home/cschmidt/dev/projects/gradle-test/build/tmp/expandedArchives/child1.tgz_4i3n5ul0nh57sslnbg0ip5l7e2/lib/child1.jar]
:child1:compileJava UP-TO-DATE
:child1:processResources UP-TO-DATE
:child1:classes UP-TO-DATE
:child1:jar UP-TO-DATE
:child1:assemble UP-TO-DATE
:child1:distCopyLibs UP-TO-DATE
:child1:tarDist UP-TO-DATE
  BUILD SUCCESSFUL
  Total time: 3.402 secs

It seems like this may be related to multiple projects. The full build.gradle is:

subprojects {
      apply plugin: 'java'
    apply plugin: 'maven'
      ext.deployHome = relativePath("$buildDir/deploy")
      /** Distribution related tasks */
    task distCopyLibs(type: Copy, dependsOn: assemble) {
          into "$deployHome/lib"
        from configurations.runtime
        from jar.archivePath
        println "Within the child copyLibs"
    }
      task tarDist(dependsOn: distCopyLibs, type: Tar) {
        description = 'Creates the distribution gzip file'
        from deployHome
        compression = Compression.GZIP
        println "Within the child tarDist"
    }
  }
  ext.distributionDir = "$buildDir/distribution"
ext.distributionPath = "$distributionDir/workers"
task copySubmodules() {
    file(distributionDir).mkdirs()
    subprojects.each { child ->
        child.tasks.tarDist.each { tarTask ->
            copy {
                from tarTree(tarTask.archivePath)
                into distributionPath
            }
            println tarTree(tarTask.archivePath).getFiles()
        }
    }
}
  task distributionTar(dependsOn: copySubmodules, type:
Tar) {
    from distributionDir
    baseName "distribution"
    destinationDir file("build")
    compression = Compression.GZIP
}
  gradle.projectsEvaluated {
  copySubmodules.dependsOn(subprojects.tarDist)
}

If I just run ‘tarDist’ within the child project, I get the problem where gradle seems to skip building the jar unless I run the task multiple times.

What’s the actual problematic behaviour here? Is it the following output?…

The specified tar file TAR '/home/cschmidt/dev/projects/gradle-test/child1/build/distributions/child1.tgz' does not exist and will be silently ignored. This behaviour has been deprecated and will cause an error in the next version of Gradle.
[]

If so, that’s not really a problem. That’s happening because the following line…

println tarTree(tarTask.archivePath).getFiles()

Is being executed during configuration, before any tasks are executed, so therefore the tar will not exist yet.

If that’s not the problem, please explain what behaviour you’re expecting in contrast to what you are seeing.

The problem was that I having to run the distribution tasks twice in order to get the final tarball to be created. I read more on the different phases yesterday and have a better understanding of what is happening now. The following code within copySubmodules had the problem:

subprojects.each { child ->
        child.tasks.tarDist.each { tarTask ->
            copy {
                from tarTree(tarTask.archivePath)
                into distributionPath
            }
    }

The part ‘from tarTree(tarTask.archivePath)’ was getting run during the configuration phase. Since the original tarball does not exist when running in a clean workspace, there is nothing to copy, so during the execution phase nothing happens. The net result is that the final tarball fails to be created until the task is run a second time. I changed the task to the following:

task copySubmodules << {
 ...
}

So that it only runs in the execution phase and it seems to work properly. Is there a more ‘gradle-ish’ way to handle something like this?

You should be using a copy task instead of the copy method.

task copySubmodules(type: Copy) {
    into distributionPath
    subprojects.each { child ->
        child.tasks.tarDist.each { tarTask ->
          from { tarTree(tarTask.archivePath) }
        }
    }
}

Also note, anywhere where you are passing a file like arg, you can wrap in a closure to defer evaluation until the latest point possible.