Skip to content

Commit 010c01a

Browse files
committed
Move ksp task cache to a gradle build service
1 parent 403cac9 commit 010c01a

File tree

3 files changed

+47
-10
lines changed

3 files changed

+47
-10
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.devtools.ksp.gradle
18+
19+
import org.gradle.api.services.BuildService
20+
import org.gradle.api.services.BuildServiceParameters
21+
import java.net.URLClassLoader
22+
import java.util.concurrent.ConcurrentHashMap
23+
24+
abstract class KspAAService : BuildService<BuildServiceParameters.None>, AutoCloseable {
25+
val isolatedClassLoaderCache = ConcurrentHashMap<String, URLClassLoader>()
26+
27+
override fun close() = isolatedClassLoaderCache.clear()
28+
}

gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspAATask.kt

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import org.gradle.api.provider.MapProperty
3939
import org.gradle.api.provider.Property
4040
import org.gradle.api.provider.Provider
4141
import org.gradle.api.provider.SetProperty
42+
import org.gradle.api.services.ServiceReference
4243
import org.gradle.api.tasks.CacheableTask
4344
import org.gradle.api.tasks.Classpath
4445
import org.gradle.api.tasks.IgnoreEmptyDirectories
@@ -95,6 +96,9 @@ abstract class KspAATask @Inject constructor(
9596
@get:Nested
9697
abstract val commandLineArgumentProviders: ListProperty<CommandLineArgumentProvider>
9798

99+
@get:ServiceReference("KspAAService")
100+
abstract val kspAAService: Property<KspAAService>
101+
98102
@TaskAction
99103
fun execute(inputChanges: InputChanges) {
100104
// FIXME: Create a class loader with clean classpath instead of shadowing existing ones. It'll require either:
@@ -155,6 +159,7 @@ abstract class KspAATask @Inject constructor(
155159
it.removedSources = removedSources
156160
it.isInputChangeIncremental = inputChanges.isIncremental
157161
it.changedClasses = changedClasses
162+
it.kspAAService.set(kspAAService)
158163
}
159164
}
160165

@@ -167,6 +172,11 @@ abstract class KspAATask @Inject constructor(
167172
kspExtension: KspExtension,
168173
): TaskProvider<KspAATask> {
169174
val project = kotlinCompilation.target.project
175+
val kspAAServiceProvider = project.gradle.sharedServices.registerIfAbsent(
176+
"KspAAService",
177+
KspAAService::class.java
178+
) {}
179+
170180
val target = kotlinCompilation.target.name
171181
val sourceSetName = kotlinCompilation.defaultSourceSet.name
172182
val kspTaskName = kotlinCompileProvider.name.replaceFirst("compile", "ksp")
@@ -190,6 +200,7 @@ abstract class KspAATask @Inject constructor(
190200
kspAATask.onlyIf {
191201
!incomingProcessors.isEmpty
192202
}
203+
kspAATask.kspAAService.set(kspAAServiceProvider)
193204
kspAATask.kspClasspath.from(kspAADepCfg.incoming.artifactView { }.files)
194205
kspAATask.kspConfig.let { cfg ->
195206
cfg.processorClasspath.from(incomingProcessors)
@@ -539,25 +550,23 @@ interface KspAAWorkParameter : WorkParameters {
539550
var removedSources: List<File>
540551
var changedClasses: List<String>
541552
var isInputChangeIncremental: Boolean
553+
var kspAAService: Property<KspAAService>
542554
}
543555

544-
var isolatedClassLoaderCache = mutableMapOf<String, URLClassLoader>()
545556
val doNotGC = mutableSetOf<Any>()
546557

547558
abstract class KspAAWorkerAction : WorkAction<KspAAWorkParameter> {
548559
override fun execute() {
549560
val gradleCfg = parameters.config
550561
val kspClasspath = parameters.kspClasspath
562+
val isolatedClassLoaderCache = parameters.kspAAService.get().isolatedClassLoaderCache
551563
val key = kspClasspath.files.map { it.toURI().toURL() }.joinToString { it.path }
552-
synchronized(isolatedClassLoaderCache) {
553-
if (isolatedClassLoaderCache[key] == null) {
554-
isolatedClassLoaderCache[key] = URLClassLoader(
555-
kspClasspath.files.map { it.toURI().toURL() }.toTypedArray(),
556-
ClassLoader.getPlatformClassLoader()
557-
)
558-
}
564+
val isolatedClassLoader = isolatedClassLoaderCache.computeIfAbsent(key) {
565+
URLClassLoader(
566+
kspClasspath.files.map { it.toURI().toURL() }.toTypedArray(),
567+
ClassLoader.getPlatformClassLoader()
568+
)
559569
}
560-
val isolatedClassLoader = isolatedClassLoaderCache[key]!!
561570

562571
// Clean stale files for now.
563572
// TODO: support incremental processing.

gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool
195195
kotlinCompilation,
196196
kotlinCompileProvider,
197197
processorClasspath,
198-
kspExtension
198+
kspExtension,
199199
)
200200

201201
val generatedSources = arrayOf(

0 commit comments

Comments
 (0)