Add internalDependencyConfigurations setting

In order to walk the full dependency graph of a task, we need to know
the internal class path dependency configurations. Suppose that we have
projects a and b where b depends on *->compile in a. If we want to find
all of the inputs for b, then if we find that there is a dependency on
b/Compile/internalDependencyClasspath, then we must add a / Compile /
internalDependencyClasspath to the list of dependencies for the task.

I copied the setup of one of the other scripted tests that was
introduced to test the track-internal-dependencies feature to write a
basic scripted test for this new key and implementation.
This commit is contained in:
Ethan Atkins 2019-01-09 17:27:50 -08:00
parent 1df62b6933
commit e910a13d7f
9 changed files with 108 additions and 0 deletions

View File

@ -583,6 +583,7 @@ object Defaults extends BuildCommon {
) ++ (sourceGenerators / fileOutputs).value,
compile := compileTask.value,
clean := Clean.taskIn(ThisScope).value,
internalDependencyConfigurations := InternalDependencies.configurations.value,
manipulateBytecode := compileIncremental.value,
compileIncremental := (compileIncrementalTask tag (Tags.Compile, Tags.CPU)).value,
printWarnings := printWarningsTask.value,

View File

@ -334,6 +334,7 @@ object Keys {
val internalDependencyAsJars = taskKey[Classpath]("The internal (inter-project) classpath as JARs.")
val dependencyClasspathAsJars = taskKey[Classpath]("The classpath consisting of internal and external, managed and unmanaged dependencies, all as JARs.")
val fullClasspathAsJars = taskKey[Classpath]("The exported classpath, consisting of build products and unmanaged and managed, internal and external dependencies, all as JARs.")
val internalDependencyConfigurations = settingKey[Seq[(ProjectRef, Set[String])]]("The project configurations that this configuration depends on")
val internalConfigurationMap = settingKey[Configuration => Configuration]("Maps configurations to the actual configuration used to define the classpath.").withRank(CSetting)
val classpathConfiguration = taskKey[Configuration]("The configuration used to define the classpath.").withRank(CTask)

View File

@ -0,0 +1,32 @@
/*
* sbt
* Copyright 2011 - 2018, Lightbend, Inc.
* Copyright 2008 - 2010, Mark Harrah
* Licensed under Apache License 2.0 (see LICENSE)
*/
package sbt
package internal
import sbt.Keys._
private[sbt] object InternalDependencies {
def configurations: Def.Initialize[Seq[(ProjectRef, Set[String])]] = Def.setting {
val allConfigs = Classpaths.allConfigs(configuration.value).map(_.name).toSet
val ref = thisProjectRef.value
val applicableConfigs = allConfigs + "*"
((ref -> allConfigs) +: buildDependencies.value.classpath
.get(ref)
.toSeq
.flatMap(_.flatMap {
case ResolvedClasspathDependency(p, rawConfigs) =>
val configs = rawConfigs.getOrElse("*->compile").split(";").flatMap { config =>
config.split("->") match {
case Array(n, c) if applicableConfigs.contains(n) => Some(c)
case _ => None
}
}
if (configs.isEmpty) None else Some(p -> configs.toSet)
})).distinct
}
}

View File

@ -0,0 +1,3 @@
package a
object A {}

View File

@ -0,0 +1,5 @@
package b
object B {
println(a.A.toString)
}

View File

@ -0,0 +1,53 @@
lazy val root = (project in file(".")).
aggregate(a, b, c, d).
settings(
inThisBuild(Seq(
scalaVersion := "2.11.7",
trackInternalDependencies := TrackLevel.NoTracking
))
)
lazy val a = project in file("a")
lazy val b = (project in file("b")).dependsOn(a % "*->compile")
lazy val c = (project in file("c")).settings(exportToInternal := TrackLevel.NoTracking)
lazy val d = (project in file("d"))
.dependsOn(c % "test->test;compile->compile")
.settings(trackInternalDependencies := TrackLevel.TrackIfMissing)
def getConfigs(key: SettingKey[Seq[(ProjectRef, Set[String])]]):
Def.Initialize[Map[String, Set[String]]] =
Def.setting(key.value.map { case (p, c) => p.project -> c }.toMap)
val checkA = taskKey[Unit]("Verify that project a's internal dependencies are as expected")
checkA := {
val compileDeps = getConfigs(a / Compile / internalDependencyConfigurations).value
assert(compileDeps == Map("a" -> Set("compile")))
val testDeps = getConfigs(a / Test / internalDependencyConfigurations).value
assert(testDeps == Map("a" -> Set("compile", "runtime", "test")))
}
val checkB = taskKey[Unit]("Verify that project b's internal dependencies are as expected")
checkB := {
val compileDeps = getConfigs(b / Compile / internalDependencyConfigurations).value
assert(compileDeps == Map("b" -> Set("compile"), "a" -> Set("compile")))
val testDeps = getConfigs(b / Test / internalDependencyConfigurations).value
assert(testDeps == Map("b" -> Set("compile", "runtime", "test"), "a" -> Set("compile")))
}
val checkC = taskKey[Unit]("Verify that project c's internal dependencies are as expected")
checkC := {
val compileDeps = getConfigs(c / Compile / internalDependencyConfigurations).value
assert(compileDeps == Map("c" -> Set("compile")))
val testDeps = getConfigs(c / Test / internalDependencyConfigurations).value
assert(testDeps == Map("c" -> Set("compile", "runtime", "test")))
}
val checkD = taskKey[Unit]("Verify that project d's internal dependencies are as expected")
checkD := {
val compileDeps = getConfigs(d / Compile / internalDependencyConfigurations).value
assert(compileDeps == Map("d" -> Set("compile"), "c" -> Set("compile")))
val testDeps = getConfigs(d / Test / internalDependencyConfigurations).value
assert(testDeps == Map("d" -> Set("compile", "runtime", "test"), "c" -> Set("compile", "test")))
}

View File

@ -0,0 +1,3 @@
package c
object C {}

View File

@ -0,0 +1,3 @@
package d
object D { println(c.C.toString) }

View File

@ -0,0 +1,7 @@
> checkA
> checkB
> checkC
> checkD