Adding additional action to Jar task (for obfuscation, jarjar, etc.)

Hi!

I need to run jarjar on a result from a Jar task. Modified jar is then used in compilation of other projects in multi-project setup.

I’m new to Gradle, but none of the solutions I could find satisfied me. So I came up with this:

// In utils.gradle:
jar.ext.finalizeIntermediate = { finalizeAction ->
    jar {
        def oldActions = actions.collect()
        actions = []
        doLast {
            // Temporarily change properties to produce 'intermediate' file,
            // run Jar actions, restore properties
            def oldClassifier = jar.classifier
            jar.classifier = (oldClassifier ?: "") + "(INTERMEDIATE)"
            jar.ext.intermediateArchivePath = jar.archivePath
            oldActions.each { it.execute(jar) }
            jar.classifier = oldClassifier
              // This action is expected to take 'jar.intermediateArchivePath' and
            // produce 'jar.archivePath' (by obfuscating, applying jarjar, etc.)
            finalizeAction()
        }
    }
}
  // In project's gradle file:
jar.finalizeIntermediate {
    ant.copy(file: jar.intermediateArchivePath, tofile: jar.archivePath)
}

This seems to work, but I’m afraid there is a use case where it breaks and burns. Can Gradle gurus please review this approach and bless it?

Your implementation is less than ideal. Particularly, by explicitly executing task actions you effectively circumvent a lot of Gradle logic to accomplish things like incremental task support. Instead, what I would suggest is defining the task that creates your final jar, assign that artifact to a custom configuration, then have the other projects in your multi-project build, depend on that configuration.

configurations {

jarjar

}

artifacts {

jarjar jarjarTask

}

In your dependent projects:

dependencies {

compile project(path: ‘:jajarProject’, configuration: ‘jarjar’)

}

Thanks for your reply, Mark!

I tried creating a configuration, but didn’t like it because it exposes details about what happens inside a subproject. My next step in that direction was to have specific configuration ‘finalJar’ for each Java plugin. I guess I have to revisit that approach unless it’s safe to do this:

jar.ext.finalizeIntermediate = { finalizeAction ->
    jar {
        def oldClassifier
            doFirst {
            // Temporarily change properties to produce 'intermediate' file,
            // set 'jar.intermediateArchivePath'
            oldClassifier = jar.classifier
            jar.classifier = (oldClassifier ?: "") + "(INTERMEDIATE)"
            jar.ext.intermediateArchivePath = jar.archivePath
        }
            doLast {
            // Restore properties
            jar.classifier = oldClassifier
                // Run 'finalizeAction' which is expected to take 'jar.intermediateArchivePath'
            // and produce 'jar.archivePath' (by obfuscating, applying jarjar, etc.)
            finalizeAction()
        }
    }
}

I.e. instead of manually invoking Jar actions I do my thing before and after standard Jar tasks. Will that interfere with incremental feature?