mirror of https://github.com/sbt/sbt.git
Fix classpath ordering for layered classloaders
The order of the classpath was not previously preserved because I converted the runtime and test classpaths to set. I fix that in this commit.
This commit is contained in:
parent
399dd920b0
commit
2c19138394
|
|
@ -46,14 +46,14 @@ private[sbt] object ClassLoaders {
|
||||||
val si = scalaInstance.value
|
val si = scalaInstance.value
|
||||||
val rawCP = data(fullClasspath.value)
|
val rawCP = data(fullClasspath.value)
|
||||||
val fullCP = if (si.isManagedVersion) rawCP else si.allJars.toSeq ++ rawCP
|
val fullCP = if (si.isManagedVersion) rawCP else si.allJars.toSeq ++ rawCP
|
||||||
val exclude = dependencyJars(exportedProducts).value.toSet ++ si.allJars.toSeq
|
val exclude = dependencyJars(exportedProducts).value.toSet ++ si.allJars
|
||||||
buildLayers(
|
buildLayers(
|
||||||
strategy = classLoaderLayeringStrategy.value,
|
strategy = classLoaderLayeringStrategy.value,
|
||||||
si = si,
|
si = si,
|
||||||
fullCP = fullCP,
|
fullCP = fullCP,
|
||||||
rawRuntimeDependencies =
|
rawRuntimeDependencies =
|
||||||
dependencyJars(Runtime / dependencyClasspath).value.filterNot(exclude),
|
dependencyJars(Runtime / dependencyClasspath).value.filterNot(exclude),
|
||||||
allDependencies = dependencyJars(dependencyClasspath).value.filterNot(exclude).toSet,
|
allDependencies = dependencyJars(dependencyClasspath).value.filterNot(exclude),
|
||||||
base = interfaceLoader,
|
base = interfaceLoader,
|
||||||
runtimeCache = (Runtime / classLoaderCache).value,
|
runtimeCache = (Runtime / classLoaderCache).value,
|
||||||
testCache = (Test / classLoaderCache).value,
|
testCache = (Test / classLoaderCache).value,
|
||||||
|
|
@ -91,17 +91,16 @@ private[sbt] object ClassLoaders {
|
||||||
val runtimeCache = (Runtime / classLoaderCache).value
|
val runtimeCache = (Runtime / classLoaderCache).value
|
||||||
val testCache = (Test / classLoaderCache).value
|
val testCache = (Test / classLoaderCache).value
|
||||||
val exclude = dependencyJars(exportedProducts).value.toSet ++ instance.allJars
|
val exclude = dependencyJars(exportedProducts).value.toSet ++ instance.allJars
|
||||||
|
val runtimeDeps = dependencyJars(Runtime / dependencyClasspath).value.filterNot(exclude)
|
||||||
|
val allDeps = dependencyJars(dependencyClasspath).value.filterNot(exclude)
|
||||||
val newLoader =
|
val newLoader =
|
||||||
(classpath: Seq[File]) => {
|
(classpath: Seq[File]) => {
|
||||||
buildLayers(
|
buildLayers(
|
||||||
strategy = classLoaderLayeringStrategy.value: @sbtUnchecked,
|
strategy = classLoaderLayeringStrategy.value: @sbtUnchecked,
|
||||||
si = instance,
|
si = instance,
|
||||||
fullCP = classpath,
|
fullCP = classpath,
|
||||||
rawRuntimeDependencies =
|
rawRuntimeDependencies = runtimeDeps,
|
||||||
(dependencyJars(Runtime / dependencyClasspath).value: @sbtUnchecked)
|
allDependencies = allDeps,
|
||||||
.filterNot(exclude),
|
|
||||||
allDependencies =
|
|
||||||
(dependencyJars(dependencyClasspath).value: @sbtUnchecked).filterNot(exclude).toSet,
|
|
||||||
base = baseLoader,
|
base = baseLoader,
|
||||||
runtimeCache = runtimeCache,
|
runtimeCache = runtimeCache,
|
||||||
testCache = testCache,
|
testCache = testCache,
|
||||||
|
|
@ -130,7 +129,7 @@ private[sbt] object ClassLoaders {
|
||||||
si: ScalaInstance,
|
si: ScalaInstance,
|
||||||
fullCP: Seq[File],
|
fullCP: Seq[File],
|
||||||
rawRuntimeDependencies: Seq[File],
|
rawRuntimeDependencies: Seq[File],
|
||||||
allDependencies: Set[File],
|
allDependencies: Seq[File],
|
||||||
base: ClassLoader,
|
base: ClassLoader,
|
||||||
runtimeCache: ClassLoaderCache,
|
runtimeCache: ClassLoaderCache,
|
||||||
testCache: ClassLoaderCache,
|
testCache: ClassLoaderCache,
|
||||||
|
|
@ -153,30 +152,31 @@ private[sbt] object ClassLoaders {
|
||||||
"Flat, ScalaInstance, RuntimeDependencies }"
|
"Flat, ScalaInstance, RuntimeDependencies }"
|
||||||
throw new IllegalArgumentException(msg)
|
throw new IllegalArgumentException(msg)
|
||||||
}
|
}
|
||||||
|
val allDependenciesSet = allDependencies.toSet
|
||||||
// The raw declarations are to avoid having to make a dynamic task. The
|
// The raw declarations are to avoid having to make a dynamic task. The
|
||||||
// allDependencies and allTestDependencies create a mutually exclusive list of jar
|
// allDependencies and allTestDependencies create a mutually exclusive list of jar
|
||||||
// dependencies for layers 2 and 3. Note that in the Runtime or Compile configs, it
|
// dependencies for layers 2 and 3. Note that in the Runtime or Compile configs, it
|
||||||
// should always be the case that allTestDependencies == Nil
|
// should always be the case that allTestDependencies == Nil
|
||||||
val allTestDependencies = if (layerTestDependencies) allDependencies else Set.empty[File]
|
val allTestDependencies = if (layerTestDependencies) allDependenciesSet else Set.empty[File]
|
||||||
val allRuntimeDependencies = (if (layerDependencies) rawRuntimeDependencies else Nil).toSet
|
val allRuntimeDependencies = (if (layerDependencies) rawRuntimeDependencies else Nil).toSet
|
||||||
|
|
||||||
|
val scalaInstanceLayer = combine(base, loader(si))
|
||||||
// layer 2
|
// layer 2
|
||||||
val runtimeDependencies = allDependencies intersect allRuntimeDependencies
|
val runtimeDependencySet = allDependenciesSet intersect allRuntimeDependencies
|
||||||
val runtimeLayer =
|
val runtimeDependencies = rawRuntimeDependencies.filter(runtimeDependencySet)
|
||||||
layer(runtimeDependencies.toSeq, loader(si), runtimeCache, resources, tmp)
|
lazy val runtimeLayer =
|
||||||
|
if (layerDependencies)
|
||||||
|
layer(runtimeDependencies, scalaInstanceLayer, runtimeCache, resources, tmp)
|
||||||
|
else scalaInstanceLayer
|
||||||
|
|
||||||
// layer 3 (optional if testDependencies are empty)
|
// layer 3 (optional if testDependencies are empty)
|
||||||
|
val testDependencySet = allTestDependencies diff runtimeDependencySet
|
||||||
// The top layer needs to include the interface jar or else the test task cannot be created.
|
val testDependencies = allDependencies.filter(testDependencySet)
|
||||||
// It needs to be separated from the runtimeLayer or else the runtimeLayer cannot be
|
val testLayer = layer(testDependencies, runtimeLayer, testCache, resources, tmp)
|
||||||
// shared between the runtime and test tasks.
|
|
||||||
val top = combine(base, runtimeLayer)
|
|
||||||
val testDependencies = allTestDependencies diff runtimeDependencies
|
|
||||||
val testLayer = layer(testDependencies.toSeq, top, testCache, resources, tmp)
|
|
||||||
|
|
||||||
// layer 4
|
// layer 4
|
||||||
val dynamicClasspath =
|
val dynamicClasspath =
|
||||||
fullCP.filterNot(testDependencies ++ runtimeDependencies ++ si.allJars)
|
fullCP.filterNot(testDependencySet ++ runtimeDependencies ++ si.allJars)
|
||||||
if (dynamicClasspath.nonEmpty)
|
if (dynamicClasspath.nonEmpty)
|
||||||
new LayeredClassLoader(dynamicClasspath, testLayer, resources, tmp)
|
new LayeredClassLoader(dynamicClasspath, testLayer, resources, tmp)
|
||||||
else testLayer
|
else testLayer
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue