Skip to content

Commit 20345bb

Browse files
authored
Merge pull request #35 from rharter/rh/worker_service_registry
Introduces a service registry for the incrementalSignal service.
2 parents 4404bed + bc5ed08 commit 20345bb

3 files changed

Lines changed: 82 additions & 21 deletions

File tree

gradle-plugin/src/main/java/com/squareup/hephaestus/plugin/DisableIncrementalCompilationTask.kt

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@ package com.squareup.hephaestus.plugin
44

55
import org.gradle.api.DefaultTask
66
import org.gradle.api.file.ConfigurableFileCollection
7-
import org.gradle.api.provider.Property
87
import org.gradle.api.tasks.Classpath
98
import org.gradle.api.tasks.InputFiles
10-
import org.gradle.api.tasks.Internal
119
import org.gradle.api.tasks.Optional
1210
import org.gradle.api.tasks.OutputFile
1311
import org.gradle.api.tasks.TaskAction
@@ -25,14 +23,13 @@ abstract class DisableIncrementalCompilationTask : DefaultTask() {
2523
@get:OutputFile @get:Optional
2624
val someFile = File(project.buildDir, "not-existing-file-because-gradle-needs-an-output")
2725

28-
@get:Internal
29-
abstract val incrementalSignal: Property<IncrementalSignal>
30-
31-
private val projectPath = project.path
26+
private val serviceKey: IncrementalSignalServiceKey = IncrementalSignalServiceKey(project.path)
3227

3328
@TaskAction fun toggleFlag() {
3429
// Disable incremental compilation if something in the classpath changed. If nothing has changed
3530
// in the classpath, then this task wouldn't run at all and be skipped.
36-
incrementalSignal.get().incremental[projectPath] = false
31+
useIncrementalSignalService(serviceKey) {
32+
it.incremental = false
33+
}
3734
}
3835
}

gradle-plugin/src/main/java/com/squareup/hephaestus/plugin/HephaestusPlugin.kt

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import org.gradle.api.Plugin
1212
import org.gradle.api.Project
1313
import org.gradle.api.plugins.AppliedPlugin
1414
import org.gradle.api.plugins.PluginManager
15-
import org.gradle.api.provider.Provider
1615
import org.jetbrains.kotlin.gradle.internal.KaptGenerateStubsTask
1716
import org.jetbrains.kotlin.gradle.plugin.KaptExtension
1817
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper
@@ -115,26 +114,26 @@ open class HephaestusPlugin : Plugin<Project> {
115114
// compile task. If the plugin classpath changed, then DisableIncrementalCompilationTask sets
116115
// the signal to false.
117116
@Suppress("UnstableApiUsage")
118-
val incrementalSignal = project.gradle.sharedServices
119-
.registerIfAbsent("incrementalSignal", IncrementalSignal::class.java) { }
117+
val incrementalSignalServiceKey = registerIncrementalSignalBuildService(project)
120118

121119
if (isAndroidProject) {
122120
project.androidVariantsConfigure { variant ->
123121
val compileTaskName = "compile${variant.name.capitalize(US)}Kotlin"
124-
disableIncrementalCompilationAction(project, incrementalSignal, compileTaskName)
122+
disableIncrementalCompilationAction(project, incrementalSignalServiceKey, compileTaskName)
125123
}
126124
} else {
127125
// The Java plugin has two Kotlin tasks we care about: compileKotlin and compileTestKotlin.
128-
disableIncrementalCompilationAction(project, incrementalSignal, "compileKotlin")
129-
disableIncrementalCompilationAction(project, incrementalSignal, "compileTestKotlin")
126+
disableIncrementalCompilationAction(project, incrementalSignalServiceKey, "compileKotlin")
127+
disableIncrementalCompilationAction(project, incrementalSignalServiceKey, "compileTestKotlin")
130128
}
131129
}
132130

133131
fun disableIncrementalCompilationAction(
134132
project: Project,
135-
incrementalSignal: Provider<IncrementalSignal>,
133+
incrementalSignalServiceKey: IncrementalSignalServiceKey,
136134
compileTaskName: String
137135
) {
136+
138137
// Disable incremental compilation, if the compiler plugin dependency isn't up-to-date.
139138
// This will trigger a full compilation of a module using Hephaestus even though its
140139
// source files might not have changed. This workaround is necessary, otherwise
@@ -146,16 +145,12 @@ open class HephaestusPlugin : Plugin<Project> {
146145
task.pluginClasspath.from(
147146
project.configurations.getByName(PLUGIN_CLASSPATH_CONFIGURATION_NAME)
148147
)
149-
task.incrementalSignal.set(incrementalSignal)
150148
}
151149

152150
project.tasks.named(compileTaskName, KotlinCompile::class.java) { compileTask ->
153151
compileTask.dependsOn(disableIncrementalCompilationTaskProvider)
154152
}
155153

156-
// We avoid a reference to the project in the doFirst.
157-
val projectPath = project.path
158-
159154
// If we merge the block below and the block above, it looks like
160155
// the kotlin compiler is generating byte code for
161156
// disableIncrementalCompilationTaskProvider to be visible from the doFirst block
@@ -164,7 +159,7 @@ open class HephaestusPlugin : Plugin<Project> {
164159
compileTask.doFirst {
165160
// If the signal is set, then the plugin classpath changed. Apply the setting that
166161
// DisableIncrementalCompilationTask requested.
167-
val incremental = incrementalSignal.get().incremental[projectPath]
162+
val incremental = getIncrementalSignalService(incrementalSignalServiceKey).incremental
168163
if (incremental != null) {
169164
compileTask.incremental = incremental
170165
}
Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,78 @@
1+
@file:Suppress("UnstableApiUsage")
2+
13
package com.squareup.hephaestus.plugin
24

5+
import com.android.build.gradle.internal.workeractions.WorkerActionServiceRegistry
6+
import com.android.ide.common.process.ProcessException
7+
import com.google.common.io.Closer
8+
import org.gradle.api.Project
39
import org.gradle.api.services.BuildService
410
import org.gradle.api.services.BuildServiceParameters.None
11+
import java.io.IOException
12+
import java.util.UUID
13+
14+
/** Used to get unique build service name. Each class loader will initialize it's onw version. */
15+
private val HEPHAESTUS_INCREMENTAL_SIGNAL_BUILD_SERVICE_NAME =
16+
"hephaestus-incremental-signal-build-service" + UUID.randomUUID().toString()
17+
18+
/**
19+
* Registers incremental signal build service and returns a service key that can be used to access
20+
* the service later.
21+
*/
22+
fun registerIncrementalSignalBuildService(project: Project): IncrementalSignalServiceKey {
23+
val buildServiceProvider = project.gradle.sharedServices.registerIfAbsent(
24+
HEPHAESTUS_INCREMENTAL_SIGNAL_BUILD_SERVICE_NAME,
25+
IncrementalSignalBuildService::class.java
26+
) {}
27+
return buildServiceProvider.get().registerIncrementalSignalService(project.path)
28+
}
29+
30+
/**
31+
* Service registry used to store IncrementalSignal services so they are accessible from the worker
32+
* actions.
33+
*/
34+
var incrementalSignalServiceRegistry: WorkerActionServiceRegistry = WorkerActionServiceRegistry()
35+
36+
/** Intended for use from worker actions. */
37+
@Throws(ProcessException::class, IOException::class)
38+
fun useIncrementalSignalService(
39+
incrementalSignalServiceKey: IncrementalSignalServiceKey,
40+
serviceRegistry: WorkerActionServiceRegistry = incrementalSignalServiceRegistry,
41+
block: (IncrementalSignalService) -> Unit
42+
) = serviceRegistry.getService(incrementalSignalServiceKey).service.let(block)
43+
44+
fun getIncrementalSignalService(
45+
incrementalSignalServiceKey: IncrementalSignalServiceKey,
46+
serviceRegistry: WorkerActionServiceRegistry = incrementalSignalServiceRegistry
47+
): IncrementalSignalService = serviceRegistry.getService(incrementalSignalServiceKey).service
48+
49+
data class IncrementalSignalServiceKey(val projectPath: String)
50+
: WorkerActionServiceRegistry.ServiceKey<IncrementalSignalService> {
51+
override val type: Class<IncrementalSignalService> get() = IncrementalSignalService::class.java
52+
}
53+
54+
data class IncrementalSignalService(var incremental: Boolean? = null)
555

656
/** This signal is used to share state between the task above and Kotlin compile tasks. */
7-
abstract class IncrementalSignal : BuildService<None> {
8-
val incremental = mutableMapOf<String, Boolean?>()
57+
abstract class IncrementalSignalBuildService : BuildService<None>, AutoCloseable {
58+
private val registeredServices = mutableSetOf<IncrementalSignalServiceKey>()
59+
private val closer = Closer.create()
60+
61+
@Synchronized
62+
fun registerIncrementalSignalService(
63+
projectPath: String,
64+
serviceRegistry: WorkerActionServiceRegistry = incrementalSignalServiceRegistry
65+
): IncrementalSignalServiceKey {
66+
val key = IncrementalSignalServiceKey(projectPath)
67+
68+
if (registeredServices.add(key)) {
69+
closer.register(serviceRegistry.registerServiceAsCloseable(key, IncrementalSignalService()))
70+
}
71+
72+
return key
73+
}
74+
75+
override fun close() {
76+
closer.close()
77+
}
978
}

0 commit comments

Comments
 (0)