When exactly are lazy FileCollections that define a dependency evaluated?

If I have something like

dependencies {
    compile fileTree(dir: 'libs', include: '*.jar')
}

my understanding is that this just defines the dependency (during the configuration phase), but the “libs” directory is not actually searched for “*.jar” files until the dependency is needed. But when exactly is it “needed”? Can it be that this is before the execution phase, i.e. also during the configuration phase?

I’m asking because I’m putting JARs into “libs” in the execution phase, but before anything gets build. Still the FileCollection does not contains the JARs I was putting into “libs”.

Yes, whenever someone asks for the files of this configuration it’s going to be resolved.

Would need more detail to pinpoint the problem.

Well, as you’ve probably guesses from the “libs” directory name, this is an Android project. As it’s not me (i.e. code that I’ve written) that asks for the files of this config, I guess this is done by the internals of the Android plugin,. The question is: When exactly does that happen?

‘configurations.compile.incoming.beforeResolve { throw new Exception(“now resolving”) }’ will tell you.

I’ve put this at the root level of my build.gradle file, but I never see that exception being thrown.

If you don’t see the exception, it means that the configuration never gets resolved. You can easily verify by adding ‘task resolve << { configurations.compile.resolve() }’. Running ‘gradle resolve’ should now trigger the exception.

It’s really weird: I’ve confirmed that ‘gradle resolve’ throws the exception, but ‘gradle assembleDebug’ does not. But if I remove the compile dependency completely, ‘gradle assembleDebug’ fails as expected. To me this means the dependency gets resolved as the build fails without it, but still ‘beforeResolve’ does not seem to get called.

The only explanation that comes to my mind is that the ‘android’ plugin is pulling some tricks here. Perhaps try ‘configurations.all { config -> config.incoming.beforeResolve { println “resolving $config.name” } }’.

Interesting. Even for just running ‘gradle tasks’ this results in

resolving _debugCompile resolving _debugPublish resolving _releaseCompile resolving _releasePublish resolving _debugTestCompile resolving _debugTestPublish

And this list does not change when running e.g. ‘gradle assembleDebug’. So the configurations do in fact seem to get resolved already in the configuration phase. But what is that about the configuration names, is the Android plugin tampering with them by adding “_debug” or “_release” prefixes to “compile”?

You’ll have to ask the developers of the Android plugin for those details.