[Gradle, JS] Add libraries filter caching in compile task

Previously any compile task was honestly reading dependency metadata from filesystem to check whether it's K/JS module even if another compile task already tested this dependency. Now the result of check is cached in build service that is cleared after build finish. It can save many rebuild time on incremental compilation of complex projects.
#KT-47154 Fixed
This commit is contained in:
Alexander Likhachev
2021-06-05 00:50:07 +03:00
parent dbb933e6a6
commit 9a4ff6e201
@@ -16,6 +16,8 @@ import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.gradle.api.services.BuildService
import org.gradle.api.services.BuildServiceParameters
import org.gradle.api.tasks.*
import org.gradle.api.tasks.compile.AbstractCompile
import org.gradle.api.tasks.compile.JavaCompile
@@ -57,6 +59,7 @@ import org.jetbrains.kotlin.incremental.ChangedFiles
import org.jetbrains.kotlin.library.impl.isKotlinLibrary
import org.jetbrains.kotlin.utils.JsLibraryUtils
import java.io.File
import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject
const val KOTLIN_BUILD_DIR_NAME = "kotlin"
@@ -616,6 +619,21 @@ abstract class Kotlin2JsCompile @Inject constructor(
}
}
).disallowChanges()
val libraryCacheService = task.project.rootProject.gradle.sharedServices.registerIfAbsent(
"${LibraryFilterCachingService::class.java.canonicalName}_${LibraryFilterCachingService::class.java.classLoader.hashCode()}",
LibraryFilterCachingService::class.java
) {}
task.libraryCache.set(libraryCacheService).also { task.libraryCache.disallowChanges() }
}
}
internal abstract class LibraryFilterCachingService : BuildService<BuildServiceParameters.None>, AutoCloseable {
private val cache = ConcurrentHashMap<File, Boolean>()
fun getOrCompute(key: File, compute: (File) -> Boolean) = cache.computeIfAbsent(key, compute)
override fun close() {
cache.clear()
}
}
@@ -711,8 +729,7 @@ abstract class Kotlin2JsCompile @Inject constructor(
// 1) purely pre-IR backend
// 2) purely IR backend
// 3) hybrid pre-IR and IR backend. Can only accept libraries with both JS and IR parts.
@get:Internal
protected val libraryFilter: (File) -> Boolean
private val libraryFilterBody: (File) -> Boolean
get() = if (kotlinOptions.isIrBackendEnabled()) {
if (kotlinOptions.isPreIrBackendDisabled()) {
::isKotlinLibrary
@@ -723,6 +740,15 @@ abstract class Kotlin2JsCompile @Inject constructor(
JsLibraryUtils::isKotlinJavascriptLibrary
}
@get:Internal
internal abstract val libraryCache: Property<LibraryFilterCachingService>
@get:Internal
protected val libraryFilter: (File) -> Boolean
get() = { file ->
libraryCache.get().getOrCompute(file, libraryFilterBody)
}
@get:Internal
internal val absolutePathProvider = project.projectDir.absolutePath