I want to automate inclusion of the latest generated third party licenses in Gradle.
Config:
- Gradle 2.x
- license-gradle-plugin 0.11.0
Code:
task beforeAssemble(dependsOn: assemble) << {
downloadLicenses.execute()
CopyToAssetsTask.execute()
}
task CopyToAssetsTask(type: Copy) {
description = 'Copies generated Third Party Licenses into assets'
from('$buildDir/reports/license') {
include('dependency-license.html')
}
into '$buildDir/intermediates/assets/debug/legal'
}
apply plugin: 'license'
downloadLicenses {
includeProjectDependencies = true
reportByDependency = true
reportByLicenseType = true
dependencyConfiguration = "compile"
}
In command line:
gradlew clean assembleDebug
The resulting APK does not include the generated file as I was hoping. I'm quite new to Gradle so maybe there is a simple explanation?
First some observations. The solution is at the end:
- You are still thinking procedurally: Telling Gradle what to do when (i.e. what you do in task
beforeAssemble
). Make use of the task graph: Specify what the dependencies of a task are (see below for some of the possibilities). When you need the output of a task, just ask Gradle to execute that task, and Gradle will figure out the transitive tasks that that task depends on. It will execute all of those tasks: only once, and in the correct order.
- This declaration:
task beforeAssemble(dependsOn: assemble)
, does not make sense. You want the task to run before assemble
, but by depending on assemble
you achieved the reverse: assemble
will be run before beforeAssemble
.
How to specify dependencies? There are multiple options:
- Using a direct dependency:
dependsOn
.
- Referring to other tasks in the
inputs
of a task.
- Setting the options of a task, which will automatically create a dependency. For example: If the
from
attribute of the Copy
task is set to the outputs of another task, the Copy
task will automatically add that other task as an input.
Here is the solution. You want two achieve two things:
- Generate the license information during the build (at some particular point).
- Include the license information in the archive(s).
Add this to your build script:
android {
// ...
// Add the output folder of the license plug-in as
// a source folder for resources.
sourceSets {
main {
resources {
srcDir 'build/reports/license'
}
}
}
}
downloadLicenses {
includeProjectDependencies = true
reportByDependency = true
reportByLicenseType = true
dependencyConfiguration = "compile"
}
// Add a dependency after the project has been evaluated, because
// the Android plug-in does not add tasks "generate*Resources" to
// the project immediately.
project.afterEvaluate {
// Download the licenses when (actually: just before) the
// resources are generated (for both the "debug" and the
// "release" build types).
// If you add/change build types, you have to add to/change
// these task names.
generateDebugResources.dependsOn tasks['downloadLicenses']
generateReleaseResources.dependsOn tasks['downloadLicenses']
}
In my project (gradle 3.4.1), it works like this in the Android "Module:app" gradle file:
plugins {
id "com.github.hierynomus.license" version "0.14.0"
}
license {
include "**/*.java"
strictCheck = false
ignoreFailures = true
skipExistingHeaders = true
}
downloadLicenses {
includeProjectDependencies = true
reportByDependency = true
reportByLicenseType = false
dependencyConfiguration = "compile"
licenses = [
(group('com.android.support')) : license('Apache License, Version 2.0', 'http://www.apache.org/licenses/LICENSE-2.0'),
(group('com.android.support.constraint')) : license('Apache License, Version 2.0', 'http://www.apache.org/licenses/LICENSE-2.0'),
(group('com.google.firebase')) : license('Apache License, Version 2.0', 'http://www.apache.org/licenses/LICENSE-2.0'),
(group('com.google.android')) : license('Apache License, Version 2.0', 'http://www.apache.org/licenses/LICENSE-2.0'),
(group('com.google.android.gms')) : license('Apache License, Version 2.0', 'http://www.apache.org/licenses/LICENSE-2.0')
]
}
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
...
}
sourceSets {
main {
assets.srcDirs = ['src/main/assets', 'build/licenses/']
}
}
buildTypes {
...
}
}
dependencies {
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:multidex:1.0.1'
compile 'com.android.support:support-v4:25.3.1'
compile 'com.android.support:design:25.3.1'
...
}
task copyLicenseReport(type: Copy) {
from('build/reports/license') {
include '**/*.html'
include '**/*.xml'
}
into 'build/licenses/thirdPartyLicenses'
}
project.afterEvaluate {
copyLicenseReport.dependsOn project.tasks.getByName('downloadLicenses')
preBuild.dependsOn copyLicenseReport
}
apply plugin: 'com.google.gms.google-services'
Try on changing CopyToAssetsTask
into:
task CopyToAssetsTask << {
copy {
description = 'Copies generated Third Party Licenses into assets'
from('$buildDir/reports/license') {
include('dependency-license.html')
}
into '$buildDir/intermediates/assets/debug/legal'
}
}
because right now, your copying is done in configuration phase.
This solution worked for me and is a slightly modified version of the answer that Johan Stuyts posted.
One limitation though: The generated report will end up in the root assets folder instead of the intended subfolder "legal".
buildscript {
// ...
dependencies {
// ...
classpath 'nl.javadude.gradle.plugins:license-gradle-plugin:0.11.0'
}
}
android {
// ...
// Add the output folder of the license plug-in as
// a source folder for assets.
sourceSets {
main {
// ...
assets.srcDirs = ['src/main/assets', 'build/reports/license']
}
}
}
downloadLicenses {
includeProjectDependencies = true
reportByDependency = true
reportByLicenseType = false
report.html.enabled = true
report.xml.enabled = false
dependencyConfiguration = "compile"
}
// Add a dependency after the project has been evaluated, because
// the Android plug-in does not add tasks "merge*Assets" to
// the project immediately.
project.afterEvaluate {
// Download the licenses when (actually: just before) the
// assets are merged (for both the "debug" and the
// "release" build types).
// If you add/change build types, you have to add to/change
// these task names.
mergeDebugAssets.dependsOn project.tasks.getByName('downloadLicenses')
mergeReleaseAssets.dependsOn project.tasks.getByName('downloadLicenses')
}