`-Xbuild-file` argument allows the compiler to run without
passing any Kotlin source file in arguments.
We have been using this property in
Kotlin Gradle plugin for a few important cases:
1. incremental compilation (to update caches when there are only removed files);
2. for KAPT (Kotlin sources don't make sense in context
of running APs).
We want to stop using `-Xbuild-file` in Kotlin Gradle plugin,
and avoid breaking the Gradle plugin or IC in other build-systems.
This change adds an argument to explicitly run
the compiler without specifying any Kotlin source file.
Add support for incremental annotation processors in KAPT. These
processors conform to https://docs.gradle.org/current/userguide/java_plugin.html#sec:incremental_annotation_processing
specification.
Support is provided by using javac compiler APIs and
recording the source file structure. At runtime, processors
are instrumented with custom Filer that is used to keep track of generated
files. In order to support classpath changes, stub generation task is
used to generated a list of changed FQCNs, and this is simply used by KAPT.
Both worker and non-worker mode are supported.
#KT-23880
#KT-27868 Fixed
Previously given dirtyFiles was removed from complementaryFilesMap
exactly on call of clearComplementaryFilesMapping. This causes fail
of next build in case of compilation error of previous build on JPS
(since complementary files not known on second build). The right way
to do it is removing (replacing) them only after successful
build.
This was working on Gradle since Gradle rebuilds whole module (project)
in case of build error.
Problem: previously, format-version.txt file was deleted while cleaning
target output on rebuild. Since directory was deleted, cache
attributesDiff stored in memory was not updated. This causes that on
saveExpectedStateIfNeeded does nothing.
The right way to fix it is move cache version format diff into
AbstractIncrementalCache, and override `clean()` method. But this is
hard to do for lookup storage, since used compilers set (jvm/js) will
known only after context init. This can be done by moving `expected`
attributes out of manager, but this is huge change for small benefit.
So, the optimal way for now is to write version for each build, even if
it is not changed.
#KT-27044 Fixed
CacheVersion class refactoring:
Responsibilities of class CacheVersion are splitted into:
- interface CacheAttributesManager<Attrs>, that should:
- load actual cache attribute values from FS
- provide expected attribute values (that is required for current build)
- checks when the existed cache (with actual attributes) values is suitable for current build (expected atribute values)
- write new values to FS for next build
- CacheAttributesDiff is created by calling CacheAttributesManager.loadDiff extension method. This is just pair of actual and expected cache attributes values, with reference to manager. Result of loadDiff can be saved.
CacheAttributesDiff are designed to be used as facade of attributes operations: CacheAttributesDiff.status are calculated based on actual and expected attribute values. Based on that status system may perform required actions (i.e. rebuild something, clearing caches, etc...).
Methods of CacheAttributesManager other then loadDiff should be used only through CacheAttributesDiff.
Build system should work in this order:
- get implementation of CacheAttributesManager for particular compiler and cache
- call loadDiff __once__ and save it result
- perform actions based on `diff.status`
- save new cache attribute values by calling `diff.saveExpectedIfNeeded()`
There are 2 implementation of CacheAttributesManager:
- CacheVersionManager that simple checks cache version number.
- CompositeLookupsCacheAttributesManager - manager for global lookups cache that may contain lookups for several compilers (jvm, js).
Gradle:
Usages of CacheVersion in gradle are kept as is. For compatibility this methods are added: CacheAttributesManager.saveIfNeeded, CacheAttributesManager.clean. This methods should not be used in new code.
JPS:
All JPS logic that was responsible for cache version checking completely rewritten.
To write proper implementation for version checking, this things also changed:
- KotlinCompileContext introduced. This context lives between first calling build of kotlin target until build finish. As of now all kotlin targets are loaded on KotlinCompileContext initialization. This is required to collect kotlin target types used in this build (jvm/js). Also all build-wide logic are moved from KotlinBuilder to KotlinCompileContext. Chunk dependency calculation also moved to build start which improves performance for big projects #KT-26113
- Kotlin bindings to JPS build targets also stored in KotlinCompileContext, and binding is fixed. Previously it is stored in local Context and reacreated for each chunk, now they stored in KotlinCompileContext which is binded by GlobalContextKey with this exception: source roots are calculated for each round, since temporary source roots with groovy stubs are created at build time and visible only in local compile context.
- KotlinChunk introduced. All chunk-wide logic are moved from KotlinModuleBuildTarget (i.e compiler, language, cache version checking and dependent cache loading)
- Fix legacy MPP common dependent modules
Cache version checking logic now works as following:
- At first chunk building all targets are loaded and used platforms are collected. Lookups cache manger is created based on this set. Actual cache attributes are loaded from FS. Based on CacheAttributesDiff.status this actions are performed: if cache is invalid all kotlin will be rebuilt. If cache is not required anymore it will be cleaned.
- Before build of each chunk local chunk cache attributes will be checked. If cache is invalid, chunk will be rebuilt. If cache is not required anymore it will be cleaned.
#KT-26113 Fixed
#KT-26072 Fixed
- support common modules metadata compilation under flag (it is not required since all common source roots are included transitively for now)
- introduce expect actual tracker in jps: move implementation from gradle to build-common
- support js incremental compilation: move implementation from gradle to build-common
Android Gradle plugin will start publishing clases in directories.
This commit adds support to find build history files when changed
files come from directories. It is similar to existing implementation
for jars i.e. it looks for .kotlin_module file under META-INF.
Test: ModulesApiHistoryAndroidTest