1 /* <lambda>null2 * Copyright 2024 The Android Open Source Project 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 androidx.build.binarycompatibilityvalidator 18 19 import androidx.binarycompatibilityvalidator.KlibDumpParser 20 import androidx.binarycompatibilityvalidator.ParseException 21 import javax.inject.Inject 22 import org.gradle.api.DefaultTask 23 import org.gradle.api.GradleException 24 import org.gradle.api.file.ConfigurableFileCollection 25 import org.gradle.api.file.DirectoryProperty 26 import org.gradle.api.file.FileSystemOperations 27 import org.gradle.api.file.RegularFileProperty 28 import org.gradle.api.provider.ListProperty 29 import org.gradle.api.provider.Property 30 import org.gradle.api.tasks.CacheableTask 31 import org.gradle.api.tasks.Classpath 32 import org.gradle.api.tasks.Input 33 import org.gradle.api.tasks.InputFile 34 import org.gradle.api.tasks.Internal 35 import org.gradle.api.tasks.OutputDirectory 36 import org.gradle.api.tasks.PathSensitive 37 import org.gradle.api.tasks.PathSensitivity 38 import org.gradle.api.tasks.TaskAction 39 import org.gradle.workers.WorkAction 40 import org.gradle.workers.WorkParameters 41 import org.gradle.workers.WorkerExecutor 42 import org.jetbrains.kotlin.library.abi.ExperimentalLibraryAbiReader 43 44 @CacheableTask 45 abstract class UpdateAbiTask 46 @Inject 47 constructor(@Internal protected val workerExecutor: WorkerExecutor) : DefaultTask() { 48 49 @get:Inject abstract val fileSystemOperations: FileSystemOperations 50 51 @get:Input abstract val version: Property<String> 52 53 @get:Input abstract val shouldWriteVersionedApiFile: Property<Boolean> 54 55 @get:Input abstract val unsupportedNativeTargetNames: ListProperty<String> 56 57 /** Text file from which API signatures will be read. */ 58 @get:PathSensitive(PathSensitivity.RELATIVE) 59 @get:InputFile 60 abstract val inputApiLocation: RegularFileProperty 61 62 /** Directory to which API signatures will be written. */ 63 @get:OutputDirectory abstract val outputDir: DirectoryProperty 64 65 @get:Classpath abstract val runtimeClasspath: ConfigurableFileCollection 66 67 @TaskAction 68 fun execute() { 69 unsupportedNativeTargetNames.get().let { targets -> 70 if (targets.isNotEmpty()) { 71 throw GradleException( 72 "Cannot update API files because the current host doesn't support the " + 73 "following targets: ${targets.joinToString(", ")}" 74 ) 75 } 76 } 77 fileSystemOperations.copy { 78 it.from(inputApiLocation) 79 it.into(outputDir) 80 } 81 if (shouldWriteVersionedApiFile.get()) { 82 fileSystemOperations.copy { 83 it.from(inputApiLocation) 84 it.into(outputDir) 85 it.rename(CURRENT_API_FILE_NAME, "${version.get()}.txt") 86 } 87 } 88 89 // Execute BCV code as a WorkAction to allow setting the classpath for the action. 90 // This is to work around the kotlin compiler needing to be a compileOnly dependency for 91 // buildSrc (https://kotl.in/gradle/internal-compiler-symbols, aosp/3368960). 92 val workQueue = workerExecutor.classLoaderIsolation { it.classpath.from(runtimeClasspath) } 93 workQueue.submit(UpdateAbiWorker::class.java) { params -> 94 params.abiFile.set(outputDir.file("current.txt")) 95 } 96 } 97 } 98 99 private interface UpdateAbiParameters : WorkParameters { 100 val abiFile: RegularFileProperty 101 } 102 103 private abstract class UpdateAbiWorker : WorkAction<UpdateAbiParameters> { 104 @OptIn(ExperimentalLibraryAbiReader::class) executenull105 override fun execute() { 106 try { 107 KlibDumpParser(parameters.abiFile.get().asFile).parse() 108 } catch (e: ParseException) { 109 System.err.println( 110 "Successfully updated API file but parser was unable to parse the generated output. " + 111 "This is a bug in the parser and should be filed to $NEW_ISSUE_URL" 112 ) 113 e.printStackTrace() 114 } 115 } 116 } 117