blob: 52c490c1d09c59cfab1a51eb3d9381b4c0fa196c [file] [log] [blame]
/*
* Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.build
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import java.io.File
/**
* Finds the outputs of every task and saves this mapping into a file
*/
abstract class ListTaskOutputsTask() : DefaultTask() {
@OutputFile
val outputFile: Property<File> = project.objects.property(File::class.java)
@Input
val removePrefixes: MutableList<String> = mutableListOf()
@Input
val tasks: MutableList<Task> = mutableListOf()
init {
group = "Help"
outputs.upToDateWhen { false }
}
fun setOutput(f: File) {
outputFile.set(f)
description = "Finds the outputs of every task and saves the resulting mapping into $f"
}
fun removePrefix(prefix: String) {
removePrefixes.add(prefix + "/")
}
fun format(tasksByOutput: Map<File, Task>): String {
val messages: MutableList<String> = mutableListOf()
for ((output, task) in tasksByOutput) {
var filePath = output.path
for (prefix in removePrefixes) {
filePath = filePath.removePrefix(prefix)
}
val keyLength = filePath.length.toInt()
val roundedKeyLength = ((keyLength / 32) + 1) * 32
val extraSpaces = " ".repeat(roundedKeyLength - keyLength)
messages.add("$filePath $extraSpaces - ${task.path}")
}
messages.sort()
val text = messages.joinToString("\n")
return text
}
@TaskAction
fun exec() {
val tasksByOutput = project.rootProject.findAllTasksByOutput()
val text = format(tasksByOutput)
val outputFile = outputFile.get()
outputFile.writeText(text)
logger.lifecycle("Wrote ${outputFile.path}")
}
}
// TODO(149103692): remove all elements of this set
val taskNamesKnownToDuplicateOutputs = setOf(
"buildOnServer",
"dist",
"generateReleaseNotes",
"jarRelease",
"jarDebug",
"kotlinSourcesJar",
"lint",
"lintFix",
"lintVital",
"sourceJar",
"zipResultsOfJvmTest",
"zipResultsOfTestDebugUnitTest",
"zipResultsOfTestReleaseUnitTest",
"zipResultsOfTestTipOfTreeDebugUnitTest",
"zipResultsOfTestTipOfTreeReleaseUnitTest",
"zipResultsOfTestPublicDebugUnitTest",
"zipResultsOfTestPublicReleaseUnitTest"
)
// For this project and all subprojects, collects all tasks and creates a map keyed by their output files
fun Project.findAllTasksByOutput(): Map<File, Task> {
// find list of all tasks
val allTasks = mutableListOf<Task>()
project.allprojects { otherProject ->
otherProject.tasks.all { task ->
allTasks.add(task)
}
}
// group tasks by their outputs
val tasksByOutput: MutableMap<File, Task> = hashMapOf()
for (otherTask in allTasks) {
for (otherTaskOutput in otherTask.outputs.files.files) {
val existingTask = tasksByOutput[otherTaskOutput]
if (existingTask != null) {
if (!taskNamesKnownToDuplicateOutputs.contains(otherTask.name) ||
!taskNamesKnownToDuplicateOutputs.contains(existingTask.name)) {
throw GradleException("Output file " + otherTaskOutput +
" was declared as an output of multiple tasks: " + otherTask + " and " +
existingTask)
}
}
tasksByOutput.put(otherTaskOutput, otherTask)
}
}
return tasksByOutput
}