Added dependency scanning, added default runtime configurations
This commit is contained in:
parent
fe6051c8f4
commit
8cf9f90805
102
src/dorkbox/gradle/DependencyScanner.kt
Normal file
102
src/dorkbox/gradle/DependencyScanner.kt
Normal file
@ -0,0 +1,102 @@
|
||||
package dorkbox.gradle
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.ResolvedArtifact
|
||||
import org.gradle.api.artifacts.ResolvedDependency
|
||||
import java.io.File
|
||||
|
||||
object DependencyScanner {
|
||||
|
||||
/**
|
||||
* THIS MUST BE IN "afterEvaluate" or run from a specific task.
|
||||
*/
|
||||
fun scan(project: Project,
|
||||
configurationName: String,
|
||||
projectDependencies: MutableList<Dependency>,
|
||||
existingNames: MutableSet<String>): MutableList<Dependency> {
|
||||
|
||||
project.configurations.getByName(configurationName).resolvedConfiguration.firstLevelModuleDependencies.forEach { dep ->
|
||||
// we know the FIRST series will exist
|
||||
val makeDepTree = makeDepTree(dep, existingNames)
|
||||
if (makeDepTree != null) {
|
||||
// it's only null if we've ALREADY scanned it
|
||||
projectDependencies.add(makeDepTree)
|
||||
}
|
||||
}
|
||||
|
||||
return projectDependencies
|
||||
}
|
||||
|
||||
|
||||
|
||||
// how to resolve dependencies
|
||||
// NOTE: it is possible, when we have a project DEPEND on an older version of that project (ie: bootstrapped from an older version)
|
||||
// we can have infinite recursion.
|
||||
// This is a problem, so we limit how much a dependency can show up the the tree
|
||||
private fun makeDepTree(dep: ResolvedDependency, existingNames: MutableSet<String>): Dependency? {
|
||||
val module = dep.module.id
|
||||
val group = module.group
|
||||
val name = module.name
|
||||
val version = module.version
|
||||
|
||||
if (!existingNames.contains("$group:$name")) {
|
||||
// println("Searching: $group:$name:$version")
|
||||
val artifacts: List<DependencyInfo> = dep.moduleArtifacts.map { artifact: ResolvedArtifact ->
|
||||
val artifactModule = artifact.moduleVersion.id
|
||||
DependencyInfo(artifactModule.group, artifactModule.name, artifactModule.version, artifact.file.absoluteFile)
|
||||
}
|
||||
|
||||
val children = mutableListOf<Dependency>()
|
||||
dep.children.forEach {
|
||||
existingNames.add("$group:$name")
|
||||
val makeDep = makeDepTree(it, existingNames)
|
||||
if (makeDep != null) {
|
||||
children.add(makeDep)
|
||||
}
|
||||
}
|
||||
|
||||
return Dependency(group, name, version, artifacts, children.toList())
|
||||
}
|
||||
|
||||
// we already have this dependency in our chain.
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten the dependency children
|
||||
*/
|
||||
fun flattenDeps(dep: Dependency): List<Dependency> {
|
||||
val flatDeps = mutableSetOf<Dependency>()
|
||||
flattenDep(dep, flatDeps)
|
||||
return flatDeps.toList()
|
||||
}
|
||||
|
||||
private fun flattenDep(dep: Dependency, flatDeps: MutableSet<Dependency>) {
|
||||
flatDeps.add(dep)
|
||||
dep.children.forEach {
|
||||
flattenDep(it, flatDeps)
|
||||
}
|
||||
}
|
||||
|
||||
data class Dependency(val group: String,
|
||||
val name: String,
|
||||
val version: String,
|
||||
val artifacts: List<DependencyInfo>,
|
||||
val children: List<Dependency>) {
|
||||
|
||||
fun mavenId(): String {
|
||||
return "$group:$name:$version"
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return mavenId()
|
||||
}
|
||||
}
|
||||
|
||||
data class DependencyInfo(val group: String, val name: String, val version: String, val file: File) {
|
||||
val id: String
|
||||
get() {
|
||||
return "$group:$name:$version"
|
||||
}
|
||||
}
|
||||
}
|
@ -21,6 +21,7 @@ import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.SourceDirectorySet
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||
import java.util.*
|
||||
|
||||
|
@ -3,9 +3,7 @@ package dorkbox.gradle
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ResolvedArtifact
|
||||
import org.gradle.api.artifacts.ResolvedDependency
|
||||
import org.gradle.api.plugins.JavaPluginConvention
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import kotlin.reflect.KMutableProperty
|
||||
@ -13,6 +11,7 @@ import kotlin.reflect.KProperty
|
||||
import kotlin.reflect.full.declaredMemberFunctions
|
||||
import kotlin.reflect.full.declaredMemberProperties
|
||||
|
||||
|
||||
open class StaticMethodsAndTools(private val project: Project) {
|
||||
/**
|
||||
* Maps the property (key/value) pairs of a property file onto the specified target object. Also maps fields in the targetObject to the
|
||||
@ -113,40 +112,45 @@ open class StaticMethodsAndTools(private val project: Project) {
|
||||
|
||||
/**
|
||||
* Resolves all child dependencies of the project
|
||||
*
|
||||
* THIS MUST BE IN "afterEvaluate" or run from a specific task.
|
||||
*/
|
||||
fun resolveDependencies(): List<ResolvedArtifact> {
|
||||
val configuration = project.configurations.getByName("default") as Configuration
|
||||
fun resolveDependencies(): List<DependencyScanner.Dependency> {
|
||||
val projectDependencies = mutableListOf<DependencyScanner.Dependency>()
|
||||
val existingNames = mutableSetOf<String>()
|
||||
|
||||
val includedDeps = mutableSetOf<ResolvedDependency>()
|
||||
val depsToSearch = LinkedList<ResolvedDependency>()
|
||||
depsToSearch.addAll(configuration.resolvedConfiguration.firstLevelModuleDependencies)
|
||||
DependencyScanner.scan(project, "compileClasspath", projectDependencies, existingNames)
|
||||
DependencyScanner.scan(project, "runtimeClasspath", projectDependencies, existingNames)
|
||||
|
||||
return includedDeps.flatMap {
|
||||
it.moduleArtifacts
|
||||
return projectDependencies
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Recursively resolves all dependencies of the project
|
||||
* Resolves all child compile dependencies of the project
|
||||
*
|
||||
* THIS MUST BE IN "afterEvaluate" or run from a specific task.
|
||||
*/
|
||||
fun resolveAllDependencies(): List<ResolvedArtifact> {
|
||||
val configuration = project.configurations.getByName("default") as Configuration
|
||||
fun resolveCompileDependencies(): List<DependencyScanner.Dependency> {
|
||||
val projectDependencies = mutableListOf<DependencyScanner.Dependency>()
|
||||
val existingNames = mutableSetOf<String>()
|
||||
|
||||
val includedDeps = mutableSetOf<ResolvedDependency>()
|
||||
val depsToSearch = LinkedList<ResolvedDependency>()
|
||||
depsToSearch.addAll(configuration.resolvedConfiguration.firstLevelModuleDependencies)
|
||||
DependencyScanner.scan(project, "compileClasspath", projectDependencies, existingNames)
|
||||
|
||||
while (depsToSearch.isNotEmpty()) {
|
||||
val dep = depsToSearch.removeFirst()
|
||||
includedDeps.add(dep)
|
||||
|
||||
depsToSearch.addAll(dep.children)
|
||||
return projectDependencies
|
||||
}
|
||||
|
||||
return includedDeps.flatMap {
|
||||
it.moduleArtifacts
|
||||
}
|
||||
/**
|
||||
* Resolves all child compile dependencies of the project
|
||||
*
|
||||
* THIS MUST BE IN "afterEvaluate" or run from a specific task.
|
||||
*/
|
||||
fun resolveRuntimeDependencies(): List<DependencyScanner.Dependency> {
|
||||
val projectDependencies = mutableListOf<DependencyScanner.Dependency>()
|
||||
val existingNames = mutableSetOf<String>()
|
||||
|
||||
DependencyScanner.scan(project, "runtimeClasspath", projectDependencies, existingNames)
|
||||
|
||||
return projectDependencies
|
||||
}
|
||||
|
||||
/**
|
||||
@ -165,6 +169,46 @@ open class StaticMethodsAndTools(private val project: Project) {
|
||||
it.testOutputDir = mainDir
|
||||
}
|
||||
}
|
||||
|
||||
// this has the side-effect of NOT creating the gradle directories....
|
||||
|
||||
// make sure that the source set directories all exist. THIS SHOULD NOT BE A PROBLEM!
|
||||
project.afterEvaluate { prj ->
|
||||
prj.allprojects.forEach { proj ->
|
||||
val javaPlugin: JavaPluginConvention = proj.convention.getPlugin(JavaPluginConvention::class.java)
|
||||
val sourceSets = javaPlugin.sourceSets
|
||||
|
||||
sourceSets.forEach { set ->
|
||||
set.output.classesDirs.forEach { dir ->
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure a default resolution strategy. While not necessary, this is used for enforcing sane project builds
|
||||
*/
|
||||
fun defaultResolutionStrategy() {
|
||||
project.configurations.forEach { config ->
|
||||
config.resolutionStrategy {
|
||||
// fail eagerly on version conflict (includes transitive dependencies)
|
||||
// e.g. multiple different versions of the same dependency (group and name are equal)
|
||||
it.failOnVersionConflict()
|
||||
|
||||
// if there is a version we specified, USE THAT VERSION (over transitive versions)
|
||||
it.preferProjectModules()
|
||||
|
||||
// cache dynamic versions for 10 minutes
|
||||
it.cacheDynamicVersionsFor(10 * 60, "seconds")
|
||||
|
||||
// don't cache changing modules at all
|
||||
it.cacheChangingModulesFor(0, "seconds")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun idea(project: Project, configure: org.gradle.plugins.ide.idea.model.IdeaModel.() -> Unit): Unit =
|
||||
|
Loading…
Reference in New Issue
Block a user