Behavior of Java plugin's clean task + dependency resolution at configuration time


(sethgoings) #1

I manage a few projects that create fat jars and have run into some subpar performance when I enhance the Java plugin’s jar task to:

jar {
  from configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) }
}

This modification requires a resolution of all runtime dependencies at configuration time (which can take a while on a slower network connection even with a short list of dependencies!). This behavior has led to lots of frustration when people just want to run basic tasks (clean, tasks, etc.)

So I have a few questions: 1. Could this be improved in later releases of Gradle? 2. Is there a way to subvert this behavior of resolving all runtime dependencies on projects during configuration time even when a basic (or unrelated) task is used? (clean, tasks, processResources, etc.) 3. Furthermore, would it be possible to improve the performance of the Java plugin’s clean task further so that it wouldn’t have to resolve buildscript dependencies as well? If I have defined a few buildscript dependencies that have transitive dependencies, the clean task can be slowed significantly by waiting for the buildscript resolution to happen.

Here’s a simple example project that exhibits these two behaviors:

buildscript {
  repositories {
    mavenCentral()
  }
    dependencies {
    classpath 'net.saliman:gradle-cobertura-plugin:1.1.0'
  }
}
  repositories {
  mavenCentral()
}
  apply plugin: 'java'
  dependencies {
  compile(
    ['com.google.inject:guice:3.0'],
    ['commons-io:commons-io:2.3'],
    ['org.apache.ws.commons.schema:XmlSchema:1.4.7'],
    ['org.apache.commons:commons-lang3:3.1'],
    ['commons-logging:commons-logging:1.1.1'],
    ['org.apache.neethi:neethi:2.0.5'],
    ['org.apache.poi:poi:3.7'],
    ['org.apache.poi:poi-scratchpad:3.0.1-FINAL'],
    ['javax.servlet:javax.servlet-api:3.0.1'],
    ['org.slf4j:slf4j-api:1.7.2'],
    ['org.slf4j:slf4j-jdk14:1.7.2'],
    ['org.codehaus.jettison:jettison:1.3.1'],
    ['javax.ws.rs:jsr311-api:1.1.1'],
    ['com.google.code.findbugs:jsr305:2.0.1'],
    ['com.google.code.findbugs:annotations:2.0.1'],
    ['org.apache.httpcomponents:httpclient:4.1'],
    ['com.google.inject.extensions:guice-assistedinject:3.0']
  )
}
  jar {
  from configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) }
}
  task wrapper(type: Wrapper) {
  gradleVersion = "1.5"
}

(Peter Niederwieser) #2

Resolving a configuration in the configuration phase should be avoided. ‘Jar.from’ accepts a closure, so you can just do ‘jar { from { … } }’.

There is no way around resolving the build script class path. I’m surprised that it’s slow. Is this a big multi-project build where each project declares the same build script dependencies?

PS: You can omit the brackets in the dependency declarations.


(sethgoings) #3

Thanks Peter! That tip on using from { … } instead of from(…) totally worked and makes sense. The buildscript problem is a part of a fairly large multiproject build.

The 3rd issue I mentioned is more of a nice to have - I think there will be a lot fewer complaints about Gradle resolving too much at the beginning of the build process once I propagate the change you suggested to fix the 2nd (and by proxy, 1st) issue I mentioned.

Thanks for your help!


(Peter Niederwieser) #4

I’ve seen significant speedups by declaring common build script dependencies in the root project only. They are (at least currently) inherited by child projects.