Skip to content

Commit ef4601f

Browse files
authored
Merge pull request #181 from gradle/gh/roomMergeIssue
Fix issues with room schema merge
2 parents 76d6ec4 + 7708f12 commit ef4601f

File tree

4 files changed

+177
-46
lines changed

4 files changed

+177
-46
lines changed

Diff for: .github/workflows/ci-check.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ jobs:
7676
- name: Setup NDK
7777
run: sudo $ANDROID_HOME/tools/bin/sdkmanager 'ndk;20.0.5594570'
7878

79-
# Patch issue in platform-tools 31.0.3 where platform-tools/api/api-versions.xml is missing
79+
# Patch issue in platform-tools 31.0.3 where platform-tools/api/api-versions.xml is missing (see https://issuetracker.google.com/issues/195445762)
8080
- name: Patch api-versions
8181
run: sudo test -f $ANDROID_HOME/platform-tools/api/api-versions.xml || (sudo mkdir $ANDROID_HOME/platform-tools/api && sudo cp .github/api-versions.xml $ANDROID_HOME/platform-tools/api/api-versions.xml)
8282

Diff for: src/main/groovy/org/gradle/android/workarounds/RoomSchemaLocationWorkaround.groovy

+50-29
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package org.gradle.android.workarounds
22

3-
43
import org.gradle.android.AndroidIssue
54
import org.gradle.api.DefaultTask
65
import org.gradle.api.Project
76
import org.gradle.api.Task
7+
import org.gradle.api.execution.TaskExecutionGraph
88
import org.gradle.api.file.ConfigurableFileCollection
99
import org.gradle.api.file.Directory
1010
import org.gradle.api.file.DirectoryProperty
@@ -13,6 +13,7 @@ import org.gradle.api.internal.file.FileOperations
1313
import org.gradle.api.model.ObjectFactory
1414
import org.gradle.api.provider.Provider
1515
import org.gradle.api.tasks.Internal
16+
import org.gradle.api.tasks.Optional
1617
import org.gradle.api.tasks.OutputDirectory
1718
import org.gradle.api.tasks.TaskAction
1819
import org.gradle.api.tasks.TaskProvider
@@ -22,6 +23,7 @@ import org.gradle.util.VersionNumber
2223

2324
import javax.inject.Inject
2425
import java.lang.reflect.Field
26+
import java.util.function.Supplier
2527

2628
/**
2729
* Changes annotation processor arguments to set the room.schemaLocation via a CommandLineArgsProcessor
@@ -72,13 +74,18 @@ class RoomSchemaLocationWorkaround implements Workaround {
7274
// Grab fileOperations so we can do copy/sync operations
7375
def fileOperations = project.fileOperations
7476

77+
// An undefined directory property for use when providers are disabled
78+
def nullDirectory = project.objects.directoryProperty()
79+
7580
// Create a task that will be used to merge the task-specific schema locations to the directory (or directories)
7681
// originally specified. This allows us to fan out the generated output and keep good cacheability for the
7782
// compile/kapt tasks but still join everything later in the location the user expects.
7883
TaskProvider<RoomSchemaLocationMergeTask> mergeTask = project.tasks.register("mergeRoomSchemaLocations", RoomSchemaLocationMergeTask) {
7984
roomSchemaMergeLocations = roomExtension.roomSchemaMergeLocations
8085
}
8186

87+
boolean javaCompileSchemaGenerationEnabled = true
88+
8289
def configureVariant = { variant ->
8390
// Make sure that the annotation processor argument has not been explicitly configured in the Android
8491
// configuration (i.e. we only want this configured through the room extension
@@ -98,15 +105,21 @@ class RoomSchemaLocationWorkaround implements Workaround {
98105

99106
// Add a command line argument provider to the task-specific list of providers
100107
task.options.compilerArgumentProviders.add(
101-
new JavaCompilerRoomSchemaLocationArgumentProvider(roomExtension.schemaLocationDir, taskSpecificSchemaDir)
108+
new JavaCompilerRoomSchemaLocationArgumentProvider(roomExtension.schemaLocationDir, taskSpecificSchemaDir, nullDirectory, { javaCompileSchemaGenerationEnabled } as Supplier)
102109
)
103110

104111
// Register the generated schemas to be merged back to the original specified schema directory
105-
roomExtension.registerOutputDirectory(taskSpecificSchemaDir)
112+
task.project.gradle.taskGraph.whenReady { TaskExecutionGraph graph ->
113+
if (graph.hasTask(task)) {
114+
roomExtension.registerOutputDirectory(taskSpecificSchemaDir)
115+
}
116+
}
106117

107118
// Seed the task-specific generated schema dir with the existing schemas
108119
task.doFirst {
109-
copyExistingSchemasToTaskSpecificTmpDir(fileOperations, roomExtension.schemaLocationDir, taskSpecificSchemaDir)
120+
if (javaCompileSchemaGenerationEnabled) {
121+
copyExistingSchemasToTaskSpecificTmpDir(fileOperations, roomExtension.schemaLocationDir, taskSpecificSchemaDir)
122+
}
110123
}
111124

112125
task.finalizedBy { roomExtension.schemaLocationDir.isPresent() ? mergeTask : null }
@@ -122,10 +135,7 @@ class RoomSchemaLocationWorkaround implements Workaround {
122135
applyToAllAndroidVariants(project) { variant ->
123136
def variantSpecificSchemaDir = project.objects.directoryProperty()
124137
variantSpecificSchemaDir.set(getVariantSpecificSchemaDir(project, "kapt${variant.name.capitalize()}Kotlin"))
125-
variant.javaCompileOptions.annotationProcessorOptions.compilerArgumentProviders.add(new KaptRoomSchemaLocationArgumentProvider(roomExtension.schemaLocationDir, variantSpecificSchemaDir))
126-
127-
// Register the variant-specific directory with the merge task
128-
roomExtension.registerOutputDirectory(variantSpecificSchemaDir)
138+
variant.javaCompileOptions.annotationProcessorOptions.compilerArgumentProviders.add(new KaptRoomSchemaLocationArgumentProvider(roomExtension.schemaLocationDir, variantSpecificSchemaDir, nullDirectory))
129139
}
130140

131141
// Kapt tasks will remove the contents of any output directories, which will interfere with any additional
@@ -148,27 +158,24 @@ class RoomSchemaLocationWorkaround implements Workaround {
148158
}
149159

150160
task.finalizedBy onlyIfAnnotationProcessorConfiguredForKapt(annotationProcessorOptionProviders) { roomExtension.schemaLocationDir.isPresent() ? mergeTask : null }
161+
162+
TaskExecutionGraph taskGraph = task.project.gradle.taskGraph
163+
taskGraph.whenReady onlyIfAnnotationProcessorConfiguredForKapt(annotationProcessorOptionProviders) { KaptRoomSchemaLocationArgumentProvider provider ->
164+
if (taskGraph.hasTask(task)) {
165+
// Register the variant-specific directory with the merge task
166+
roomExtension.registerOutputDirectory(provider.schemaLocationDir)
167+
}
168+
}
151169
}
152170

153171
project.tasks.withType(kaptWithoutKotlincTaskClass).configureEach(configureKaptTask)
154172
project.tasks.withType(kaptWithKotlincTaskClass).configureEach(configureKaptTask)
155173

156-
// Since we've added a new kapt-specific provider to the variant, go through the
157-
// JavaCompile tasks and remove this provider from its task-specific list so that
158-
// it only has its JavaCompile-specific provider. This is not great, but there
174+
// Since we've added a new kapt-specific provider to the variant, disable the provider
175+
// used for the JavaCompile task. This is not great, but there
159176
// does not seem to be a way around this with the way the kotlin android plugin
160177
// maps annotation processor providers from the variant directly onto kapt tasks.
161-
project.afterEvaluate {
162-
project.tasks.withType(JavaCompile).configureEach { JavaCompile task ->
163-
def itr = task.options.compilerArgumentProviders.iterator()
164-
while (itr.hasNext()) {
165-
def provider = itr.next()
166-
if (provider instanceof KaptRoomSchemaLocationArgumentProvider) {
167-
itr.remove()
168-
}
169-
}
170-
}
171-
}
178+
javaCompileSchemaGenerationEnabled = false
172179
}
173180
}
174181

@@ -295,12 +302,20 @@ class RoomSchemaLocationWorkaround implements Workaround {
295302
@Internal
296303
final Provider<Directory> configuredSchemaLocationDir
297304

298-
@OutputDirectory
305+
@Internal
299306
final Provider<Directory> schemaLocationDir
300307

301-
RoomSchemaLocationArgumentProvider(Provider<Directory> configuredSchemaLocationDir, Provider<Directory> schemaLocationDir) {
308+
@Internal
309+
final Supplier<Boolean> enabled
310+
311+
@Internal
312+
final Provider<Directory> nullDirectory
313+
314+
RoomSchemaLocationArgumentProvider(Provider<Directory> configuredSchemaLocationDir, Provider<Directory> schemaLocationDir, Provider<Directory> nullDirectory, Supplier<Boolean> enabled) {
302315
this.configuredSchemaLocationDir = configuredSchemaLocationDir
316+
this.enabled = enabled
303317
this.schemaLocationDir = schemaLocationDir
318+
this.nullDirectory = nullDirectory
304319
}
305320

306321
@Internal
@@ -310,25 +325,31 @@ class RoomSchemaLocationWorkaround implements Workaround {
310325

311326
@Override
312327
Iterable<String> asArguments() {
313-
if (configuredSchemaLocationDir.isPresent()) {
328+
if (configuredSchemaLocationDir.isPresent() && enabled.get()) {
314329
return ["-A${ROOM_SCHEMA_LOCATION}=${schemaLocationPath}" as String]
315330
} else {
316331
return []
317332
}
318333
}
334+
335+
@OutputDirectory
336+
@Optional
337+
Provider<Directory> getEffectiveSchemaLocationDir() {
338+
return enabled.get() ? schemaLocationDir : nullDirectory
339+
}
319340
}
320341

321342
static class JavaCompilerRoomSchemaLocationArgumentProvider extends RoomSchemaLocationArgumentProvider {
322-
JavaCompilerRoomSchemaLocationArgumentProvider(Provider<Directory> configuredSchemaLocationDir, Provider<Directory> schemaLocationDir) {
323-
super(configuredSchemaLocationDir, schemaLocationDir)
343+
JavaCompilerRoomSchemaLocationArgumentProvider(Provider<Directory> configuredSchemaLocationDir, Provider<Directory> schemaLocationDir, Provider<Directory> nullDirectory, Supplier<Boolean> enabled) {
344+
super(configuredSchemaLocationDir, schemaLocationDir, nullDirectory, enabled)
324345
}
325346
}
326347

327348
static class KaptRoomSchemaLocationArgumentProvider extends RoomSchemaLocationArgumentProvider {
328349
private Provider<Directory> temporarySchemaLocationDir
329350

330-
KaptRoomSchemaLocationArgumentProvider(Provider<Directory> configuredSchemaLocationDir, Provider<Directory> schemaLocationDir) {
331-
super(configuredSchemaLocationDir, schemaLocationDir)
351+
KaptRoomSchemaLocationArgumentProvider(Provider<Directory> configuredSchemaLocationDir, Provider<Directory> schemaLocationDir, Provider<Directory> nullDirectory) {
352+
super(configuredSchemaLocationDir, schemaLocationDir, nullDirectory, { true } as Supplier<Boolean>)
332353
this.temporarySchemaLocationDir = schemaLocationDir.map {it.dir("../${it.asFile.name}Temp") }
333354
}
334355

0 commit comments

Comments
 (0)