blob: bbbeffc6c7119d8a66d4dfe0661bf5b17d905d11 [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 com.jakewharton.dex.DexParser.Companion.toDexParser
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.provider.Property
import org.gradle.api.tasks.CacheableTask
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.TaskProvider
import org.json.simple.JSONObject
import java.io.File
private const val BYTECODE_SIZE = "bytecode_size"
private const val METHOD_COUNT = "method_count"
private const val METRICS_DIRECTORY = "librarymetrics"
private const val JSON_FILE_EXTENSION = ".json"
private const val JAR_FILE_EXTENSION = ".jar"
private const val LINT_JAR = "lint$JAR_FILE_EXTENSION"
@CacheableTask
abstract class ReportLibraryMetricsTask : DefaultTask() {
init {
group = "LibraryMetrics"
description = "Task for reporting build time library metrics. Currently gathers .aar sizes."
}
/**
* The variants we are interested in gathering metrics for.
*/
@get:[InputFiles PathSensitive(PathSensitivity.RELATIVE)]
abstract val jarFiles: ConfigurableFileCollection
@get:OutputFile
abstract val outputFile: Property<File>
@TaskAction
fun reportLibraryMetrics() {
val file = outputFile.get()
file.parentFile.mkdirs()
val json = JSONObject()
val jarFiles = getJarFiles()
val bytecodeSize = getBytecodeSize(jarFiles)
if (bytecodeSize > 0L) {
json[BYTECODE_SIZE] = bytecodeSize
}
val methodCount = getMethodCount(jarFiles)
if (methodCount > 0) {
json[METHOD_COUNT] = methodCount
}
file.writeText(json.toJSONString())
}
private fun getJarFiles(): List<File> {
return jarFiles.files.filter { file ->
file.name.endsWith(JAR_FILE_EXTENSION) &&
// AARs bundle a `lint.jar` that contains lint checks published by the library -
// this isn't runtime code and is not part of the actual library, so ignore it.
file.name != LINT_JAR
}
}
private fun getBytecodeSize(jarFiles: List<File>): Long {
return jarFiles.map { it.length() }.sum()
}
private fun getMethodCount(jarFiles: List<File>): Int {
return when {
jarFiles.isEmpty() -> 0
jarFiles.all { it.isFile } -> jarFiles.toDexParser().listMethods().size
else ->
throw IllegalStateException("One or more of the items in $jarFiles is not a file.")
}
}
}
fun Project.configureReportLibraryMetricsTask(): TaskProvider<ReportLibraryMetricsTask> {
val task = tasks.register(
AndroidXPlugin.REPORT_LIBRARY_METRICS_TASK,
ReportLibraryMetricsTask::class.java
)
task.configure {
val outputDir = File(project.rootProject.getDistributionDirectory(), METRICS_DIRECTORY)
it.outputFile.set(
task.map {
File(outputDir, "${project.group}_${project.name}$JSON_FILE_EXTENSION")
}
)
}
return task
}