Skip to content

Commit ea78431

Browse files
Centralize dependency files for the common case.
1 parent 93f7c07 commit ea78431

File tree

9 files changed

+87
-33
lines changed

9 files changed

+87
-33
lines changed

src/main/kotlin/com/autonomousapps/internal/OutputPaths.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@
22

33
package com.autonomousapps.internal
44

5+
import com.autonomousapps.internal.OutputPaths.Companion.ROOT_DIR
56
import org.gradle.api.Project
67

7-
internal const val ROOT_DIR = "reports/dependency-analysis"
8-
98
internal class OutputPaths(
109
private val project: Project,
11-
variantName: String
10+
variantName: String,
1211
) {
1312

13+
internal companion object {
14+
const val ROOT_DIR = "reports/dependency-analysis"
15+
}
16+
1417
private fun file(path: String) = project.layout.buildDirectory.file(path)
15-
private fun dir(path: String) = project.layout.buildDirectory.dir(path)
1618

1719
private val variantDirectory = "$ROOT_DIR/$variantName"
1820
private val intermediatesDir = "${variantDirectory}/intermediates"
@@ -32,7 +34,7 @@ internal class OutputPaths(
3234
val declaredProcPath = file("${intermediatesDir}/procs-declared.json")
3335
val abiAnalysisPath = file("${intermediatesDir}/abi.json")
3436
val abiDumpPath = file("${variantDirectory}/abi-dump.txt")
35-
val dependenciesDir = dir("${variantDirectory}/dependencies")
37+
val dependencies = file("${variantDirectory}/dependencies.txt")
3638
val explodedSourcePath = file("${intermediatesDir}/exploded-source.json")
3739
val explodingBytecodePath = file("${intermediatesDir}/exploding-bytecode.json")
3840
val syntheticProjectPath = file("${intermediatesDir}/synthetic-project.json")

src/main/kotlin/com/autonomousapps/internal/analyzer/AndroidProjectAnalyzer.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ internal class AndroidLibAnalyzer(
265265
): TaskProvider<AndroidScoreTask> {
266266
return project.tasks.register<AndroidScoreTask>("computeAndroidScore$taskNameSuffix") {
267267
dependencies.set(synthesizeDependenciesTask.flatMap { it.outputDir })
268+
dependenciesList.set(synthesizeDependenciesTask.flatMap { it.output })
268269
syntheticProject.set(synthesizeProjectViewTask.flatMap { it.output })
269270
output.set(outputPaths.androidScorePath)
270271
}

src/main/kotlin/com/autonomousapps/model/ProjectVariant.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import com.autonomousapps.internal.utils.fromJson
77
import com.autonomousapps.model.CodeSource.Kind
88
import com.autonomousapps.model.declaration.Variant
99
import com.squareup.moshi.JsonClass
10+
import com.squareup.moshi.JsonEncodingException
1011
import org.gradle.api.file.Directory
1112

1213
/** Represents a variant-specific view of the project under analysis. */
@@ -19,7 +20,7 @@ data class ProjectVariant(
1920
val variant: Variant,
2021
val sources: Set<Source>,
2122
val classpath: Set<Coordinates>,
22-
val annotationProcessors: Set<Coordinates>
23+
val annotationProcessors: Set<Coordinates>,
2324
) {
2425

2526
val usedClassesBySrc: Set<String> by unsafeLazy {
@@ -90,9 +91,13 @@ data class ProjectVariant(
9091
.map {
9192
val file = dependenciesDir.file(it.toFileName())
9293
if (file.asFile.exists()) {
93-
file.fromJson<Dependency>()
94+
try {
95+
file.fromJson<Dependency>()
96+
} catch (e: JsonEncodingException) {
97+
throw IllegalStateException("Couldn't deserialize '${file.asFile}'", e)
98+
}
9499
} else {
95-
error("No file ${it.toFileName()}")
100+
error("No file '${it.toFileName()}'")
96101
}
97102
}
98103
.toSet()

src/main/kotlin/com/autonomousapps/services/InMemoryCache.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@
33
package com.autonomousapps.services
44

55
import com.autonomousapps.Flags.cacheSize
6+
import com.autonomousapps.internal.OutputPaths.Companion.ROOT_DIR
67
import com.autonomousapps.model.InlineMemberCapability
78
import com.autonomousapps.model.intermediates.AnnotationProcessorDependency
89
import com.autonomousapps.model.intermediates.ExplodingJar
910
import com.autonomousapps.subplugin.DEPENDENCY_ANALYSIS_PLUGIN
1011
import com.github.benmanes.caffeine.cache.Cache
1112
import com.github.benmanes.caffeine.cache.Caffeine
1213
import org.gradle.api.Project
14+
import org.gradle.api.file.DirectoryProperty
1315
import org.gradle.api.invocation.Gradle
1416
import org.gradle.api.provider.Property
1517
import org.gradle.api.provider.Provider
@@ -20,6 +22,7 @@ abstract class InMemoryCache : BuildService<InMemoryCache.Params> {
2022

2123
interface Params : BuildServiceParameters {
2224
val cacheSize: Property<Long>
25+
val dependenciesDir: DirectoryProperty
2326
}
2427

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

53-
companion object {
56+
internal companion object {
5457
private const val SHARED_SERVICES_IN_MEMORY_CACHE = "inMemoryCache"
5558
private const val DEFAULT_CACHE_VALUE = -1L
5659

@@ -89,6 +92,13 @@ abstract class InMemoryCache : BuildService<InMemoryCache.Params> {
8992
.sharedServices
9093
.registerIfAbsent(SHARED_SERVICES_IN_MEMORY_CACHE, InMemoryCache::class.java) {
9194
parameters.cacheSize.set(project.cacheSize(DEFAULT_CACHE_VALUE))
95+
parameters.dependenciesDir.set(project.layout.buildDirectory.dir("${ROOT_DIR}/dependencies"))
96+
97+
// TODO I wonder how this works in the context of a composite build. Maybe I should create a new service just
98+
// for this, and _not_ share that service across builds?
99+
if (project != project.rootProject) {
100+
project.logger.warn("Creating global dependencies output directory in '${project.path}'")
101+
}
92102
}
93103
}
94104
}

src/main/kotlin/com/autonomousapps/subplugin/ProjectPlugin.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,9 @@ internal class ProjectPlugin(private val project: Project) {
611611

612612
val synthesizeDependenciesTask =
613613
tasks.register<SynthesizeDependenciesTask>("synthesizeDependencies$taskNameSuffix") {
614-
inMemoryCache.set(InMemoryCache.register(project))
614+
val cache = InMemoryCache.register(project)
615+
616+
inMemoryCache.set(cache)
615617
projectPath.set(thisProjectPath)
616618
compileDependencies.set(graphViewTask.flatMap { it.outputNodes })
617619
physicalArtifacts.set(artifactsReportTask.flatMap { it.output })
@@ -625,7 +627,8 @@ internal class ProjectPlugin(private val project: Project) {
625627
findNativeLibsTask?.let { task -> nativeLibs.set(task.flatMap { it.output }) }
626628
findAndroidAssetsTask?.let { task -> androidAssets.set(task.flatMap { it.output }) }
627629

628-
outputDir.set(outputPaths.dependenciesDir)
630+
outputDir.set(cache.flatMap { it.parameters.dependenciesDir })
631+
output.set(outputPaths.dependencies)
629632
}
630633

631634
/* ******************************
@@ -707,6 +710,7 @@ internal class ProjectPlugin(private val project: Project) {
707710
graph.set(graphViewTask.flatMap { it.output })
708711
declarations.set(findDeclarationsTask.flatMap { it.output })
709712
dependencies.set(synthesizeDependenciesTask.flatMap { it.outputDir })
713+
dependenciesList.set(synthesizeDependenciesTask.flatMap { it.output })
710714
syntheticProject.set(synthesizeProjectViewTask.flatMap { it.output })
711715
kapt.set(isKaptApplied())
712716
output.set(outputPaths.dependencyTraceReportPath)

src/main/kotlin/com/autonomousapps/subplugin/RootPlugin.kt

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import com.autonomousapps.internal.advice.DslKind
99
import com.autonomousapps.internal.utils.log
1010
import com.autonomousapps.model.declaration.Configurations.CONF_ADVICE_ALL_CONSUMER
1111
import com.autonomousapps.model.declaration.Configurations.CONF_RESOLVED_DEPS_CONSUMER
12+
import com.autonomousapps.services.InMemoryCache
1213
import com.autonomousapps.tasks.BuildHealthTask
1314
import com.autonomousapps.tasks.ComputeDuplicateDependenciesTask
1415
import com.autonomousapps.tasks.GenerateBuildHealthTask
@@ -20,9 +21,7 @@ import org.gradle.kotlin.dsl.register
2021

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

23-
/**
24-
* This "plugin" is applied to the root project only.
25-
*/
24+
/** This "plugin" is applied to the root project only. */
2625
internal class RootPlugin(private val project: Project) {
2726

2827
init {
@@ -42,24 +41,13 @@ internal class RootPlugin(private val project: Project) {
4241
conditionallyApplyToSubprojects()
4342
}
4443

45-
/** Only apply to all subprojects if user hasn't requested otherwise. See [shouldAutoApply]. */
46-
private fun Project.conditionallyApplyToSubprojects() {
47-
if (!shouldAutoApply()) {
48-
logger.debug("Not applying plugin to all subprojects. User must apply to each manually")
49-
return
50-
}
51-
52-
logger.debug("Applying plugin to all subprojects")
53-
subprojects {
54-
logger.debug("Auto-applying to $path.")
55-
apply(plugin = DEPENDENCY_ANALYSIS_PLUGIN)
56-
}
57-
}
58-
5944
/** Root project. Configures lifecycle tasks that aggregates reports across all subprojects. */
6045
private fun Project.configureRootProject() {
6146
val paths = RootOutputPaths(this)
6247

48+
// Register this in the root project to centralize dependency synthesis files
49+
InMemoryCache.register(this)
50+
6351
val computeDuplicatesTask = tasks.register<ComputeDuplicateDependenciesTask>("computeDuplicateDependencies") {
6452
dependsOn(resolvedDepsConf)
6553
resolvedDependenciesReports = resolvedDepsConf
@@ -88,6 +76,20 @@ internal class RootPlugin(private val project: Project) {
8876
}
8977
}
9078

79+
/** Only apply to all subprojects if user hasn't requested otherwise. See [shouldAutoApply]. */
80+
private fun Project.conditionallyApplyToSubprojects() {
81+
if (!shouldAutoApply()) {
82+
logger.debug("Not applying plugin to all subprojects. User must apply to each manually")
83+
return
84+
}
85+
86+
logger.debug("Applying plugin to all subprojects")
87+
subprojects {
88+
logger.debug("Auto-applying to $path.")
89+
apply(plugin = DEPENDENCY_ANALYSIS_PLUGIN)
90+
}
91+
}
92+
9193
private fun Project.createResolvableConfiguration(confName: String): Configuration =
9294
configurations.create(confName) {
9395
isVisible = false

src/main/kotlin/com/autonomousapps/tasks/AndroidScoreTask.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,16 @@ abstract class AndroidScoreTask @Inject constructor(
2929
@get:InputFile
3030
abstract val syntheticProject: RegularFileProperty
3131

32-
@get:PathSensitive(PathSensitivity.NONE)
33-
@get:InputDirectory
32+
/**
33+
* TODO: docs
34+
*/
35+
@get:Internal
3436
abstract val dependencies: DirectoryProperty
3537

38+
@get:PathSensitive(PathSensitivity.NONE)
39+
@get:InputFile
40+
abstract val dependenciesList: RegularFileProperty
41+
3642
@get:OutputFile
3743
abstract val output: RegularFileProperty
3844

src/main/kotlin/com/autonomousapps/tasks/ComputeUsagesTask.kt

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,20 @@ abstract class ComputeUsagesTask @Inject constructor(
3838
@get:InputFile
3939
abstract val declarations: RegularFileProperty
4040

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

48+
/**
49+
* Only for task snapshotting. A simplified representation of [dependencies].
50+
*/
51+
@get:PathSensitive(PathSensitivity.NONE)
52+
@get:InputFile
53+
abstract val dependenciesList: RegularFileProperty
54+
4555
@get:PathSensitive(PathSensitivity.NONE)
4656
@get:InputFile
4757
abstract val syntheticProject: RegularFileProperty

src/main/kotlin/com/autonomousapps/tasks/SynthesizeDependenciesTask.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,14 @@ abstract class SynthesizeDependenciesTask @Inject constructor(
8181
@get:InputFile
8282
abstract val androidAssets: RegularFileProperty
8383

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

88+
/** A simplified representation of [outputDir] for task snapshotting purposes only. */
89+
@get:OutputFile
90+
abstract val output: RegularFileProperty
91+
8792
@TaskAction fun action() {
8893
workerExecutor.noIsolation().submit(SynthesizeDependenciesWorkAction::class.java) {
8994
inMemoryCache.set(this@SynthesizeDependenciesTask.inMemoryCache)
@@ -98,6 +103,7 @@ abstract class SynthesizeDependenciesTask @Inject constructor(
98103
nativeLibs.set(this@SynthesizeDependenciesTask.nativeLibs)
99104
androidAssets.set(this@SynthesizeDependenciesTask.androidAssets)
100105
outputDir.set(this@SynthesizeDependenciesTask.outputDir)
106+
output.set(this@SynthesizeDependenciesTask.output)
101107
}
102108
}
103109

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

119125
val outputDir: DirectoryProperty
126+
val output: RegularFileProperty
120127
}
121128

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

126133
override fun execute() {
127134
val outputDir = parameters.outputDir
135+
val output = parameters.output.getAndDelete()
128136

129137
val dependencies = parameters.compileDependencies.fromJson<CoordinatesContainer>().coordinates
130138
val physicalArtifacts = parameters.physicalArtifacts.fromJsonSet<PhysicalArtifact>()
@@ -182,7 +190,13 @@ abstract class SynthesizeDependenciesTask @Inject constructor(
182190
.map { it.build() }
183191
.forEach { dependency ->
184192
val coordinates = dependency.coordinates
185-
outputDir.file(coordinates.toFileName()).get().asFile.bufferWriteJson(dependency)
193+
val file = outputDir.file(coordinates.toFileName()).get().asFile
194+
if (!file.exists()) {
195+
file.bufferWriteJson(dependency)
196+
}
197+
198+
// This is the task output for snapshotting purposes
199+
output.appendText("${coordinates.gav()}\n")
186200
}
187201
}
188202

0 commit comments

Comments
 (0)