Avoiding configuration cache misses working with files in settings.gradle.kts

Hello

So in the help we have this little example.

rootDir.listFiles().filter { it.isDirectory && (new File(it, "build.gradle.kts").exists()) }.forEach {
    include(it.name)
}

I used something similar and noticed frequent configuration cache misses. I thought: ok that kind of make sense: for example if a new directory “build” pops up or gets deleted because of a clean, gradles cache mechanism has no way to detect that this directory is actually not relevant for the configuration.
So I rewrote it to something like this:

val provider = providers.provider {
    fileTree(".") {
        include("Foundation/*/build.gradle.kts")
        include("Utilities/*/build.gradle.kts")
 

    }
        .map { it.parent }
        .map { it.removePrefix(rootDir.path) }
        .map { it.replace("\\", ":") }
        .sorted()
}
provider.get().forEach{
    include(it)
}

However I realized that unfortunatly this trick doesnt help. Each time a directoy gets added or removed, gradle prints

Calculating task graph as configuration cache cannot be reused because an input to settings file 'settings.gradle.kts' has changed.

Even though its and empty directory and the provider value doesnt change. I am not sure on why that is or where the

an input to settings file

part even comes from.

Is there a good way to dynamicly include files? I am currently using find -name build.gradle.kts > file.list and then parse that file because thats more stable, but that awkward…

Best regards

Even if you would not request the Provider’s value at configuration time (which you do) but would configure it as input for some task, it would still be all files configuration cache input, because you still list all files to determine the provider value and the provider value is calculated at the time the configuration cache is written.

You probably need to create a value source and use that.
Because value-sources only invalidate the CC when their output changes.
But value-sources are always evaluated even if CC is reused and if CC is not reused it even is calculated twice.

1 Like

Yep Seems good.
Here is the complete snippet to play around with or if someone wants to update the docs…

abstract class MyProjects: ValueSource<List<String>,MyProjects.Parameters> {
    override fun obtain(): List<String> {
        return parameters.root.get().listFiles()!!
            .filter { it.resolve("build.gradle.kts").isFile }
            .map { it.name }
            .sorted()
    }

    interface Parameters : ValueSourceParameters {
        val root: Property<File>
    }
}

providers.of(MyProjects::class) {
    parameters.root = rootDir
}.get().forEach {
    include(it)
}

If you’d like the docs updated, you need to open a PR or improvement ticket on GitHub. :slight_smile: