sourceSets.main.compileClasspath vs configurations.compile

Hi. What is the difference between: sourceSets.main.compileClasspath and configurations.compile (the same for all other pairs, as sourceSets always have corresponding configurations)? I did a simple test in my projects, and both of these print the same:

println "sourceSets.main.compileClasspath"
sourceSets.main.compileClasspath.each { println it }
println()
  println "configurations.compile"
configurations.compile.resolve().each { println it }
println()

These as well:

println "sourceSets.main.runtimeClasspath"
sourceSets.main.compileClasspath.each { println it }
println()
  println "configurations.runtime"
configurations.runtime.resolve().each { println it }
println()

I have seen build.gradle files that use configurations to define the classpath, yet others use sourceSets. What is the ‘right’ / better way? What is really the difference here?

wujek

A configuration is not necessarily a classpath, though it might be. A configuration is just a named group of dependencies, where the source set’s classpath is exactly that.

As to which is correct to use, it depends on what you are doing. If you want to iterate the classpath, always use the appropriate classpath property of the source set. If you want to iterate the configuration (which may be used as a component of one or more source set classpath properties) use it.

Does that clear it up?

1 Like

Thanks, it is a bit clearer now. So one can say, that a sourceSet’s classpath is 0 or more configurations (which can be used for something else as well) plus other stuff, like output of other sourceSets?

Some more questions, if you don’t mind.

  1. When I create a source set xyz, its compileClasspath is by default configurations.xyzCompile, its runtimeClasspath is by default configurations.xyzRuntime, right?

  2. Gradle has a /gradle/integTest.gradle, where integRuntime is configured like this:

sourceSets {
    integTest {
        compileClasspath = sourceSets.main.output + sourceSets.test.output + configurations.integTestCompile
        runtimeClasspath = output + compileClasspath + configurations.integTestRuntime
    }
}

But it could be as well:

sourceSets {
    integTest {
        compileClasspath = sourceSets.main.output + sourceSets.test.output + compileClasspath
        runtimeClasspath = output + compileClasspath + runtimeClasspath
    }
}

right? As the compile/runtimeClasspaths are by default configured (if I am not mistaken) as mentioned above in #1, and then reused to define the new compile/runtimeClasspath. This is actually how I did that in my project, but I might be wrong, or it might work by accident. Can you please comment on that?

  1. Does the integTest sourceSet, which depends on sourceSets.main.output, implicitly mean that integTestCompile dependsOn compile? It seems to be the case (in my projec), but I would like to exclude the possibility I am relying on something unspecified / accidental (like alphabetic sorting or sth).

wujek

So one can say, that a sourceSet’s classpath is 0 or more configurations (which can be used for something else as well) plus other stuff, like output of other sourceSets

Exactly.

When I create a source set xyz, its compileClasspath is by default configurations.xyzCompile, its runtimeClasspath is by default configurations.xyzRuntime, right?

Right.

Gradle has a /gradle/integTest.gradle, where integRuntime is configured like this:

I think it could actually be:

sourceSets {
    integTest {
        compileClasspath += sourceSets.main.output + sourceSets.test.output
    }
}

(which is effectively the same thing)

So the redefinition that the compileClasspath includes the runtimeClasspath is redundant, you can just use the above syntax.

Does the integTest sourceSet, which depends on sourceSets.main.output, implicitly mean that integTestCompile dependsOn compile? It seems to be the case (in my projec), but I would like to exclude the possibility I am relying on something unspecified / accidental (like alphabetic sorting or sth).

It does mean that. The ‘FileCollection’ returned by ‘sourceSets.«name».output’ is ‘Buildable’. This means that it can carry information about what tasks need to be run to make the files available. Gradle uses this to infer the task dependencies.

This feature is very explicit and you can rely on it.

Correction, it should be:

sourceSets {
    integTest {
        compileClasspath += main.output + test.output
        runtimeClasspath += main.output + test.output
    }
}

The ‘runtimeClasspath’ does not implicitly include the ‘compileClasspath’.

The difference would be the ordering of the things on the classpath. This could be important if, for some reason, you want to override a class from main for tests. If tests are first on the classpath, the JVM would use the overridden class in tests. I have no idea whether anybody uses it that way, though.

Thanks for your answers, they are very helpful.

The difference would be the ordering of the things on the classpath.

Very true.