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 package androidx.build 17 18 import org.gradle.api.DefaultTask 19 import org.gradle.api.file.RegularFileProperty 20 import org.gradle.api.provider.Property 21 import org.gradle.api.tasks.Input 22 import org.gradle.api.tasks.Internal 23 import org.gradle.api.tasks.OutputFile 24 import org.gradle.api.tasks.TaskAction 25 import org.gradle.work.DisableCachingByDefault 26 import org.jetbrains.kotlin.gradle.dsl.KotlinVersion 27 28 /** Check if the kotlin-stdlib transitive dependencies are the same as the project specified one. */ 29 @DisableCachingByDefault(because = "not worth caching") 30 abstract class CheckKotlinApiTargetTask : DefaultTask() { 31 32 @get:Input abstract val kotlinTarget: Property<KotlinVersion> 33 34 @get:Internal val projectPath: String = project.path 35 36 @get:Input 37 val allDependencies: List<Pair<String, String>> = 38 project.configurations 39 .filter { it.isPublished() && it.isCanBeResolved } 40 .flatMap { config -> 41 config.resolvedConfiguration.firstLevelModuleDependencies.map { 42 "${it.moduleName}:${it.moduleVersion}" to config.name 43 } 44 } 45 46 @get:OutputFile abstract val outputFile: RegularFileProperty 47 48 @TaskAction 49 fun check() { 50 val incompatibleConfigurations = 51 allDependencies 52 .asSequence() 53 .filter { it.first.startsWith("kotlin-stdlib:") } 54 .map { it.first.substringAfter(":") to it.second } 55 .map { KotlinVersion.fromVersion(it.first.substringBeforeLast('.')) to it.second } 56 .filter { it.first != kotlinTarget.get() } 57 .map { it.second } 58 .toList() 59 60 val outputFile = outputFile.get().asFile 61 outputFile.parentFile.mkdirs() 62 63 if (incompatibleConfigurations.isNotEmpty()) { 64 val errorMessage = 65 incompatibleConfigurations.joinToString( 66 prefix = 67 "The project's kotlin-stdlib target is ${kotlinTarget.get()} but these " + 68 "configurations are pulling in different versions of kotlin-stdlib: ", 69 postfix = 70 "\nRun ./gradlew $projectPath:dependencies to see which dependency is " + 71 "pulling in the incompatible kotlin-stdlib" 72 ) 73 outputFile.writeText("FAILURE: $errorMessage") 74 throw IllegalStateException(errorMessage) 75 } 76 } 77 78 companion object { 79 const val TASK_NAME = "checkKotlinApiTarget" 80 } 81 } 82