@@ -33,6 +33,9 @@ import java.lang.reflect.Field
33
33
* aforementioned merge task. Note that this workaround only works with Kotlin Gradle plugin 1.3.70 or
34
34
* higher.
35
35
*
36
+ * There are multiple issues related to these problems:
37
+ * - https://issuetracker.google.com/issues/132245929
38
+ * - https://issuetracker.google.com/issues/139438151
36
39
*/
37
40
@AndroidIssue (introducedIn = " 3.5.0" , fixedIn = [], link = " https://issuetracker.google.com/issues/132245929" )
38
41
class RoomSchemaLocationWorkaround implements Workaround {
@@ -102,11 +105,18 @@ class RoomSchemaLocationWorkaround implements Workaround {
102
105
103
106
// Register the generated schemas to be merged back to the original specified schema directory
104
107
task. project. roomSchemaMergeLocations. registerMerge(schemaDestinationDir, taskSpecificSchemaDir)
108
+
109
+ // Seed the task-specific generated schema dir with the existing schemas
110
+ task. doFirst {
111
+ copyExistingSchemasToTaskSpecificTmpDir(task, schemaDestinationDir, taskSpecificSchemaDir)
112
+ }
105
113
}
106
114
)
107
115
108
116
// Change the room schema location back to an absolute path right before the kapt tasks execute.
109
- // This allows other annotation processors that rely on the path being absolute to still function.
117
+ // This allows other annotation processors that rely on the path being absolute to still function and
118
+ // makes it resilient when the working directory is something other than the project directory.
119
+ // See https://issuetracker.google.com/issues/139438151
110
120
project. plugins. withId(" kotlin-kapt" ) {
111
121
project. tasks. withType(kaptWithoutKotlincTaskClass). configureEach { Task task ->
112
122
task. finalizedBy mergeTask
@@ -121,7 +131,12 @@ class RoomSchemaLocationWorkaround implements Workaround {
121
131
}
122
132
123
133
doFirst {
124
- setRoomSchemaLocationToTaskSpecificDirForKaptWithoutKotlinc(task)
134
+ // Setup a task-specific tmp dir and populate it with the existing schemas
135
+ setRoomSchemaLocationToTaskSpecificTmpDirForKaptWithoutKotlinc(task)
136
+ }
137
+ doLast {
138
+ // Copy the generated schemas from the tmp dir to the tracked output dir
139
+ copyGeneratedSchemasToOutputDir(task, getTaskSpecificSchemaTmpDir(task), getTaskSpecificSchemaDir(task))
125
140
}
126
141
}
127
142
@@ -138,7 +153,12 @@ class RoomSchemaLocationWorkaround implements Workaround {
138
153
}
139
154
140
155
doFirst {
141
- setRoomSchemaLocationToTaskSpecificDirForKaptWithKotlinc(task)
156
+ // Setup a task-specific tmp dir and populate it with the existing schemas
157
+ setRoomSchemaLocationToTaskSpecificTmpDirForKaptWithKotlinc(task)
158
+ }
159
+ doLast {
160
+ // Copy the generated schemas from the tmp dir to the tracked output dir
161
+ copyGeneratedSchemasToOutputDir(task, getTaskSpecificSchemaTmpDir(task), getTaskSpecificSchemaDir(task))
142
162
}
143
163
}
144
164
}
@@ -149,6 +169,11 @@ class RoomSchemaLocationWorkaround implements Workaround {
149
169
return new File (schemaBaseDir, task. name)
150
170
}
151
171
172
+ static File getTaskSpecificSchemaTmpDir (Task task ) {
173
+ def schemaBaseDir = task. project. layout. buildDirectory. dir(" roomSchemas/tmp" ). get(). asFile
174
+ return new File (schemaBaseDir, task. name)
175
+ }
176
+
152
177
static def getCompilerPluginOptions (Task task ) {
153
178
def processorOptionsField = getAccessibleField(task. class, " processorOptions" )
154
179
def compilerPluginOptions = processorOptionsField. get(task)
@@ -208,20 +233,44 @@ class RoomSchemaLocationWorkaround implements Workaround {
208
233
task. project. roomSchemaMergeLocations. registerMerge(schemaDestinationDir, taskSpecificSchemaDir)
209
234
}
210
235
211
- private static void setRoomSchemaLocationToTaskSpecificDirForKaptWithoutKotlinc (Task task ) {
236
+ private static void copyExistingSchemasToTaskSpecificTmpDir (Task task , File existingSchemaDir , File taskSpecificTmpDir ) {
237
+ // populate the task-specific tmp dir with any existing (non-generated) schemas
238
+ // this allows other annotation processors that might operate on these schemas
239
+ // to find them via the schema location argument
240
+ task. project. sync {
241
+ from existingSchemaDir
242
+ into taskSpecificTmpDir
243
+ }
244
+ }
245
+
246
+ private static void copyGeneratedSchemasToOutputDir (Task task , File taskSpecificTmpDir , File outputDir ) {
247
+ // Copy the generated generated schemas from the task-specific tmp dir to the
248
+ // task-specific output dir. This dance prevents the kapt task from clearing out
249
+ // the existing schemas before the annotation processors run
250
+ task. project. sync {
251
+ from taskSpecificTmpDir
252
+ into outputDir
253
+ }
254
+ }
255
+
256
+ private static void setRoomSchemaLocationToTaskSpecificTmpDirForKaptWithoutKotlinc (Task task ) {
212
257
def processorOptions = getCompilerPluginOptions(task)
213
258
processorOptions. each { option ->
214
259
if (option. key == ROOM_SCHEMA_LOCATION ) {
215
- setOptionValue(option, getTaskSpecificSchemaDir(task). absolutePath)
260
+ def taskSpecificTmpDir = getTaskSpecificSchemaTmpDir(task)
261
+ copyExistingSchemasToTaskSpecificTmpDir(task, task. project. file(option. value), taskSpecificTmpDir)
262
+ setOptionValue(option, taskSpecificTmpDir. absolutePath)
216
263
}
217
264
}
218
265
}
219
266
220
- private static void setRoomSchemaLocationToTaskSpecificDirForKaptWithKotlinc (Task task ) {
267
+ private static void setRoomSchemaLocationToTaskSpecificTmpDirForKaptWithKotlinc (Task task ) {
221
268
def encodedOptions = getEncodedCompilerPluginOptions(task)
222
269
def apOptions = decode(encodedOptions. value)
223
270
if (apOptions. containsKey(ROOM_SCHEMA_LOCATION )) {
224
- apOptions[ROOM_SCHEMA_LOCATION ] = getTaskSpecificSchemaDir(task). absolutePath
271
+ def taskSpecificTmpDir = getTaskSpecificSchemaTmpDir(task)
272
+ copyExistingSchemasToTaskSpecificTmpDir(task, task. project. file(apOptions[ROOM_SCHEMA_LOCATION ]), taskSpecificTmpDir)
273
+ apOptions[ROOM_SCHEMA_LOCATION ] = taskSpecificTmpDir. absolutePath
225
274
setOptionValue(encodedOptions, encode(apOptions))
226
275
}
227
276
}
@@ -313,7 +362,6 @@ class RoomSchemaLocationWorkaround implements Workaround {
313
362
@TaskAction
314
363
void mergeSourcesToDestinations () {
315
364
roomSchemaMergeLocations. mergeAssociations. each { destination , source ->
316
- project. delete(destination)
317
365
println " Merging schemas to ${ destination} "
318
366
project. copy {
319
367
duplicatesStrategy(DuplicatesStrategy . INCLUDE )
0 commit comments