Conversation
215c6ef to
e91d89b
Compare
compiler-api/src/main/java/com/squareup/anvil/compiler/api/GeneratedFile.kt
Show resolved
Hide resolved
0e31737 to
a8662a7
Compare
dce7f22 to
f0a7e6d
Compare
f0a7e6d to
243b078
Compare
build-logic/conventions/src/main/kotlin/com/squareup/anvil/conventions/BasePlugin.kt
Show resolved
Hide resolved
compiler-api/src/main/java/com/squareup/anvil/compiler/api/AnvilContext.kt
Show resolved
Hide resolved
handstandsam
left a comment
There was a problem hiding this comment.
Reviewed on a call with @RBusarow
243b078 to
756ab5a
Compare
JoelWilcox
left a comment
There was a problem hiding this comment.
Partial review, still working my way through most of the tests
compiler-api/src/main/java/com/squareup/anvil/compiler/api/GeneratedFileWithSources.kt
Outdated
Show resolved
Hide resolved
...ls/src/testFixtures/java/com/squareup/anvil/compiler/internal/testing/SimpleCodeGenerator.kt
Outdated
Show resolved
Hide resolved
...ls/src/testFixtures/java/com/squareup/anvil/compiler/internal/testing/SimpleCodeGenerator.kt
Outdated
Show resolved
Hide resolved
...ls/src/testFixtures/java/com/squareup/anvil/compiler/internal/testing/SimpleCodeGenerator.kt
Outdated
Show resolved
Hide resolved
compiler/src/main/java/com/squareup/anvil/compiler/codegen/CodeGenerationExtension.kt
Outdated
Show resolved
Hide resolved
compiler/src/main/java/com/squareup/anvil/compiler/codegen/incremental/GeneratedFileCache.kt
Outdated
Show resolved
Hide resolved
compiler/src/main/java/com/squareup/anvil/compiler/codegen/incremental/GeneratedFileCache.kt
Show resolved
Hide resolved
compiler/src/test/java/com/squareup/anvil/compiler/codegen/CodeGenerationExtensionTest.kt
Show resolved
Hide resolved
gradle-plugin/src/gradleTest/java/com/squareup/anvil/plugin/LifecycleTest.kt
Show resolved
Hide resolved
| * - Generated code is cached in a way that Gradle understands, | ||
| * and will be restored from cache along with other build artifacts. | ||
| * | ||
| * By default this feature is enabled. |
There was a problem hiding this comment.
I'm thinking maybe we should default this to disabled first and have it be opt-in while we get feedback on it, verify no major issues pop up, and also do benchmarking for performance impact. Then we can switch it to enabled by default in a follow-up release
There was a problem hiding this comment.
That's my thought as well, except that while testing against a snapshot or otherwise-special build, it's more convenient to just have it enabled. So I was thinking leave it enabled by default up until release, then disable it by default, then enable it in a follow-up.
There was a problem hiding this comment.
That's my thought as well, except that while testing against a snapshot or otherwise-special build, it's more convenient to just have it enabled. So I was thinking leave it enabled by default up until release, then disable it by default, then enable it in a follow-up.
It would be easy to get released in the wrong state that way though, and just creates additional work along the way. Shouldn't enabling for the snapshot be really easy now by just setting it in your gradle.properties file?
There was a problem hiding this comment.
Adding on to the previous comment, I think changing to false now is also preferred so that we're testing a snapshot as close to release as possible which lets us verify the expected default behavior etc
756ab5a to
89df450
Compare
...ler/src/test/java/com/squareup/anvil/compiler/codegen/incremental/FileCacheOperationsTest.kt
Outdated
Show resolved
Hide resolved
gradle-plugin/src/gradleTest/java/com/squareup/anvil/plugin/IncrementalTest.kt
Outdated
Show resolved
Hide resolved
gradle-plugin/src/gradleTest/java/com/squareup/anvil/plugin/IncrementalTest.kt
Show resolved
Hide resolved
gradle-plugin/src/gradleTest/java/com/squareup/anvil/plugin/IncrementalTest.kt
Outdated
Show resolved
Hide resolved
gradle-plugin/src/gradleTest/java/com/squareup/anvil/plugin/IncrementalTest.kt
Outdated
Show resolved
Hide resolved
gradle-plugin/src/gradleTest/java/com/squareup/anvil/plugin/IncrementalTest.kt
Outdated
Show resolved
Hide resolved
89df450 to
22e4f97
Compare
…er generated context: #836 (comment)
…er generated context: #836 (comment)
e0c01fb to
29da0d0
Compare
gradle-plugin/src/gradleTest/java/com/squareup/anvil/plugin/LifecycleTest.kt
Outdated
Show resolved
Hide resolved
gradle-plugin/src/gradleTest/java/com/squareup/anvil/plugin/IncrementalTest.kt
Outdated
Show resolved
Hide resolved
compiler/src/main/java/com/squareup/anvil/compiler/codegen/incremental/GeneratedFileCache.kt
Outdated
Show resolved
Hide resolved
| is RelativeFile -> { | ||
| if (sourceFile == RelativeFile.ANY) return true | ||
| val currentMd5 = sourceFile.md5() | ||
| val previousMd5 = filesToMd5.put(sourceFile, currentMd5) |
There was a problem hiding this comment.
This should be using get() right? Right now it has a side effect of modifying the tracked MD5
There was a problem hiding this comment.
This is intentional, but it's tricky.
This function must always calculate the file's current md5 in order to do the comparison. As such, we might as well cache it. The filesToMd5.put(...) returns the previously-stored value or null, so we still get to do the same comparison -- and now we get the cache update for free.
There was a problem hiding this comment.
👍 that makes sense for optimizing. I don't remember if there's already a test for this, but if not it's probably worth adding one to make it explicit that this behavior is intentional. I would have assumed it was a bug and changed it to get if I was reading this sometime in the future since the method name hasChanged suggests it's only checking things
| * - Generated code is cached in a way that Gradle understands, | ||
| * and will be restored from cache along with other build artifacts. | ||
| * | ||
| * By default this feature is enabled. |
There was a problem hiding this comment.
Adding on to the previous comment, I think changing to false now is also preferred so that we're testing a snapshot as close to release as possible which lets us verify the expected default behavior etc
2ba5838 to
af5cf9c
Compare
af5cf9c to
d7ca03d
Compare
|
I'm not 100% sure if it's related to this pull request, but it's very likely. I've used the latest beta with |
We start off with new feature toggle:
trackSourceFiles.It's present in the Gradle DSL and as a Gradle property.
The majority of changes are behind that toggle, but not all.
Changes that ignore
trackSourceFilesGeneratedFileWithSourcesreplacesGeneratedFileIn order to support incremental compilation, we need to track what source files resulted in what generated files, then aggregate that data in
CodeGenerationExtension. The existingGeneratedFiletype is perfectly situated for this, but I wanted to make it explicit whether the code being generated is going to be incremental or not, so I extracted an interface from it and introduced a new type.If
trackSourceFilesis enabled but the consuming project is using a custom generator that returns the deprecatedGeneratedFile, the build will fail.It is possible to return a
GeneratedFileWithSourceswith an empty list of source files. Anvil will then treat the generated file as if it was generated from all source files in the source set, and it will be invalidated by any change.trackSourceFiles == truetrackSourceFiles == falseGeneratedFileGeneratedFileWithSourcesGeneratedFileWithSourceswith an empty sources list
build/anvil/src-gen-<variant>has movedWe now write a cache file as well, and need to put it somewhere. The new structure is pretty comparable to what KSP and KGP do.
Prior to these changes, the generated output's folder structure resembled this:
Now, the
src-gen-maindirectory is gone and we have this:New Incremental and Caching Behavior
Tracking Anvil output in Gradle
AnvilPluginwill add the generated source code and cache binary file asTaskOutputsof their correspondingcompileKotlintask:kotlinCompilation.compileTaskProvider.configure { task -> if (variant.variantFilter.trackSourceFiles) { task.outputs.dir(srcGenDir) task.outputs.dir(anvilCacheDir) } }This means that Gradle will handle cache/restore logic on its own when it's a fresh build, when it's from a (Gradle) build cache, or when the task is already up to date.
This is not enough to handle incremental builds, like when a single source file is changed or if a source file is deleted.
File hashing
The files that the Kotlin compiler gives us in
CodeGenerationExtension.onAnalysisCompletedaren't only the changed files. There is no built-in way for us to compare those inputs to the inputs of the last invocation ofonAnalysisCompleted.We now create an MD5 hash of every file that goes through
CodeGenerationExtension, whether it's generated or human-written. These hashes are stored inbuild/anvil/<variant name>/caches/generated-file-cache.bin, which is written to disk after every invocation ofonAnalysisCompleted.Tracking source <--> generated relationships
Thanks to GeneratedFileWithSources, we know exactly which source files resulted in which generated files. These relationships are also stored in
build/anvil/<variant name>/caches/generated-file-cache.bin.Deleting out-of-date outputs
A file is considered to be changed if it is in the input files and its current MD5 hash is different from its cached hash, or if the cache doesn't contain a hash for that file.
A file is considered to be deleted if it's present in the cache but not on disk, AND it is not tracked as a generated file in the cache.
For every changed or deleted file, we delete all downstream generated files recursively. For example, in the above diagram, if
Source_2.ktis changed, we deletegen2.kt,gen3.kt,gen5.kt, andgen6.kt.Restoring missing outputs
Because we include the generated files as
TaskOutputsof thecompileKotlintask, Gradle will delete those files any time it re-runs the task. This would break incremental builds, where we may only receive a subset of the source files, and therefore only re-generate a subset of the output.Before we generate any new code, we restore any missing generated files from the
generated-file-cache.bincache.TODO
trackSourceFiles