20 * along with AboutOss. If not, see <http://www.gnu.org/licenses/>. |
20 * along with AboutOss. If not, see <http://www.gnu.org/licenses/>. |
21 */ |
21 */ |
22 package com.geekorum.build |
22 package com.geekorum.build |
23 |
23 |
24 import com.android.build.api.dsl.AndroidSourceSet |
24 import com.android.build.api.dsl.AndroidSourceSet |
|
25 import com.android.build.api.dsl.CommonExtension |
25 import com.android.build.gradle.BaseExtension |
26 import com.android.build.gradle.BaseExtension |
26 import com.android.build.gradle.DynamicFeaturePlugin |
27 import com.android.build.gradle.DynamicFeaturePlugin |
27 import com.android.build.gradle.TestPlugin |
28 import com.android.build.gradle.TestPlugin |
28 import com.hierynomus.gradle.license.LicenseBasePlugin |
29 import com.hierynomus.gradle.license.LicenseBasePlugin |
29 import com.hierynomus.gradle.license.tasks.LicenseCheck |
30 import com.hierynomus.gradle.license.tasks.LicenseCheck |
38 import org.gradle.kotlin.dsl.* |
39 import org.gradle.kotlin.dsl.* |
39 import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension |
40 import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension |
40 import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper |
41 import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper |
41 import org.jetbrains.kotlin.gradle.plugin.KotlinJsPluginWrapper |
42 import org.jetbrains.kotlin.gradle.plugin.KotlinJsPluginWrapper |
42 import org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper |
43 import org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper |
|
44 import java.io.File |
43 import java.util.Locale |
45 import java.util.Locale |
44 |
46 |
45 internal fun Project.configureSourceLicenseChecker() { |
47 internal fun Project.configureSourceLicenseChecker() { |
46 apply<LicensePlugin>() |
48 apply<LicensePlugin>() |
47 |
49 |
48 configure<LicenseExtension> { |
50 configure<LicenseExtension> { |
49 header = file("$rootDir/config/license/header.txt") |
51 header = file("$rootDir/config/license/header.txt") |
50 mapping("java", "SLASHSTAR_STYLE") |
52 mapping("java", "SLASHSTAR_STYLE") |
|
53 mapping("json", "SLASHSTAR_STYLE") |
51 mapping("kt", "SLASHSTAR_STYLE") |
54 mapping("kt", "SLASHSTAR_STYLE") |
52 |
55 |
53 excludes(listOf("**/*.webp", "**/*.png")) |
56 excludes(listOf("**/*.webp", "**/*.png", "**/*.jpeg", "**/*.jpg")) |
54 } |
57 } |
55 |
58 |
56 // the LicensePlugin doesn't configure itself properly on DynamicFeaturePlugin |
59 // the LicensePlugin doesn't configure itself properly on DynamicFeaturePlugin |
57 // Copied the code to configure it |
60 // Copied the code to configure it |
58 plugins.withType(DynamicFeaturePlugin::class.java) { |
61 plugins.withType<DynamicFeaturePlugin> { |
59 configureAndroid() |
62 configureAndroid() |
60 } |
63 } |
61 |
64 |
62 // the LicensePlugin doesn't configure itself properly on Android Test plugin |
65 // the LicensePlugin doesn't configure itself properly on Android Test plugin |
63 // Copied the code to configure it |
66 // Copied the code to configure it |
64 plugins.withType(TestPlugin::class.java) { |
67 plugins.withType<TestPlugin> { |
65 configureAndroid() |
68 configureAndroid() |
66 } |
69 } |
67 |
70 |
68 // make the license tasks looks for kotlin files in an Android project |
71 // make the license tasks looks for kotlin files in an Android project |
69 plugins.withType(KotlinAndroidPluginWrapper::class.java) { |
72 plugins.withType<KotlinAndroidPluginWrapper> { |
70 configureKotlinAndroid() |
73 configureKotlinAndroid() |
71 } |
74 } |
72 |
75 |
73 // make the license tasks for kotlin js project |
76 // make the license tasks for kotlin js project |
74 plugins.withType(KotlinJsPluginWrapper::class.java) { |
77 plugins.withType<KotlinJsPluginWrapper> { |
75 configureKotlin() |
78 configureKotlin() |
76 } |
79 } |
77 |
80 |
78 plugins.withType(KotlinMultiplatformPluginWrapper::class.java) { |
81 plugins.withType<KotlinMultiplatformPluginWrapper> { |
79 configureKotlin() |
82 configureKotlin() |
80 } |
83 configureComposeResources() |
81 } |
84 } |
82 |
85 |
83 @OptIn(ExperimentalStdlibApi::class) |
86 tasks.withType<License>().configureEach { |
|
87 notCompatibleWithConfigurationCache("License tasks calls getProject() at execution time") |
|
88 } |
|
89 } |
|
90 |
84 private fun Project.configureKotlin() { |
91 private fun Project.configureKotlin() { |
85 val kotlin = the<KotlinProjectExtension>() |
92 val kotlin = the<KotlinProjectExtension>() |
86 val taskInfix = "" |
93 val taskInfix = "" |
87 kotlin.sourceSets.configureEach { |
94 kotlin.sourceSets.configureEach { |
88 val kotlinSource = this |
95 val kotlinSource = this |
112 source(kotlinSource.kotlin) |
119 source(kotlinSource.kotlin) |
113 exclude { |
120 exclude { |
114 // exclude generated files, notably protobuf, ksp, hilt |
121 // exclude generated files, notably protobuf, ksp, hilt |
115 "/generated/" in it.file.path |
122 "/generated/" in it.file.path |
116 } |
123 } |
|
124 } |
|
125 val sourceSetFormatTaskName = |
|
126 "${LicenseBasePlugin.getFORMAT_TASK_BASE_NAME()}${taskInfix}${name.capitalize()}" |
|
127 if (sourceSetFormatTaskName in tasks.names) { |
|
128 // tasks may have already been added by configuration for the Android plugin |
|
129 logger.info("Tasks $sourceSetFormatTaskName already exists. configure it") |
|
130 tasks.named(sourceSetFormatTaskName, LicenseFormat::class.java, configureLicenseFormatTaskLambda) |
|
131 } else { |
|
132 logger.info("Adding ${project.name}:$sourceSetFormatTaskName task for sourceSet ${kotlinSource.name}") |
|
133 tasks.register(sourceSetFormatTaskName, LicenseFormat::class.java, configureLicenseFormatTaskLambda) |
|
134 } |
|
135 } |
|
136 } |
|
137 |
|
138 private fun Project.configureComposeResources() { |
|
139 val kotlin = the<KotlinProjectExtension>() |
|
140 val taskInfix = "ComposeResources" |
|
141 kotlin.sourceSets.configureEach { |
|
142 val kotlinSource = this |
|
143 val sourceSetTaskName = |
|
144 "${LicenseBasePlugin.getLICENSE_TASK_BASE_NAME()}${taskInfix}${name.capitalize()}" |
|
145 if (name.startsWith("generated")) { |
|
146 logger.info("Skip sourceSet $name because it's generated code") |
|
147 return@configureEach |
|
148 } |
|
149 val resourceDir = kotlinSource.resources.sourceDirectories.files.first() |
|
150 val composeResourceDir = File(resourceDir, "../composeResources") |
|
151 |
|
152 val configureLicenseCheckTaskLambda: LicenseCheck.() -> Unit = { |
|
153 source(composeResourceDir) |
|
154 } |
|
155 if (sourceSetTaskName in tasks.names) { |
|
156 // tasks may have already been added by configuration for the Android plugin |
|
157 logger.info("Tasks $sourceSetTaskName already exists. configure it") |
|
158 tasks.named(sourceSetTaskName, LicenseCheck::class.java, configureLicenseCheckTaskLambda) |
|
159 } else { |
|
160 logger.info("Adding ${project.name}:$sourceSetTaskName task for sourceSet ${kotlinSource.name}") |
|
161 tasks.register(sourceSetTaskName, LicenseCheck::class.java, configureLicenseCheckTaskLambda) |
|
162 } |
|
163 |
|
164 val configureLicenseFormatTaskLambda: LicenseFormat.() -> Unit = { |
|
165 source(composeResourceDir) |
117 } |
166 } |
118 val sourceSetFormatTaskName = |
167 val sourceSetFormatTaskName = |
119 "${LicenseBasePlugin.getFORMAT_TASK_BASE_NAME()}${taskInfix}${name.capitalize()}" |
168 "${LicenseBasePlugin.getFORMAT_TASK_BASE_NAME()}${taskInfix}${name.capitalize()}" |
120 if (sourceSetFormatTaskName in tasks.names) { |
169 if (sourceSetFormatTaskName in tasks.names) { |
121 // tasks may have already been added by configuration for the Android plugin |
170 // tasks may have already been added by configuration for the Android plugin |
157 } |
206 } |
158 } |
207 } |
159 |
208 |
160 |
209 |
161 private fun Project.configureAndroid() { |
210 private fun Project.configureAndroid() { |
162 val android = the<BaseExtension>() |
211 val android = the<CommonExtension>() |
163 configureSourceSetRule(android.sourceSets, "Android") { ss -> |
212 configureSourceSetRule(android.sourceSets, "Android") { ss -> |
164 @Suppress("DEPRECATION") |
213 @Suppress("DEPRECATION") |
165 when (ss) { |
214 when (ss) { |
166 // the dsl.AndroidSourceSet don't expose any getter, so we still need to cast it |
215 // the dsl.AndroidSourceSet don't expose any getter, so we still need to cast it |
167 is com.android.build.gradle.api.AndroidSourceSet -> { |
216 is com.android.build.gradle.api.AndroidSourceSet -> { |
168 ss.java.getSourceFiles() + ss.res.getSourceFiles() + fileTree(ss.manifest.srcFile) |
217 val kotlinFileTrees = ss.kotlin.directories.foldIndexed(fileTree() as FileTree) { index, acc, n -> |
|
218 if (index == 0) { // skip first as it's an empty tree created for typing |
|
219 fileTree(n) |
|
220 } else { |
|
221 acc + fileTree(n) |
|
222 } |
|
223 } |
|
224 ss.java.getSourceFiles() + ss.res.getSourceFiles() + fileTree(ss.manifest.srcFile) + kotlinFileTrees |
169 } |
225 } |
170 else -> fileTree() |
226 else -> fileTree() |
171 } |
227 } |
172 } |
228 } |
173 } |
229 } |