--- 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<LicenseExtension> {
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<DynamicFeaturePlugin> {
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<TestPlugin> {
configureAndroid()
}
// make the license tasks looks for kotlin files in an Android project
- plugins.withType(KotlinAndroidPluginWrapper::class.java) {
+ plugins.withType<KotlinAndroidPluginWrapper> {
configureKotlinAndroid()
}
// make the license tasks for kotlin js project
- plugins.withType(KotlinJsPluginWrapper::class.java) {
+ plugins.withType<KotlinJsPluginWrapper> {
configureKotlin()
}
- plugins.withType(KotlinMultiplatformPluginWrapper::class.java) {
+ plugins.withType<KotlinMultiplatformPluginWrapper> {
configureKotlin()
+ configureComposeResources()
+ }
+
+ tasks.withType<License>().configureEach {
+ notCompatibleWithConfigurationCache("License tasks calls getProject() at execution time")
}
}
-@OptIn(ExperimentalStdlibApi::class)
private fun Project.configureKotlin() {
val kotlin = the<KotlinProjectExtension>()
val taskInfix = ""
@@ -128,6 +135,48 @@
}
}
+private fun Project.configureComposeResources() {
+ val kotlin = the<KotlinProjectExtension>()
+ 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<KotlinProjectExtension>()
@@ -159,13 +208,20 @@
private fun Project.configureAndroid() {
- val android = the<BaseExtension>()
+ val android = the<CommonExtension>()
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()
}