Skip to content

Commit

Permalink
Centralize dependency files for the common case.
Browse files Browse the repository at this point in the history
  • Loading branch information
autonomousapps committed Dec 5, 2023
1 parent 3f8c4cb commit 39e23ec
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 20 deletions.
12 changes: 7 additions & 5 deletions src/main/kotlin/com/autonomousapps/internal/OutputPaths.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@

package com.autonomousapps.internal

import com.autonomousapps.internal.OutputPaths.Companion.ROOT_DIR
import org.gradle.api.Project

internal const val ROOT_DIR = "reports/dependency-analysis"

internal class OutputPaths(
private val project: Project,
variantName: String
variantName: String,
) {

internal companion object {
const val ROOT_DIR = "reports/dependency-analysis"
}

private fun file(path: String) = project.layout.buildDirectory.file(path)
private fun dir(path: String) = project.layout.buildDirectory.dir(path)

private val variantDirectory = "$ROOT_DIR/$variantName"
private val intermediatesDir = "${variantDirectory}/intermediates"
Expand All @@ -34,7 +36,7 @@ internal class OutputPaths(
val declaredProcPath = file("${intermediatesDir}/procs-declared.json")
val abiAnalysisPath = file("${intermediatesDir}/abi.json")
val abiDumpPath = file("${variantDirectory}/abi-dump.txt")
val dependenciesDir = dir("${variantDirectory}/dependencies")
val dependencies = file("${variantDirectory}/dependencies.txt")
val explodedSourcePath = file("${intermediatesDir}/exploded-source.json")
val explodingBytecodePath = file("${intermediatesDir}/exploding-bytecode.json")
val syntheticProjectPath = file("${intermediatesDir}/synthetic-project.json")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ internal class AndroidLibAnalyzer(
): TaskProvider<AndroidScoreTask> {
return project.tasks.register<AndroidScoreTask>("computeAndroidScore$taskNameSuffix") {
dependencies.set(synthesizeDependenciesTask.flatMap { it.outputDir })
dependenciesList.set(synthesizeDependenciesTask.flatMap { it.output })
syntheticProject.set(synthesizeProjectViewTask.flatMap { it.output })
output.set(outputPaths.androidScorePath)
}
Expand Down
11 changes: 8 additions & 3 deletions src/main/kotlin/com/autonomousapps/model/ProjectVariant.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.autonomousapps.internal.utils.fromJson
import com.autonomousapps.model.CodeSource.Kind
import com.autonomousapps.model.declaration.Variant
import com.squareup.moshi.JsonClass
import com.squareup.moshi.JsonEncodingException
import org.gradle.api.file.Directory

/** Represents a variant-specific view of the project under analysis. */
Expand All @@ -20,7 +21,7 @@ data class ProjectVariant(
val sources: Set<Source>,
val classpath: Set<Coordinates>,
val annotationProcessors: Set<Coordinates>,
val testInstrumentationRunner: String?
val testInstrumentationRunner: String?,
) {

val usedClassesBySrc: Set<String> by unsafeLazy {
Expand Down Expand Up @@ -91,9 +92,13 @@ data class ProjectVariant(
.map {
val file = dependenciesDir.file(it.toFileName())
if (file.asFile.exists()) {
file.fromJson<Dependency>()
try {
file.fromJson<Dependency>()
} catch (e: JsonEncodingException) {
throw IllegalStateException("Couldn't deserialize '${file.asFile}'", e)
}
} else {
error("No file ${it.toFileName()}")
error("No file '${it.toFileName()}'")
}
}
.toSet()
Expand Down
12 changes: 11 additions & 1 deletion src/main/kotlin/com/autonomousapps/services/InMemoryCache.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
package com.autonomousapps.services

import com.autonomousapps.Flags.cacheSize
import com.autonomousapps.internal.OutputPaths.Companion.ROOT_DIR
import com.autonomousapps.model.InlineMemberCapability
import com.autonomousapps.model.intermediates.AnnotationProcessorDependency
import com.autonomousapps.model.intermediates.ExplodingJar
import com.autonomousapps.subplugin.DEPENDENCY_ANALYSIS_PLUGIN
import com.github.benmanes.caffeine.cache.Cache
import com.github.benmanes.caffeine.cache.Caffeine
import org.gradle.api.Project
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.invocation.Gradle
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
Expand All @@ -20,6 +22,7 @@ abstract class InMemoryCache : BuildService<InMemoryCache.Params> {

interface Params : BuildServiceParameters {
val cacheSize: Property<Long>
val dependenciesDir: DirectoryProperty
}

private val cacheSize = parameters.cacheSize.get()
Expand Down Expand Up @@ -50,7 +53,7 @@ abstract class InMemoryCache : BuildService<InMemoryCache.Params> {
procs.asMap().putIfAbsent(procName, proc)
}

companion object {
internal companion object {
private const val SHARED_SERVICES_IN_MEMORY_CACHE = "inMemoryCache"
private const val DEFAULT_CACHE_VALUE = -1L

Expand Down Expand Up @@ -89,6 +92,13 @@ abstract class InMemoryCache : BuildService<InMemoryCache.Params> {
.sharedServices
.registerIfAbsent(SHARED_SERVICES_IN_MEMORY_CACHE, InMemoryCache::class.java) {
parameters.cacheSize.set(project.cacheSize(DEFAULT_CACHE_VALUE))
parameters.dependenciesDir.set(project.layout.buildDirectory.dir("${ROOT_DIR}/dependencies"))

// TODO I wonder how this works in the context of a composite build. Maybe I should create a new service just
// for this, and _not_ share that service across builds?
if (project != project.rootProject) {
project.logger.warn("Creating global dependencies output directory in '${project.path}'")
}
}
}
}
8 changes: 6 additions & 2 deletions src/main/kotlin/com/autonomousapps/subplugin/ProjectPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,9 @@ internal class ProjectPlugin(private val project: Project) {

val synthesizeDependenciesTask =
tasks.register<SynthesizeDependenciesTask>("synthesizeDependencies$taskNameSuffix") {
inMemoryCache.set(InMemoryCache.register(project))
val cache = InMemoryCache.register(project)

inMemoryCache.set(cache)
projectPath.set(thisProjectPath)
compileDependencies.set(graphViewTask.flatMap { it.outputNodes })
physicalArtifacts.set(artifactsReport.flatMap { it.output })
Expand All @@ -661,7 +663,8 @@ internal class ProjectPlugin(private val project: Project) {
findNativeLibsTask?.let { task -> nativeLibs.set(task.flatMap { it.output }) }
findAndroidAssetsTask?.let { task -> androidAssets.set(task.flatMap { it.output }) }

outputDir.set(outputPaths.dependenciesDir)
outputDir.set(cache.flatMap { it.parameters.dependenciesDir })
output.set(outputPaths.dependencies)
}

/* ******************************
Expand Down Expand Up @@ -745,6 +748,7 @@ internal class ProjectPlugin(private val project: Project) {
graph.set(graphViewTask.flatMap { it.output })
declarations.set(findDeclarationsTask.flatMap { it.output })
dependencies.set(synthesizeDependenciesTask.flatMap { it.outputDir })
dependenciesList.set(synthesizeDependenciesTask.flatMap { it.output })
syntheticProject.set(synthesizeProjectViewTask.flatMap { it.output })
kapt.set(isKaptApplied())
output.set(outputPaths.dependencyTraceReportPath)
Expand Down
10 changes: 6 additions & 4 deletions src/main/kotlin/com/autonomousapps/subplugin/RootPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.autonomousapps.internal.advice.DslKind
import com.autonomousapps.internal.utils.log
import com.autonomousapps.model.declaration.Configurations.CONF_ADVICE_ALL_CONSUMER
import com.autonomousapps.model.declaration.Configurations.CONF_RESOLVED_DEPS_CONSUMER
import com.autonomousapps.services.InMemoryCache
import com.autonomousapps.tasks.BuildHealthTask
import com.autonomousapps.tasks.ComputeDuplicateDependenciesTask
import com.autonomousapps.tasks.GenerateBuildHealthTask
Expand All @@ -22,9 +23,7 @@ import org.gradle.kotlin.dsl.register

internal const val DEPENDENCY_ANALYSIS_PLUGIN = "com.autonomousapps.dependency-analysis"

/**
* This "plugin" is applied to the root project only.
*/
/** This "plugin" is applied to the root project only. */
internal class RootPlugin(private val project: Project) {

init {
Expand Down Expand Up @@ -67,7 +66,7 @@ internal class RootPlugin(private val project: Project) {
"You have ${FLAG_CLEAR_ARTIFACTS}=${clearArtifacts.get()} set. This flag does nothing; you should remove it."
)
}

val silentWarnings = providers.gradleProperty(FLAG_SILENT_WARNINGS)
if (silentWarnings.isPresent) {
logger.warn(
Expand All @@ -80,6 +79,9 @@ internal class RootPlugin(private val project: Project) {
private fun Project.configureRootProject() {
val paths = RootOutputPaths(this)

// Register this in the root project to centralize dependency synthesis files
InMemoryCache.register(this)

val computeDuplicatesTask = tasks.register<ComputeDuplicateDependenciesTask>("computeDuplicateDependencies") {
dependsOn(resolvedDepsConf)
resolvedDependenciesReports = resolvedDepsConf
Expand Down
10 changes: 8 additions & 2 deletions src/main/kotlin/com/autonomousapps/tasks/AndroidScoreTask.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,16 @@ abstract class AndroidScoreTask @Inject constructor(
@get:InputFile
abstract val syntheticProject: RegularFileProperty

@get:PathSensitive(PathSensitivity.NONE)
@get:InputDirectory
/**
* TODO: docs
*/
@get:Internal
abstract val dependencies: DirectoryProperty

@get:PathSensitive(PathSensitivity.NONE)
@get:InputFile
abstract val dependenciesList: RegularFileProperty

@get:OutputFile
abstract val output: RegularFileProperty

Expand Down
14 changes: 12 additions & 2 deletions src/main/kotlin/com/autonomousapps/tasks/ComputeUsagesTask.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,20 @@ abstract class ComputeUsagesTask @Inject constructor(
@get:InputFile
abstract val declarations: RegularFileProperty

@get:PathSensitive(PathSensitivity.NONE)
@get:InputDirectory
/**
* This contains all of the [Dependencies][Dependency] used by this project. It cannot be a task input because it is
* a globally shared directory that many tasks write to and read from. See also [dependenciesList].
*/
@get:Internal
abstract val dependencies: DirectoryProperty

/**
* Only for task snapshotting. A simplified representation of [dependencies].
*/
@get:PathSensitive(PathSensitivity.NONE)
@get:InputFile
abstract val dependenciesList: RegularFileProperty

@get:PathSensitive(PathSensitivity.NONE)
@get:InputFile
abstract val syntheticProject: RegularFileProperty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,14 @@ abstract class SynthesizeDependenciesTask @Inject constructor(
@get:InputFile
abstract val androidAssets: RegularFileProperty

// TODO: Maybe this should not be an OutputDirectory anymore, but just Internal? Since multiple tasks will write to it
@get:OutputDirectory
abstract val outputDir: DirectoryProperty

/** A simplified representation of [outputDir] for task snapshotting purposes only. */
@get:OutputFile
abstract val output: RegularFileProperty

@TaskAction fun action() {
workerExecutor.noIsolation().submit(SynthesizeDependenciesWorkAction::class.java) {
inMemoryCache.set(this@SynthesizeDependenciesTask.inMemoryCache)
Expand All @@ -98,6 +103,7 @@ abstract class SynthesizeDependenciesTask @Inject constructor(
nativeLibs.set(this@SynthesizeDependenciesTask.nativeLibs)
androidAssets.set(this@SynthesizeDependenciesTask.androidAssets)
outputDir.set(this@SynthesizeDependenciesTask.outputDir)
output.set(this@SynthesizeDependenciesTask.output)
}
}

Expand All @@ -117,6 +123,7 @@ abstract class SynthesizeDependenciesTask @Inject constructor(
val androidAssets: RegularFileProperty

val outputDir: DirectoryProperty
val output: RegularFileProperty
}

abstract class SynthesizeDependenciesWorkAction : WorkAction<SynthesizeDependenciesParameters> {
Expand All @@ -125,6 +132,7 @@ abstract class SynthesizeDependenciesTask @Inject constructor(

override fun execute() {
val outputDir = parameters.outputDir
val output = parameters.output.getAndDelete()

val dependencies = parameters.compileDependencies.fromJson<CoordinatesContainer>().coordinates
val physicalArtifacts = parameters.physicalArtifacts.fromJsonSet<PhysicalArtifact>()
Expand Down Expand Up @@ -182,7 +190,13 @@ abstract class SynthesizeDependenciesTask @Inject constructor(
.map { it.build() }
.forEach { dependency ->
val coordinates = dependency.coordinates
outputDir.file(coordinates.toFileName()).get().asFile.bufferWriteJson(dependency)
val file = outputDir.file(coordinates.toFileName()).get().asFile
if (!file.exists()) {
file.bufferWriteJson(dependency)
}

// This is the task output for snapshotting purposes
output.appendText("${coordinates.gav()}\n")
}
}

Expand Down

0 comments on commit 39e23ec

Please sign in to comment.