@@ -33,6 +33,9 @@ import java.lang.reflect.Field
3333 * aforementioned merge task. Note that this workaround only works with Kotlin Gradle plugin 1.3.70 or
3434 * higher.
3535 *
36+ * There are multiple issues related to these problems:
37+ * - https://issuetracker.google.com/issues/132245929
38+ * - https://issuetracker.google.com/issues/139438151
3639 */
3740@AndroidIssue (introducedIn = " 3.5.0" , fixedIn = [], link = " https://issuetracker.google.com/issues/132245929" )
3841class RoomSchemaLocationWorkaround implements Workaround {
@@ -102,11 +105,18 @@ class RoomSchemaLocationWorkaround implements Workaround {
102105
103106 // Register the generated schemas to be merged back to the original specified schema directory
104107 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+ }
105113 }
106114 )
107115
108116 // 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
110120 project. plugins. withId(" kotlin-kapt" ) {
111121 project. tasks. withType(kaptWithoutKotlincTaskClass). configureEach { Task task ->
112122 task. finalizedBy mergeTask
@@ -121,7 +131,12 @@ class RoomSchemaLocationWorkaround implements Workaround {
121131 }
122132
123133 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))
125140 }
126141 }
127142
@@ -138,7 +153,12 @@ class RoomSchemaLocationWorkaround implements Workaround {
138153 }
139154
140155 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))
142162 }
143163 }
144164 }
@@ -149,6 +169,11 @@ class RoomSchemaLocationWorkaround implements Workaround {
149169 return new File (schemaBaseDir, task. name)
150170 }
151171
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+
152177 static def getCompilerPluginOptions (Task task ) {
153178 def processorOptionsField = getAccessibleField(task. class, " processorOptions" )
154179 def compilerPluginOptions = processorOptionsField. get(task)
@@ -208,20 +233,44 @@ class RoomSchemaLocationWorkaround implements Workaround {
208233 task. project. roomSchemaMergeLocations. registerMerge(schemaDestinationDir, taskSpecificSchemaDir)
209234 }
210235
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 ) {
212257 def processorOptions = getCompilerPluginOptions(task)
213258 processorOptions. each { option ->
214259 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)
216263 }
217264 }
218265 }
219266
220- private static void setRoomSchemaLocationToTaskSpecificDirForKaptWithKotlinc (Task task ) {
267+ private static void setRoomSchemaLocationToTaskSpecificTmpDirForKaptWithKotlinc (Task task ) {
221268 def encodedOptions = getEncodedCompilerPluginOptions(task)
222269 def apOptions = decode(encodedOptions. value)
223270 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
225274 setOptionValue(encodedOptions, encode(apOptions))
226275 }
227276 }
@@ -313,7 +362,6 @@ class RoomSchemaLocationWorkaround implements Workaround {
313362 @TaskAction
314363 void mergeSourcesToDestinations () {
315364 roomSchemaMergeLocations. mergeAssociations. each { destination , source ->
316- project. delete(destination)
317365 println " Merging schemas to ${ destination} "
318366 project. copy {
319367 duplicatesStrategy(DuplicatesStrategy . INCLUDE )
0 commit comments