Exclude major sbt modules from metabuild resolution

Fixes #4582

#4443 introduced a perf enhacement of exluding sbt out of the metabuild, and instead appending the list of JARs resolved by the sbt launcher to the classpath.
This strategy worked in most cases, but it seems like some plugins are explicitly depending on IO module. In those cases, old IO would come before the new IO in the classpath ordering, resulting to "Symbol X is missing from classpath" error.
This fixes the issue by excluding all modules whose organization is `org.scala-sbt`.

As an escape hatch, I am adding a new key `reresolveSbtArtifacts`, which can be used to opt out of this behavior.
This commit is contained in:
Eugene Yokota 2019-03-28 14:59:55 -04:00
parent de5c0434df
commit 33e648473f
2 changed files with 19 additions and 3 deletions

View File

@ -175,6 +175,7 @@ object Defaults extends BuildCommon {
javaOptions :== Nil,
sbtPlugin :== false,
isMetaBuild :== false,
reresolveSbtArtifacts :== false,
crossPaths :== true,
sourcePositionMappers :== Nil,
artifactClassifier in packageSrc :== Some(SourceClassifier),
@ -1897,6 +1898,7 @@ object Classpaths {
unmanagedClasspath := unmanagedDependencies.value,
managedClasspath := {
val isMeta = isMetaBuild.value
val force = reresolveSbtArtifacts.value
val app = appConfiguration.value
val sbtCp0 = app.provider.mainClasspath.toList
val sbtCp = sbtCp0 map { Attributed.blank(_) }
@ -1905,7 +1907,7 @@ object Classpaths {
classpathTypes.value,
update.value
)
if (isMeta) mjars ++ sbtCp
if (isMeta && !force) mjars ++ sbtCp
else mjars
},
exportedProducts := trackedExportedProducts(TrackLevel.TrackAlways).value,
@ -2349,12 +2351,25 @@ object Classpaths {
ScalaArtifacts.toolDependencies(sbtOrg, version, isDotty) ++ pluginAdjust
}
},
// in case of meta build, exclude sbt from the dependency graph, so we can use the sbt resolved by the launcher
// in case of meta build, exclude all sbt modules from the dependency graph, so we can use the sbt resolved by the launcher
allExcludeDependencies := {
val sbtdeps = sbtDependency.value
val isMeta = isMetaBuild.value
val force = reresolveSbtArtifacts.value
val excludes = excludeDependencies.value
if (isMeta) excludes.toVector :+ ExclusionRule(sbtdeps.organization, sbtdeps.name)
val sbtModules = Vector(
"sbt",
"zinc_2.12",
"librarymanagement-core_2.12",
"librarymanagement-ivy_2.12",
"util-logging_2.12",
"util-position_2.12",
"io_2.12"
)
val sbtModulesExcludes = sbtModules map { nm: String =>
ExclusionRule(organization = sbtdeps.organization, name = nm)
}
if (isMeta && !force) excludes.toVector ++ sbtModulesExcludes
else excludes
},
dependencyOverrides ++= {

View File

@ -186,6 +186,7 @@ object Keys {
val discoveredSbtPlugins = taskKey[PluginDiscovery.DiscoveredNames]("The names of sbt plugin-related modules (modules that extend Build, Plugin, AutoPlugin) defined by this project.").withRank(CTask)
val sbtPlugin = settingKey[Boolean]("If true, enables adding sbt as a dependency and auto-generation of the plugin descriptor file.").withRank(BMinusSetting)
val isMetaBuild = settingKey[Boolean]("If true, this is a metabuild, a project inside project/ directory, and sbt is added to the classpath.").withRank(DSetting)
val reresolveSbtArtifacts = settingKey[Boolean]("If true, include sbt into the metabuild dependency graph. Otherwise reuse the artifacts resolved by the launcher on startup.").withRank(DSetting)
val pluginCrossBuild = taskKey[Unit]("Dummy task to scope `sbtVersion in pluginCrossBuild`, which gets used for plugin compilation.")
val crossSbtVersions = settingKey[Seq[String]]("The versions of Sbt used when cross-building an sbt plugin.")
val printWarnings = taskKey[Unit]("Shows warnings from compilation, including ones that weren't printed initially.").withRank(BPlusTask)