License List Plugin is a Gradle plugin to manage artifacts' licenses that your Android project uses. It can generate the data source as human readable or handy format.
- Introduction
- Getting Started
- Tasks
- Extension
- Tips
- license-tools-plugin migration
- [Local jar/aar files][#manage-local-files)
- Exclude specific groups/artifacts
- Add other configurations like WearApp
- Custom variant-aware configurations
- Html template customization
- Render Json output
- Known limitation
- Migration
- LICENSE
The goals of this plugin are the following
- Easy to add/delete/change licenses through human readable text. (either of Yaml, Json)
- Flexible visualization of licenses. (Html template injection, Json export)
- Whitelabel support using productFlavors or buildTypes for Android project. (Possible to manage for each variants)
Yaml configuration example is like the following.
release:
androidx.activity:
- key: activity
displayName: Activity
url: https://developer.android.com/jetpack/androidx
copyrightHolders:
- The Android Open Source Project
licenses:
- apache-2.0
This plugin can generate HTML or a json file for the license viewer based on the management file.
Sample view using json | The default html layout |
---|---|
Apply the plugin to "com.android.application" modules.
For example, plugins block in Kotlin
ref: https://plugins.gradle.org/plugin/io.github.jmatsu.license-list#kotlin-usage
plugins {
id("com.android.application")
id("io.github.jmatsu.license-list") version ("<version}>")
}
Groovy
ref: https://plugins.gradle.org/plugin/io.github.jmatsu.license-list#groovy-usage
// Legacy groovy example.
buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath "io.github.jmatsu:license-list-gradle:<version>"
}
}
apply plugin: "com.android.application"
apply plugin: "io.github.jmatsu.license-list"
You can generate management files based on the current dependencies.
If you need to manage only one variant, then it's better to configure this plugin first. For example, freeRelease
is the variant to be managed.
licenseList {
defaultVariant = "freeRelease"
}
And then, run ./gradlew initLicenseList
. It's kinda alias of initFreeReleaseLicenseList
. For those who need to manage multiple variants, init<Variant>LicenseList
is available for each variants by default so please use the proper task.
For those who have been using cookpad/license-tools-plugin, you can migrate your licenses.yml. Please check license-tools-plugin migration.
After running initLicenseList
, you've got the management files below.
- artifact-definition.yml
- license-catalog.yml
- .artifactignore
This file contains the definitions of artifacts and license keys to manage.
structured with scope (default)
The base format is Map<Scope, Map<Group, List<ArtifactDefinition>>>
.
"<variant/scope name>":
"<group>":
- key: "<artifact name>" # Required
displayName: "<A name that will be displayed>" # Required
url: "<the url of this artifact>" # Optional. null or removing this field means this artifact has no url
copyrightHolders: # Optional. null or removing this field means this artifact has no copyright holders
- "<copyright holder name>"
- ...
license: # Required
- "<license key which is defined in license-catalog.yml>"
skip: "<true|false>" # Optional. Specify true if this artifact is not found in the current dependencies but should be displayed. false by default.
# Please use .artifactignore if you would like not to display any artifacts.
...
...
...
structured w/o scope
The base format is Map<Group, List<ArtifactDefinition>>
.
flatten
The base format is List<ArtifactDefinition>
. The format of ArtifactDefinition
is almost same but only key is different.
- key: "<group>:<artifact name>"
...
...
This file contains licenses that artifacts have references. This plugin infers licenses using their name and provide primary keys automatically.
- key: "<the primary key of this license>" # Required
name: "<name to be displayed>" # Required
url: "<license url>" # Optional. null or removing this field means this license has no url.
This file is to find artifact that should be ignored from the management. Each lines must consist of regular expressions or glob patterns that matches with <group>:<name>
. If you'd like to use glob
pattern, you need to configure this plugin through the extension. ref: Extension
Regular expression samples
com\.example:sample-artifact
io\.github\.jmatsu\.internal:.*
io\.github\.jmatsu\..*
Glob pattern samples
: is a path separator instead of /
com.example:sample-artifact
io.github.jmatsu.internal:*
io.github.jmatsu.**
This section explains how you will manage the files that this plugin uses.
The basic management cycle is the below.
- Run
./gradlew validate<Variant>LicenseList
- Run
merge<Variant>LicenseList
to reflect the current artifacts if failed. - Run
./gradlew inspect<Variant>LicenseList
- Modify
artifact-definition.yml
based on the inspection report above.- You may want to modify
.artifactignore
to exclude several artifacts. - If so, please go to Step2 after updating
.artifactignore
to reflect the ignore configurations.
- You may want to modify
- And also, modify
license-catalog.yml
as well. - Go back to Step1 until no issue is found.
Generate the file for your license viewer by running ./gradlew visualize<Variant>LicenseList
and embed it into your application.
This plugin supports html
and json
as the resource format.
This plugin follows the naming strategy of Android Gradle Plugin does as much as possible. i.e. <actionName><Variant>LicenseList
is it.
init<Variant>LicenseList
This is the entrypoint of this plugin. It generates the base definition file and the license catalog file that you will manage.
Do you want to overwrite it?
If you would like to re-initialize the definition files, then please pass -Poverwrite=true
when running this task.
Available since 0.4
inspect<Variant>LicenseList
Inspect the current management files and report lacked attributes.
NOTE: This doesn't mean your definition file satisfy license usages. It's your responsibility, not of this plugin.
validate<Variant>LicenseList
This checks if the current definition files and the current project dependencies differ.
NOTE: This doesn't mean your definition file satisfy license usages. It's your responsibility, not of this plugin.
merge<Variant>LicenseList
Merge the current project dependencies into the current definition files with respecting the current definition files.
The strategy is defensive. This task will preserve your changes in the definition files.
visualize<Variant>LicenseList
It will create a HTML file or JSON file based on the plugin configuration if validation and inspection succeed.
NOTE: -PskipInspect=true
can skip inspect action and -PskipValidate=true
can skip validate action.
Tips: example renders its licenses based on the both of json and html.
licenseList {
// Control availability of this plugin('s tasks). true by default.
isEnabled = <true|false>
// Make initLicenseList an alias of `initFreeReleaseLicenseList`
defaultTarget = "<variant name like freeRelease>"
// The filter pattern used for ignore feature. regex is default.
ignoreFormat = "<regex|glob>"
variants {
// you can declare the configuration for each variants
create("freeRelease") {
// A directory that contains artifact-definition.yml, license-catalog.yml and .artifactignore
baseDir = file("license-list")
// options for the management file
assembly {
// management file format
// optional: yaml by default
format = "<yaml|json>"
// the style of the managed content
// optional: structured by default
style = "<structured|flatten>"
// whether or not artifacts are grouped by scopes like `implementation`
// optional: true by default
groupByScopes = true
// Rarely used. See Tips/Custom configurations
// optional
additionalScopes += setOf("customImplConfiguration")
// Rarely used. See Tips/WearApp
// optional
targetConfigurations += setOf("wearApp")
}
// options for the report file
visualization {
format = "<html|json>" // html by default
// the embedded template will be used by default
htmlTemplateDir = file("</where/plugin/find/for/html-template>")
// To support free maker's breaking changes. rarely used.
freeMakerVersion = "<version string>"
// `<variant>/assets` is the default location
outputDir = file("</where/plugin/generate/file/to>")
}
}
}
}
ref: cookpad/license-tools-plugin
Those who are from license-tools-plugin can migrate their yml file to the format that this plugin supports.
Configure this plugin for the migration
plugins {
id("com.cookpad.android.licensetools") // A migration task is available only when the plugin is applied
id("io.github.jmatsu.license-list")
}
licenseTools {
licensesYaml = ... // this property is supported
ignoreGroups = [...] // this property is also supported
}
licenseList {
defaultVariant = "<please specify the variant you would like to manage>"
}
Run the migration task
Please note that the following task is available only when license-tools-plugin
is applied
./gradlew migrateLicenseToolsDefinition
Copy generated files and remove license-tools-plugin
Generated files are available in /path/to/app-module/build/license-list
. They are .artifactignore
, artifact-definition.yml
, and license-catalog.yml
.
Please move them to the directory where you would like to use for the management. The default configuration will check /path/to/app-module
directory.
- Only v1.7.0 is tested. Please feel free to open issues if you have any problems.
licenseTools.ignoreProjects
is not supported. Because I couldn't imagine the usecase that we really want to ignore projects. The group/artifact ignore feature is enough.
Points
- Each line of
.artifactignore
are the same toskip
in license-tools-plugin skip
inartifact-definition.yml
is the same toforceGenerate
This plugin can manage local files as well. local-files
is the reserved group in artifact-definition.yml
.
local-files: # equivalent to group
- key: "<jar/aar filename (requires the extension)>"
...
...
...
You can exclude specific groups and/or artifacts through .artifactignore
file. .artifactignore
file is a list of Regexp that matches with <group>:<name>
.
Let's say you want to exclude com.example
group and io.github.jmatsu:example
artifact. Your ignore file should be like the following.
com.example:.*
io.github.jmatsu:example
Please note that this plugin will automatically add ^
and $
to each lines, so you must not add it in this ignore file.
For the more details, see example/app/license-list/.artifactignore.
For example wearApp
is an independent from implementation
etc. This plugin allows you to add such independent configurations to discovery targets. (No action is required if the variant's configurations extend the custom configurations.)
assembly {
targetConfigurations += "wearApp"
}
If you have created functionalImplementation
and <variant>FunctionalImplementation
for each variants, additionalScopes
will be your help.
assembly {
// Elements in additionalScopes will be used to build dynamic configurations with using targetConfigurations
// e.g. `functional` will be used to build `functionalImplementation`, `functionalTestImplementation` and so on
additionalScopes += "functional"
}
This plugin uses FreeMaker to generate HTML files and can accept an user-defined template like the following.
visualization {
// the name of the template file must be *license.html.ftl
htmlTemplateDir = file("customTemplateDir")
}
Please check the original ftl
file for variables that you can use.
You can generate resources in json format.
licenseList {
variants {
freeRelease {
visualization {
format = "json"
}
}
}
}
The schema of the json resources are defined in schema
module, which is published to jcenter.
repositories {
jcenter()
}
dependencies {
implementation("io.github.jmatsu:license-list-schema:<version>")
}
They are just interfaces in pure Kotlin. So you can chose any serialization method, custom attribute transformation, and so on in the both of Java and Kotlin.
- Only for Android application projects.
- I think Java project support should also be supported but not yet planned.
- Sharing configuration between variants
- Modification detection
The generated license URLs have been changed to show the contents correctly. Please run mergeLicenseList
and visualizeLicenseList
tasks to update your license catalog file and visualized file.
Breaking change1 :
inspect
action was introduced in 0.4
. It reports missing or misconfigured attributes in your management files. inspect
action does
- Recognize empty string and empty array as invalid values, and null as valid values.
- null was default values of
License#url
until0.3
. Since0.4
, "" (empty string) is a default value becauseinspection
should fail if no url is found in a pom file. Please modify null to "" in your management file if the null is not unintended to make it an inspection target. It's okay to leavenull
as it is if it's intended of course. - empty array was default values of
ArtifactDefinition#copyrightHolders
. It has not been changed in0.4
but empty array becomes one of invalid values. This meansinspect
will fail anyway. Please use null or remove the copyrightHolders field from your management file if the artifact really has no copyright holders.
- null was default values of
Breaking change2 :
- Now
visualize
action depends onvalidate
andinspect
actions. - Please pass
-PskipInspect=true
and/or-PskipValidate=true
unless necessary.
Deprecation:
artifactOutputDirectory
has been deprecated and renamed tobaseDir
Under MIT License.
Copyright 2020 Jumpei Matsuda (jmatsu)
- This plugin partially uses cookpad/license-tools-plugin's source code to support migration.
- The Gradle plugin design is inspired by Triple-T/gradle-play-publisher.