1 /* <lambda>null2 * Copyright 2021 Google LLC 3 * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package com.google.devtools.ksp.gradle 18 19 import com.android.build.api.dsl.CommonExtension 20 import com.android.build.gradle.BaseExtension 21 import org.gradle.api.Project 22 import org.gradle.api.file.FileCollection 23 import org.gradle.api.tasks.TaskProvider 24 import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation 25 import java.io.File 26 27 /** 28 * This helper class handles communication with the android plugin. 29 * It is isolated in a separate class to avoid adding dependency on the android plugin. 30 * Instead, we add a compileOnly dependency to the Android Plugin, which means we can still function 31 * without the Android plugin. The downside is that we need to ensure never to access Android 32 * plugin APIs directly without checking its existence (we have tests covering that case). 33 */ 34 @Suppress("UnstableApiUsage") // some android APIs are unsable. 35 object AndroidPluginIntegration { 36 37 private val agpPluginIds = listOf("com.android.application", "com.android.library", "com.android.dynamic-feature") 38 39 fun forEachAndroidSourceSet(project: Project, onSourceSet: (String) -> Unit) { 40 agpPluginIds.forEach { agpPluginId -> 41 project.pluginManager.withPlugin(agpPluginId) { 42 // for android apps, we need a configuration per source set 43 decorateAndroidExtension(project, onSourceSet) 44 } 45 } 46 } 47 48 private fun decorateAndroidExtension(project: Project, onSourceSet: (String) -> Unit) { 49 val sourceSets = when (val androidExt = project.extensions.getByName("android")) { 50 is BaseExtension -> androidExt.sourceSets 51 is CommonExtension<*, *, *, *> -> androidExt.sourceSets 52 else -> throw RuntimeException("Unsupported Android Gradle plugin version.") 53 } 54 sourceSets.all { 55 onSourceSet(it.name) 56 } 57 } 58 59 fun getCompilationSourceSets(kotlinCompilation: KotlinJvmAndroidCompilation): List<String> { 60 return kotlinCompilation.androidVariant 61 .sourceSets 62 .map { it.name } 63 } 64 65 fun registerGeneratedSources( 66 project: Project, 67 kotlinCompilation: KotlinJvmAndroidCompilation, 68 kspTaskProvider: TaskProvider<KspTaskJvm>, 69 javaOutputDir: File, 70 kotlinOutputDir: File, 71 classOutputDir: File, 72 resourcesOutputDir: FileCollection, 73 ) { 74 val kspJavaOutput = project.fileTree(javaOutputDir).builtBy(kspTaskProvider) 75 val kspKotlinOutput = project.fileTree(kotlinOutputDir).builtBy(kspTaskProvider) 76 val kspClassOutput = project.fileTree(classOutputDir).builtBy(kspTaskProvider) 77 kspJavaOutput.include("**/*.java") 78 kspKotlinOutput.include("**/*.kt") 79 kspClassOutput.include("**/*.class") 80 kotlinCompilation.androidVariant.registerExternalAptJavaOutput(kspJavaOutput) 81 kotlinCompilation.androidVariant.addJavaSourceFoldersToModel(kspKotlinOutput.dir) 82 kotlinCompilation.androidVariant.registerPreJavacGeneratedBytecode(kspClassOutput) 83 kotlinCompilation.androidVariant.registerPostJavacGeneratedBytecode(resourcesOutputDir) 84 } 85 } 86