From 33e648473f4e145b854e3b619b6dd464a36be3ae Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Thu, 28 Mar 2019 14:59:55 -0400 Subject: [PATCH] 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. --- main/src/main/scala/sbt/Defaults.scala | 21 ++++++++++++++++++--- main/src/main/scala/sbt/Keys.scala | 1 + 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index b4cc42383..9050b5ae7 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -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 ++= { diff --git a/main/src/main/scala/sbt/Keys.scala b/main/src/main/scala/sbt/Keys.scala index 5fdeeea03..ade13247d 100644 --- a/main/src/main/scala/sbt/Keys.scala +++ b/main/src/main/scala/sbt/Keys.scala @@ -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)