feat(pkl-gradle): Implement gradle configuration cache support#1500
Open
ffluk3 wants to merge 1 commit intoapple:mainfrom
Open
feat(pkl-gradle): Implement gradle configuration cache support#1500ffluk3 wants to merge 1 commit intoapple:mainfrom
ffluk3 wants to merge 1 commit intoapple:mainfrom
Conversation
Modern versions of Gradle support configuration caching to prevent the gradual increase of project size to affect the overall developer experience of Gradle builds. To prepare the PKL project, and specificall pkl-gradle, for configuration support, we introduce an integration test to vet configuration cache rules, and then perform the necessary updates to provide configuration cache support. Fixes apple#1425
HT154
reviewed
Apr 7, 2026
|
|
||
| private final Map<List<Object>, Pair<List<File>, List<URI>>> parsedSourceModulesCache = | ||
| new HashMap<>(); | ||
| @org.gradle.api.tasks.PathSensitive(org.gradle.api.tasks.PathSensitivity.RELATIVE) |
Contributor
There was a problem hiding this comment.
We tend to prefer importing the types here instead of the fq name at the usage site.
Suggested change
| @org.gradle.api.tasks.PathSensitive(org.gradle.api.tasks.PathSensitivity.RELATIVE) | |
| @PathSensitive(PathSensitivity.RELATIVE) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1425
Gradle's configuration cache is one of the more impactful performance features in modern Gradle. It serializes the task graph after the first configuration phase so subsequent builds can skip it entirely. For large projects this can mean the difference between a multi-second configuration overhead and near-instant task scheduling.
The root cause preventing
pkl-gradlefrom adopting the configuration cache was a handful of patterns the configuration cache explicitly prohibits: holding a reference to theProjectobject in a plugin field, accessinggetProject()inside task action code at execution time, and caching CLI option objects that close over non-serializable state. These patterns work fine in a standard Gradle build, but they prevent Gradle from safely serializing the task graph to disk.What changed
PKL Plugin rework
The most visible structural change in
PklPluginis the removal of the@LateInit private Project projectfield. Rather than storing the project on the plugin instance, it's now passed as a parameter through the configure call chain. This is a mechanical but pervasive refactor, since everyconfigure*method gains aprojectargument and passes via property drilling.Per-task changes
BasePklTaskcapturesproject.getLayout().getProjectDirectory()at configuration time into agetWorkingDir()DirectoryProperty, rather than callinggetProject().getProjectDir()at execution time.CliBaseOptionsis now constructed fresh each time it's needed inside a task action, which is a trade-off between the (potentially negligible) cost of construction, and caching it, which would require holding a cross-boundary reference that defeats the configuration cache.EvalTask's lazily-cachedProvider<CliEvaluator>is similarly replaced with a factory method, andJavaCodeGenTaskandKotlinCodeGenTaskleverage the output dir.ModulesTask,getTransitiveModules()changes from aListProperty<File>to aConfigurableFileCollection(enabling.from()wiring rather than.set()), and gains a@PathSensitive(RELATIVE)annotation so the task doesn't unnecessarily re-run when files are moved between machines but their content and relative paths are unchanged. TheparsedSourceModulesCachemap is also removed — it was there to avoid redundant parsing but is incompatible with the cache since it holds mutable state across invocations.Cleanup
The logic for parsing transitive file imports out of the
AnalyzeImportsJSON output was previously duplicated in three places acrossAnalyzeImportsTaskandPklPlugin, with inconsistent error handling. This is consolidated into a singlepublic static parseTransitiveFiles(RegularFile)method onAnalyzeImportsTask, which throws with a descriptive message if parsing fails rather than silently returning an empty list and leaving dependent tasks with incomplete inputs. The two dead API methods that had accumulated onAnalyzeImportsTaskare removed.Tests
Each task type gets a new
is configuration cache compatibletest that runs the task twice with--configuration-cacheand asserts that the first run stores a cache entry and the second reuses it. The test infrastructure for this lives in a newrunTaskWithConfigurationCachehelper onAbstractTest. NOTE: these tests run slightly slower than the rest of the suite because they need the forked Gradle process to execute twice to prove out configuraion cache usage.