Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Centralize dependency files for the common case. #1004

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 @@ -4,17 +4,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 @@ -37,7 +39,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 @@ -220,6 +220,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 @@ -9,6 +9,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 @@ -22,7 +23,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 @@ -93,9 +94,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 @@ -5,6 +5,7 @@
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
Expand All @@ -13,6 +14,7 @@ import com.autonomousapps.tasks.KotlinCapabilities
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 @@ -23,6 +25,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 @@ -53,7 +56,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 @@ -92,6 +95,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 @@ -671,7 +671,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 @@ -686,7 +688,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 @@ -770,6 +773,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
8 changes: 5 additions & 3 deletions src/main/kotlin/com/autonomousapps/subplugin/RootPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import com.autonomousapps.internal.advice.DslKind
import com.autonomousapps.internal.artifacts.DagpArtifacts
import com.autonomousapps.internal.artifacts.Resolver.Companion.interProjectResolver
import com.autonomousapps.internal.utils.log
import com.autonomousapps.services.InMemoryCache
import com.autonomousapps.tasks.BuildHealthTask
import com.autonomousapps.tasks.ComputeDuplicateDependenciesTask
import com.autonomousapps.tasks.GenerateBuildHealthTask
Expand All @@ -23,9 +24,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 @@ -87,6 +86,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") {
resolvedDependenciesReports.setFrom(resolvedDepsResolver.internal)
output.set(paths.duplicateDependenciesPath)
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 @@ -31,10 +31,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 @@ -40,10 +40,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 @@ -87,9 +87,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 @@ -105,6 +110,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 @@ -125,6 +131,7 @@ abstract class SynthesizeDependenciesTask @Inject constructor(
val androidAssets: RegularFileProperty

val outputDir: DirectoryProperty
val output: RegularFileProperty
}

abstract class SynthesizeDependenciesWorkAction : WorkAction<SynthesizeDependenciesParameters> {
Expand All @@ -133,6 +140,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 @@ -192,7 +200,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