This message was deleted.
# configuration-cache
s
This message was deleted.
m
Also same question if the task input is a provider using the configuration instead of the configuration:
Copy code
provider {
  configuration.files.md5()
}
Can the CC be smart enough to not invalidate here?
v
For the first part if I got you right, CC should not be invalidated, as the configuration of the tasks does not change. The file contents should not be relevant as long as you do not read those file contents at configuration time. For the second part I did not understand at all what you mean. If you mean you are calculating an md5 sum over some files at configuration time (or in a provider that is set to a task property) then the CC will be invalidated. Even if the md5 would be the same with different file contents (unlikely but theoretically possible) CC would be invalidated as you read the file contents at configuration time, so the file contents are CC input, unless you do it inside a
ValueSource
. In that case only the result of the value source would make the CC invalid or not, but then is executed on every build even if CC is reused and if not reused even twice.
m
Yep, that was the question. I guess I wasn't clear on what "configuration time" is. But from your answer, the code that is inside a provider used as task input is executed during configuration time, right?
This seems to work
Copy code
input.set(configuration.elements.map { it.md5() })
provider { configuration... }
doesn't work at all because it breaks task dependency (which is not related to CC)
v
Exactly,
elements
is there to get a
Provider
that carries the task dependencies of the
FileCollection
. Actually I wonder that
input.set(configuration.elements.map { it.md5() })
is not invalidating the CC. I thought the providers are calculated at the time the CC entry is written and the result persisted.
m
I think this is the relevant code:
Copy code
public ExecutionTimeValue<? extends T> calculateExecutionTimeValue() {
        if (contentsAreBuiltByTask()) {
            return ExecutionTimeValue.changingValue(this);
        }
        return ExecutionTimeValue.fixedValue(get());
    }
so if the configuration is buildable by a task then
get()
isn't called and instead the transforming lambdas are serialized instead
So the providers are "resolved" sometimes before CC and sometimes after
v
Ah, of course. Makes sense that task execution results cannot be serialized to CC. hen-and-egg, you know. 😄
😄 1
With this for example CC is invalidated if you change
foo.txt
contents:
Copy code
abstract class Foo : DefaultTask() {
    @get:Input
    abstract val input: Property<String>

    @TaskAction
    fun foo() {
        println("input = ${input.get()}")
    }
}
val fooBucket by configurations.dependencyScope("fooBucket")
val fooElements = configurations.resolvable("fooElements") {
    extendsFrom(fooBucket)
}
dependencies {
    fooBucket(files("foo.txt"))
}
val foo by tasks.registering(Foo::class) {
    input = fooElements.flatMap { it.elements }.map { it.single().asFile.readText() }
}
m
Feels almost counterintuitive. CC works "better" if your build is more "complex"
What prevents
configuration
to be serialized as a "changing" value all the time (even when contents are not built by tasks)
v
And with this CC is reused as the task dependency is there:
Copy code
abstract class Foo : DefaultTask() {
    @get:Input
    abstract val input: Property<String>

    @TaskAction
    fun foo() {
        println("input = ${input.get()}")
    }
}
val fooBucket by configurations.dependencyScope("fooBucket")
val fooElements = configurations.resolvable("fooElements") {
    extendsFrom(fooBucket)
}
val bar by tasks.registering(Sync::class) {
    from(file("foo.txt"))
    into(layout.buildDirectory.dir("bar"))
}
dependencies {
    fooBucket(bar.map { it.outputs.files })
}
val foo by tasks.registering(Foo::class) {
    input = fooElements.flatMap { it.asFileTree.elements }.map { it.single().asFile.readText() }
}
👍 1
What prevents
configuration
to be serialized as a "changing" value all the time (even when contents are not built by tasks)
It would typically be slower. If you can calculate a value at configuration time and persist the result, you don't have to do the calculation when CC is reused as the result of the calculation is already present.
👍 1
Same with dependency resolution, the result of it is serialized to CC and it does not need to be done when CC is reused.
An alternative is, to not read the potentially changing file at configuration time, but just give the file itself as input to the task and calculate the value based on the contents at execution time of the task
m
Yep 👍