buildSrc/src/main/kotlin/SourceLicenseChecker.kt
changeset 0 0a13dcabf7d3
child 11 c028b38c3bdf
equal deleted inserted replaced
-1:000000000000 0:0a13dcabf7d3
       
     1 /*
       
     2  * AboutOss is a utility library to retrieve and display
       
     3  * opensource licenses in Android applications.
       
     4  *
       
     5  * Copyright (C) 2023 by Frederic-Charles Barthelery.
       
     6  *
       
     7  * This file is part of AboutOss.
       
     8  *
       
     9  * AboutOss is free software: you can redistribute it and/or modify
       
    10  * it under the terms of the GNU General Public License as published by
       
    11  * the Free Software Foundation, either version 3 of the License, or
       
    12  * (at your option) any later version.
       
    13  *
       
    14  * AboutOss is distributed in the hope that it will be useful,
       
    15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    17  * GNU General Public License for more details.
       
    18  *
       
    19  * You should have received a copy of the GNU General Public License
       
    20  * along with AboutOss.  If not, see <http://www.gnu.org/licenses/>.
       
    21  */
       
    22 package com.geekorum.build
       
    23 
       
    24 import com.android.build.api.dsl.AndroidSourceSet
       
    25 import com.android.build.gradle.BaseExtension
       
    26 import com.android.build.gradle.DynamicFeaturePlugin
       
    27 import com.hierynomus.gradle.license.LicenseBasePlugin
       
    28 import com.hierynomus.gradle.license.tasks.LicenseCheck
       
    29 import com.hierynomus.gradle.license.tasks.LicenseFormat
       
    30 import nl.javadude.gradle.plugins.license.License
       
    31 import nl.javadude.gradle.plugins.license.LicenseExtension
       
    32 import nl.javadude.gradle.plugins.license.LicensePlugin
       
    33 import org.gradle.api.NamedDomainObjectContainer
       
    34 import org.gradle.api.Project
       
    35 import org.gradle.api.file.FileTree
       
    36 import org.gradle.api.tasks.TaskProvider
       
    37 import org.gradle.kotlin.dsl.*
       
    38 import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
       
    39 import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper
       
    40 import org.jetbrains.kotlin.gradle.plugin.KotlinJsPluginWrapper
       
    41 import org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper
       
    42 import java.util.*
       
    43 
       
    44 internal fun Project.configureSourceLicenseChecker() {
       
    45     apply<LicensePlugin>()
       
    46 
       
    47     configure<LicenseExtension> {
       
    48         header = file("$rootDir/config/license/header.txt")
       
    49         mapping("java", "SLASHSTAR_STYLE")
       
    50         mapping("kt", "SLASHSTAR_STYLE")
       
    51 
       
    52         excludes(listOf("**/*.webp", "**/*.png"))
       
    53     }
       
    54 
       
    55     // the LicensePlugin doesn't configure itself properly on DynamicFeaturePlugin
       
    56     // Copied the code to configure it
       
    57     plugins.withType(DynamicFeaturePlugin::class.java) {
       
    58         configureAndroid()
       
    59     }
       
    60     // make the license tasks looks for kotlin files in an Android project
       
    61     plugins.withType(KotlinAndroidPluginWrapper::class.java) {
       
    62         configureKotlinAndroid()
       
    63     }
       
    64 
       
    65     // make the license tasks for kotlin js project
       
    66     plugins.withType(KotlinJsPluginWrapper::class.java) {
       
    67         configureKotlin()
       
    68     }
       
    69 
       
    70     plugins.withType(KotlinMultiplatformPluginWrapper::class.java) {
       
    71         configureKotlin()
       
    72     }
       
    73 }
       
    74 
       
    75 @OptIn(ExperimentalStdlibApi::class)
       
    76 private fun Project.configureKotlin() {
       
    77     val kotlin = the<KotlinProjectExtension>()
       
    78     val taskInfix = ""
       
    79     kotlin.sourceSets.configureEach {
       
    80         val kotlinSource = this
       
    81         val sourceSetTaskName =
       
    82             "${LicenseBasePlugin.getLICENSE_TASK_BASE_NAME()}${taskInfix}${name.capitalize(Locale.ROOT)}"
       
    83         logger.info("Adding $sourceSetTaskName task for sourceSet ${kotlinSource.name}")
       
    84         if (sourceSetTaskName in tasks.names) {
       
    85             // tasks may have already been added by configuration for the Android plugin
       
    86             logger.info("Tasks $sourceSetTaskName already exists. Skip")
       
    87             return@configureEach
       
    88         }
       
    89         tasks.register(sourceSetTaskName, LicenseCheck::class.java) {
       
    90             source(kotlinSource.kotlin)
       
    91         }
       
    92         val sourceSetFormatTaskName =
       
    93             "${LicenseBasePlugin.getFORMAT_TASK_BASE_NAME()}${taskInfix}${name.capitalize(Locale.ROOT)}"
       
    94         tasks.register(sourceSetFormatTaskName, LicenseFormat::class.java) {
       
    95             source(kotlinSource.kotlin)
       
    96         }
       
    97     }
       
    98 }
       
    99 
       
   100 @OptIn(ExperimentalStdlibApi::class)
       
   101 private fun Project.configureKotlinAndroid() {
       
   102     val kotlin = the<KotlinProjectExtension>()
       
   103     val android = the<BaseExtension>()
       
   104     val taskInfix = "Android"
       
   105     android.sourceSets.configureEach {
       
   106         val kotlinSource = kotlin.sourceSets[name]
       
   107         logger.info("Adding kotlin sources from sourceSet $name to License plugin tasks")
       
   108         val sourceSetTaskName =
       
   109             "${LicenseBasePlugin.getLICENSE_TASK_BASE_NAME()}${taskInfix}${name.capitalize(Locale.ROOT)}"
       
   110         tasks.named(sourceSetTaskName, LicenseCheck::class.java) {
       
   111             source(kotlinSource.kotlin, manifest.srcFile)
       
   112         }
       
   113         val sourceSetFormatTaskName =
       
   114             "${LicenseBasePlugin.getFORMAT_TASK_BASE_NAME()}${taskInfix}${name.capitalize(Locale.ROOT)}"
       
   115         tasks.named(sourceSetFormatTaskName, LicenseFormat::class.java) {
       
   116             source(kotlinSource.kotlin, manifest.srcFile)
       
   117         }
       
   118     }
       
   119 }
       
   120 
       
   121 
       
   122 private fun Project.configureAndroid() {
       
   123     val android = the<BaseExtension>()
       
   124     configureSourceSetRule(android.sourceSets, "Android") { ss ->
       
   125         @Suppress("DEPRECATION")
       
   126         when (ss) {
       
   127             // the dsl.AndroidSourceSet don't expose any getter, so we still need to cast it
       
   128             is com.android.build.gradle.api.AndroidSourceSet -> {
       
   129         ss.java.getSourceFiles() + ss.res.getSourceFiles() + fileTree(ss.manifest.srcFile)
       
   130             }
       
   131             else -> fileTree()
       
   132         }
       
   133     }
       
   134 }
       
   135 
       
   136 /**
       
   137  * Dynamically create a task for each sourceSet, and register with check
       
   138  */
       
   139 @Suppress("DefaultLocale")
       
   140 private fun Project.configureSourceSetRule(androidSourceSetContainer: NamedDomainObjectContainer<out AndroidSourceSet>,
       
   141                                            taskInfix: String, sourceSetSources: (AndroidSourceSet) -> FileTree) {
       
   142     // This follows the other check task pattern
       
   143     androidSourceSetContainer.configureEach {
       
   144         val sourceSetTaskName = "${LicenseBasePlugin.getLICENSE_TASK_BASE_NAME()}${taskInfix}${name.capitalize()}"
       
   145         logger.info("Adding $sourceSetTaskName task for sourceSet $name")
       
   146 
       
   147         val checkTask = tasks.register(sourceSetTaskName, LicenseCheck::class.java)
       
   148         configureForSourceSet(this, checkTask, sourceSetSources)
       
   149 
       
   150         // Add independent license task, which will perform format
       
   151         val sourceSetFormatTaskName = "${LicenseBasePlugin.getFORMAT_TASK_BASE_NAME()}${taskInfix}${name.capitalize()}"
       
   152         val formatTask = tasks.register(sourceSetFormatTaskName, LicenseFormat::class.java)
       
   153         configureForSourceSet(this, formatTask, sourceSetSources)
       
   154     }
       
   155 }
       
   156 
       
   157 private fun configureForSourceSet(sourceSet: AndroidSourceSet, task: TaskProvider<out License>, sourceSetSources: (AndroidSourceSet) -> FileTree) {
       
   158     task.configure {
       
   159         // Explicitly set description
       
   160         description = "Scanning license on ${sourceSet.name} files"
       
   161 
       
   162         // Default to all source files from SourceSet
       
   163         source = sourceSetSources(sourceSet)
       
   164     }
       
   165 }