s5b
s5b

Reputation: 728

Creating a post build copy task with Gradle

I am struggling with the Gradle build lifecycle; specifically with the split between the configuration and execution phases. I have read a number of sections in the Gradle manual and have seen a number of ideas online, but have not found a solution to the following problem:

I want to run a specific task to produce an artifact at the end of my java-library-distribution build that is a flattened version of the runtime configuration jars. That is, I only want to produce the artifact when I run the specific task to create the artifact.

I have created the following task:

task packageSamplerTask(type: Tar, dependsOn: distTar) {
    description "Packages the build jars including dependencies as a flattened tar file. Artifact: ${distsDir}/${archivesBaseName}-${version}.tar"
    from tarTree("${distsDir}/${archivesBaseName}-${version}.tar").files
    classifier = 'dist'
    into "${distsDir}/${archivesBaseName}-dist-${version}.tar"
}

Although this task does produce the required artifact, the task runs during gradle's configuration phase. This behavior has the following consequences:

It appears that if I extend the Copy task in this manner I'm always going to get this kind of premature behavior.

Is there a way to use the << closure / doLast declarations to get what I want? Or is there something else I'm missing / should be doing?

Update

After further work I have clarified my requirements, and resolved my question as follows (specifically):

"I want to package my code and my code's dependencies as a flat archive of jars that can be deployed as a jMeter plugin. The package can then be installed by unpacking into the jMeter lib/ext directory, as is. The package, therefore, must not include the jMeter jars (and their dependencies) which are used for building and testing"

Because Gradle doesn't appear to support the Maven-like provided dependency management, I created a new configuration for my package which excludes the jMeter jars.

configurations {
    jmpackage {
        extendsFrom runtime
        exclude group: 'org.apache.jmeter', name: 'ApacheJMeter_core', version: '2.11'
        exclude group: 'org.apache.jmeter', name: 'ApacheJMeter_java', version: '2.11'
    }
}

And then created the following task (using the closure recommendation from Peter Niederwieser):

task packageSamplerTask(type: Tar, dependsOn: assemble) {
    from { libsDir }
    from { configurations.jmpackage.getAsFileTree() }
    classifier = 'dist'
}

This solution appears to work, and it allows me to use just theGradle java plugin, too.

Upvotes: 2

Views: 3519

Answers (2)

The End
The End

Reputation: 709

First your task isn't executed in the configuration phase but like EVERY task it is configured in that phase. And your closure is just a configuration of your task (a Configuration closure, not an Action closure). That is why your code is "executed" in the configuration phase".

If you want your code to be executed in the execution phase have to write it in a doLastclosure or doFirst. But in your case it is better to keep it in a configuration closure, because you are configuring your task.

To make sure your build doesn't fail because of the missing folder, you can create it with distsDir.mkdirs().

Upvotes: 0

Peter Niederwieser
Peter Niederwieser

Reputation: 123968

The task declaration is fine, but the flattening needs to be deferred too:

...
from { tarTree("${distsDir}/${archivesBaseName}-${version}.tar").files }

Also, the Tar file should be referred to in a more abstract way. For example:

from { tarTree(distTar.archivePath).files }  

Upvotes: 1

Related Questions