Skip to content

Commit

Permalink
Only resolve external dependencies. More performant.
Browse files Browse the repository at this point in the history
  • Loading branch information
autonomousapps committed Aug 23, 2022
1 parent 824d18a commit 074b0a3
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 20 deletions.
1 change: 1 addition & 0 deletions src/main/kotlin/com/autonomousapps/internal/OutputPaths.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ internal class OutputPaths(

val artifactsPath = file("${intermediatesDir}/artifacts.json")
val artifactsPrettyPath = file("${intermediatesDir}/artifacts-pretty.json")
val externalDependenciesPath = file("${intermediatesDir}/external-dependencies.txt")
val allDeclaredDepsPath = file("${intermediatesDir}/all-declared-dependencies.json")
val allDeclaredDepsPrettyPath = file("${intermediatesDir}/all-declared-dependencies-pretty.json")
val inlineUsagePath = file("${intermediatesDir}/inline-usage.json")
Expand Down
10 changes: 10 additions & 0 deletions src/main/kotlin/com/autonomousapps/internal/artifactViews.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.autonomousapps.internal
import org.gradle.api.artifacts.ArtifactCollection
import org.gradle.api.artifacts.ArtifactView
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.component.ModuleComponentIdentifier
import org.gradle.api.artifacts.result.ResolvedDependencyResult
import org.gradle.api.attributes.Attribute
import org.gradle.api.attributes.Category
Expand All @@ -22,6 +23,15 @@ private fun Configuration.artifactViewFor(attrValue: String): ArtifactView = inc
lenient(true)
}

internal fun Configuration.externalArtifactsFor(attrValue: String): ArtifactCollection = externalArtifactViewFor(attrValue).artifacts

private fun Configuration.externalArtifactViewFor(attrValue: String): ArtifactView = incoming.artifactView {
attributes.attribute(attributeKey, attrValue)
lenient(true)
// Only resolve external dependencies! Without this, all project dependencies will get _compiled_.
componentFilter { id -> id is ModuleComponentIdentifier }
}

/**
* Returns true if any of the variants are a kind of platform.
*/
Expand Down
6 changes: 3 additions & 3 deletions src/main/kotlin/com/autonomousapps/internal/utils/utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ internal inline fun <reified T> RegularFileProperty.fromNullableJsonSet(): Set<T
return orNull?.asFile?.readText()?.fromJsonSet()
}

internal fun RegularFileProperty.readLines(): List<String> {
return get().asFile.readLines()
}
internal fun RegularFileProperty.readLines(): List<String> = get().readLines()

internal fun RegularFile.readLines(): List<String> = asFile.readLines()

internal fun RegularFileProperty.readText(): String = get().asFile.readText()

Expand Down
14 changes: 12 additions & 2 deletions src/main/kotlin/com/autonomousapps/subplugin/ProjectPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -497,9 +497,19 @@ internal class ProjectPlugin(private val project: Project) {
outputRuntimeDot.set(outputPaths.runtimeGraphDotPath)
}

val resolveExternalDependencies =
tasks.register<ResolveExternalDependenciesTask>("resolveExternalDependencies$taskNameSuffix") {
configureTask(
project = this@analyzeDependencies,
compileClasspath = configurations[dependencyAnalyzer.compileConfigurationName],
runtimeClasspath = configurations[dependencyAnalyzer.runtimeConfigurationName],
jarAttr = dependencyAnalyzer.attributeValueJar
)
output.set(outputPaths.externalDependenciesPath)
}

computeResolvedDependenciesTask.configure {
dependencyGraphViews.add(graphViewTask.flatMap { it.output })
dependencyGraphViews.add(graphViewTask.flatMap { it.outputRuntime })
externalDependencies.add(resolveExternalDependencies.flatMap { it.output })
}

val computeDominatorTask = tasks.register<ComputeDominatorTreeTask>("computeDominatorTree$taskNameSuffix") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ abstract class ComputeDuplicateDependenciesTask : DefaultTask() {
@TaskAction fun action() {
val output = output.getAndDelete()

val map = mutableMapOf<String, SortedSet<String>>()
val map = sortedMapOf<String, SortedSet<String>>()

resolvedDependenciesReports.dependencies.asSequence()
// They should all be project dependencies, but
Expand All @@ -60,6 +60,7 @@ abstract class ComputeDuplicateDependenciesTask : DefaultTask() {
}
}

output.writeText(map.toJson())
// map.toMap() because we can't serialize a SortedMap
output.writeText(map.toMap().toJson())
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package com.autonomousapps.tasks

import com.autonomousapps.TASK_GROUP_DEP_INTERNAL
import com.autonomousapps.internal.utils.flatMapToOrderedSet
import com.autonomousapps.internal.utils.fromJson
import com.autonomousapps.internal.utils.getAndDelete
import com.autonomousapps.model.DependencyGraphView
import com.autonomousapps.internal.utils.readLines
import com.autonomousapps.model.Coordinates
import com.autonomousapps.model.ModuleCoordinates
import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFile
Expand All @@ -22,22 +21,22 @@ abstract class ComputeResolvedDependenciesTask : DefaultTask() {

@get:PathSensitive(PathSensitivity.RELATIVE)
@get:InputFiles
abstract val dependencyGraphViews: ListProperty<RegularFile>
abstract val externalDependencies: ListProperty<RegularFile>

@get:OutputFile
abstract val output: RegularFileProperty

@TaskAction fun action() {
val output = output.getAndDelete()

// TODO figure out data structure
val dependencyGraph = dependencyGraphViews.get()
.map { it.fromJson<DependencyGraphView>() }
.associateBy { "${it.name},${it.configurationName}" }
val dependencies = dependencyGraph.values
val dependencies: Set<ModuleCoordinates> = externalDependencies.get()
.asSequence()
.flatMap { it.nodes }
.filterIsInstance<ModuleCoordinates>()
.flatMap { it.readLines() }
.map {
val external = Coordinates.of(it)
check(external is ModuleCoordinates) { "ModuleCoordinates expected. Was $it." }
external
}
.toSortedSet()

output.writeText(dependencies.joinToString(separator = "\n") { it.gav() })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ abstract class PrintDuplicateDependenciesTask : DefaultTask() {
val report = duplicateDependenciesReport.fromJsonMapSet<String, String>()
val total = report.size
val sum = report.values.sumOf { it.size }
val duplicates = report.filter { it.value.size > 1 }
val duplicates = report.filterTo(sortedMapOf()) { it.value.size > 1 }
val duplicateCount = duplicates.size

val output = buildString {
Expand All @@ -35,7 +35,7 @@ abstract class PrintDuplicateDependenciesTask : DefaultTask() {
} else {
appendLine(" These are:")
duplicates.forEach { (id, versions) ->
appendLine("* $id:${versions.joinToString(separator = ",", prefix = "{", postfix = "}")}")
appendLine("* $id:${versions.sorted().joinToString(separator = ",", prefix = "{", postfix = "}")}")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.autonomousapps.tasks

import com.autonomousapps.TASK_GROUP_DEP_INTERNAL
import com.autonomousapps.internal.GradleVersions
import com.autonomousapps.internal.externalArtifactsFor
import com.autonomousapps.internal.graph.GraphViewBuilder
import com.autonomousapps.internal.utils.getAndDelete
import com.autonomousapps.model.ModuleCoordinates
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.*

@Suppress("UnstableApiUsage") // Guava graphs
@CacheableTask
abstract class ResolveExternalDependenciesTask : DefaultTask() {

init {
group = TASK_GROUP_DEP_INTERNAL
description = "Resolves external dependencies for single variant."

if (GradleVersions.isAtLeastGradle74) {
@Suppress("LeakingThis")
notCompatibleWithConfigurationCache("Cannot serialize Configurations")
}
}

@Transient
private lateinit var compileClasspath: Configuration

@Transient
private lateinit var runtimeClasspath: Configuration

@get:PathSensitive(PathSensitivity.NAME_ONLY)
@get:InputFiles
abstract val compileFiles: ConfigurableFileCollection

@get:PathSensitive(PathSensitivity.NAME_ONLY)
@get:InputFiles
abstract val runtimeFiles: ConfigurableFileCollection

/** Output in json format for compile classpath graph. */
@get:OutputFile
abstract val output: RegularFileProperty

internal fun configureTask(
project: Project,
compileClasspath: Configuration,
runtimeClasspath: Configuration,
jarAttr: String
) {
this.compileClasspath = compileClasspath
this.runtimeClasspath = runtimeClasspath
compileFiles.setFrom(project.provider { compileClasspath.externalArtifactsFor(jarAttr).artifactFiles })
runtimeFiles.setFrom(project.provider { runtimeClasspath.externalArtifactsFor(jarAttr).artifactFiles })
}

@TaskAction fun action() {
val output = output.getAndDelete()

val compileGraph = GraphViewBuilder(compileClasspath).graph
val runtimeGraph = GraphViewBuilder(runtimeClasspath).graph

val dependencies = compileGraph.nodes().asSequence().plus(runtimeGraph.nodes().asSequence())
.filterIsInstance<ModuleCoordinates>()
.toSortedSet()

output.writeText(dependencies.joinToString(separator = "\n") { it.gav() })
}
}

0 comments on commit 074b0a3

Please sign in to comment.