# HG changeset patch # User Da Risk # Date 1778007356 14400 # Node ID 684356cd6a7d94a41eae6ecce797a41d3426bffc # Parent ceee12802fbc87556affb1ee085d56b5c404dd81 build: update SourceLicenseChecker for AGP 9.x diff -r ceee12802fbc -r 684356cd6a7d buildSrc/src/main/kotlin/SourceLicenseChecker.kt --- a/buildSrc/src/main/kotlin/SourceLicenseChecker.kt Mon May 04 23:53:58 2026 -0400 +++ b/buildSrc/src/main/kotlin/SourceLicenseChecker.kt Tue May 05 14:55:56 2026 -0400 @@ -22,6 +22,7 @@ package com.geekorum.build import com.android.build.api.dsl.AndroidSourceSet +import com.android.build.api.dsl.CommonExtension import com.android.build.gradle.BaseExtension import com.android.build.gradle.DynamicFeaturePlugin import com.android.build.gradle.TestPlugin @@ -40,6 +41,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper import org.jetbrains.kotlin.gradle.plugin.KotlinJsPluginWrapper import org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper +import java.io.File import java.util.Locale internal fun Project.configureSourceLicenseChecker() { @@ -48,39 +50,44 @@ configure { header = file("$rootDir/config/license/header.txt") mapping("java", "SLASHSTAR_STYLE") + mapping("json", "SLASHSTAR_STYLE") mapping("kt", "SLASHSTAR_STYLE") - excludes(listOf("**/*.webp", "**/*.png")) + excludes(listOf("**/*.webp", "**/*.png", "**/*.jpeg", "**/*.jpg")) } // the LicensePlugin doesn't configure itself properly on DynamicFeaturePlugin // Copied the code to configure it - plugins.withType(DynamicFeaturePlugin::class.java) { + plugins.withType { configureAndroid() } // the LicensePlugin doesn't configure itself properly on Android Test plugin // Copied the code to configure it - plugins.withType(TestPlugin::class.java) { + plugins.withType { configureAndroid() } // make the license tasks looks for kotlin files in an Android project - plugins.withType(KotlinAndroidPluginWrapper::class.java) { + plugins.withType { configureKotlinAndroid() } // make the license tasks for kotlin js project - plugins.withType(KotlinJsPluginWrapper::class.java) { + plugins.withType { configureKotlin() } - plugins.withType(KotlinMultiplatformPluginWrapper::class.java) { + plugins.withType { configureKotlin() + configureComposeResources() + } + + tasks.withType().configureEach { + notCompatibleWithConfigurationCache("License tasks calls getProject() at execution time") } } -@OptIn(ExperimentalStdlibApi::class) private fun Project.configureKotlin() { val kotlin = the() val taskInfix = "" @@ -128,6 +135,48 @@ } } +private fun Project.configureComposeResources() { + val kotlin = the() + val taskInfix = "ComposeResources" + kotlin.sourceSets.configureEach { + val kotlinSource = this + val sourceSetTaskName = + "${LicenseBasePlugin.getLICENSE_TASK_BASE_NAME()}${taskInfix}${name.capitalize()}" + if (name.startsWith("generated")) { + logger.info("Skip sourceSet $name because it's generated code") + return@configureEach + } + val resourceDir = kotlinSource.resources.sourceDirectories.files.first() + val composeResourceDir = File(resourceDir, "../composeResources") + + val configureLicenseCheckTaskLambda: LicenseCheck.() -> Unit = { + source(composeResourceDir) + } + if (sourceSetTaskName in tasks.names) { + // tasks may have already been added by configuration for the Android plugin + logger.info("Tasks $sourceSetTaskName already exists. configure it") + tasks.named(sourceSetTaskName, LicenseCheck::class.java, configureLicenseCheckTaskLambda) + } else { + logger.info("Adding ${project.name}:$sourceSetTaskName task for sourceSet ${kotlinSource.name}") + tasks.register(sourceSetTaskName, LicenseCheck::class.java, configureLicenseCheckTaskLambda) + } + + val configureLicenseFormatTaskLambda: LicenseFormat.() -> Unit = { + source(composeResourceDir) + } + val sourceSetFormatTaskName = + "${LicenseBasePlugin.getFORMAT_TASK_BASE_NAME()}${taskInfix}${name.capitalize()}" + if (sourceSetFormatTaskName in tasks.names) { + // tasks may have already been added by configuration for the Android plugin + logger.info("Tasks $sourceSetFormatTaskName already exists. configure it") + tasks.named(sourceSetFormatTaskName, LicenseFormat::class.java, configureLicenseFormatTaskLambda) + } else { + logger.info("Adding ${project.name}:$sourceSetFormatTaskName task for sourceSet ${kotlinSource.name}") + tasks.register(sourceSetFormatTaskName, LicenseFormat::class.java, configureLicenseFormatTaskLambda) + } + } +} + @OptIn(ExperimentalStdlibApi::class) private fun Project.configureKotlinAndroid() { val kotlin = the() @@ -159,13 +208,20 @@ private fun Project.configureAndroid() { - val android = the() + val android = the() configureSourceSetRule(android.sourceSets, "Android") { ss -> @Suppress("DEPRECATION") when (ss) { // the dsl.AndroidSourceSet don't expose any getter, so we still need to cast it is com.android.build.gradle.api.AndroidSourceSet -> { - ss.java.getSourceFiles() + ss.res.getSourceFiles() + fileTree(ss.manifest.srcFile) + val kotlinFileTrees = ss.kotlin.directories.foldIndexed(fileTree() as FileTree) { index, acc, n -> + if (index == 0) { // skip first as it's an empty tree created for typing + fileTree(n) + } else { + acc + fileTree(n) + } + } + ss.java.getSourceFiles() + ss.res.getSourceFiles() + fileTree(ss.manifest.srcFile) + kotlinFileTrees } else -> fileTree() }