Require help with making tasks configuration cacheable

Hi,

I have a small task that i am using in gradle script which does nothing but just prints me the build file name and the project name for a gradle project or sub project

For gradle projects, where configuration cache is enabled, it fails with error
line 115: invocation of ‘Task.project’ at execution time is unsupported.
See Configuration cache


tasks.register('getBuildFileNames') {

doLast{
            println "Getting Build File: ${project.getBuildFile()}->${project.getDisplayName()}"
        }
}

I wanted to make the task gradle cache safe, and following the docs here Configuration cache

i changed it to the below , which works

tasks.register('getBuildFileNames') {
        def buildFile = project.getBuildFile()
        def name = project.getDisplayName()
        doLast {
                            println "Getting Build File: ${buildFile}->${name}"
        }

}

Question : i am sure i am missing something very basic, but how are these two different? i am still accessing the project object, why does the second codebase work with configuration cache but the first one does not?

The difference is when you access it.

In the first version you access it at execution time, which is forbidden.
When the task state is deserialized from configuration cache, there is no valid Project instance to query as this cannot be serialized.

In the second version you access it at configuration time and have it in local variables, the values of which are then serialized to the configuration cache and restored from there.

That makes a lot of sense, but one follow up question. Is it possible that the results may differ? say the task is reporting whether a plugin is applied( which may be applied via conventions) or task is reporting the dependencies present for the sub project for say runtimeElements configuration, can the results differ based on if they are executed during configuration phase vs execution phase?

Probably depends on whether you do it properly or not. :smiley:
If you check pluginManager.hasPlugin or plugins.hasPlugin results can probably differ.
If you use pluginManager.withPlugin and then set a boolean flag to true, results should be consistent.

1 Like

Nice… i learned something new today.

how about

project.configurations.getByName("compileClasspath").incoming.getResolutionResult().getAllDependencies()

will results for the above alter based on whether it runs at configuration phase or execution phase?

so far all the projects that i have tested them, some common oss ones like micrometer, jmeter, hibernate, etc the result dont really differ. But i am still feeling iffy about it.

I don’t think it can differ.
If you call that line and after that try to declare an additional dependency on implementation for example, the build fails with “Cannot change dependencies of dependency configuration ‘:implementation’ after it has been included in dependency resolution.”.
So the result should not be able to change any further.

1 Like

thank you @Vampire , this was helpful

1 Like