Is there a public API that allows a plugin to read...
# community-support
m
Is there a public API that allows a plugin to read and write entries in the build cache?
v
Not that I know of. I think you can only declare a task or transform as cachable for it to be put to and pulled from cache, but no manual caching.
🙏 1
v
I guess the work in worker api is cacheable as well, isn't it?
m
You're reading my mind @Vladimir Sitnikov, this all comes from https://github.com/gradle/gradle/issues/34082 🙂
I don't think workers are cacheable.
👆 1
t
They don't declare inputs and outputs, only "parameters"
👆 1
😞 1
v
For tasks that are using isolated workers, this feels like unnecessary invalidation. The workers have very constrained input/outputs and do not share the classpath with the rest of the build so they probably do not need to be recomputed when the build script classpath changes.
I don't think this is true. If the class path is not available in the worker, the work action would also not be available and thus could not be executed.
Sadly, it's also fragile because any change in the buildscript classpath ends up changing most (all of?) the cache keys.
Depends. For built-in tasks for example it should not invalidate the cache key, because their classpath did not change unless you changed the Gradle version or added custom task actions.
m
> If the class path is not available in the worker, the work action would also not be available and thus could not be executed. True 👍 I never really got that part of the worker API actually, feels like it's only halfway isolation. I guess where I'm going with this is that there "should" be a way to make this possible (do work that is completely isolated from the rest of the build). > For built-in tasks for example it should not invalidate the cache key, because their classpath did not change How is the classpath of a task computed? I have never really understood that part. Is Gradle able to look up the jar where a given task is defined (easy) and all its referenced jars (harder)?
v
I guess where I'm going with this is that there "should" be a way to make this possible (do work that is completely isolated from the rest of the build).
For that you would inject
ExecOperations
and use
javaExec
on it. There you completely control the classpath and the process is not reused. Even with process-isolation the worker processes are reused if possible so are not enough for use-cases where static state is involved and the problem
How is the classpath of a task computed? I have never really understood that part. Is Gradle able to look up the jar where a given task is defined (easy) and all its referenced jars (harder)?
I don't fully remember, quite some time I looked into that last. But I guess it takes the class of all actions and gets the classloader hierarchy of that. Thus if you have a built-in task only the Gradle stuff is in the classpath and thus the task should get the same cache-key
m
Mmm I see
So if you have KGP and AGP as an
implementation
in your
build-logic
included build, they will probably all belong to the same classloader.
So changing anything in your
build-logic
runtime classpath will invalidate all of KGP and AGP and 90% of your build (but not the built-in Gradle tasks)
v
Quite possible, yes.
t
IIRC, Gradle will analyze the class dependencies of the WorkAction to only "copy" those into the isolated classloader, and only if they're not in the given classpath already. If you code your WorkActions against a
compileOnly
dependency that will then be provided at runtime to the worker API, then the work action should only depend on your WorkParameter, and everything else will come from the runtime-configured classpath.
👍 1
v
Oh, interesting. I'll have to experiment a bit with that. 😄