From 647dbc47f4731baa31a52f75af762e8a50d602e7 Mon Sep 17 00:00:00 2001 From: eugene yokota Date: Wed, 4 Mar 2026 02:35:38 -0500 Subject: [PATCH] [2.x] Move compiler bridge to Update (#8836) **Problem** We want to grab tooling artifacts in update. **Solution** This adds binary compiler bridge artifacts into the update graph. --- .../sbt/librarymanagement/ConfigRef.scala | 4 +++ .../ConfigurationExtra.scala | 1 + .../librarymanagement/ScalaArtifacts.scala | 24 ++++++++++++++++ main/src/main/scala/sbt/Defaults.scala | 28 +++---------------- .../main/scala/sbt/internal/Compiler.scala | 11 ++++++++ .../scala/sbt/internal/inc/ZincLmUtil.scala | 8 ++---- 6 files changed, 46 insertions(+), 30 deletions(-) diff --git a/lm-core/src/main/scala/sbt/librarymanagement/ConfigRef.scala b/lm-core/src/main/scala/sbt/librarymanagement/ConfigRef.scala index 5ef4bdb2d..9dceb8526 100644 --- a/lm-core/src/main/scala/sbt/librarymanagement/ConfigRef.scala +++ b/lm-core/src/main/scala/sbt/librarymanagement/ConfigRef.scala @@ -44,11 +44,13 @@ object ConfigRef extends sbt.librarymanagement.ConfigRefFunctions { private lazy val Pom = new ConfigRef("pom") private lazy val ScalaTool = new ConfigRef("scala-tool") private lazy val ScalaDocTool = new ConfigRef("scala-doc-tool") + private lazy val ScalaReplTool = new ConfigRef("scala-repl-tool") private lazy val CompilerPlugin = new ConfigRef("plugin") private lazy val Component = new ConfigRef("component") private lazy val RuntimeInternal = new ConfigRef("runtime-internal") private lazy val TestInternal = new ConfigRef("test-internal") private lazy val CompileInternal = new ConfigRef("compile-internal") + private lazy val ZincTool = new ConfigRef("zinc-tool") def apply(name: String): ConfigRef = name match { case "default" => Default @@ -61,11 +63,13 @@ object ConfigRef extends sbt.librarymanagement.ConfigRefFunctions { case "pom" => Pom case "scala-tool" => ScalaTool case "scala-doc-tool" => ScalaDocTool + case "scala-repl-tool" => ScalaReplTool case "plugin" => CompilerPlugin case "component" => Component case "runtime-internal" => RuntimeInternal case "test-internal" => TestInternal case "compile-internal" => CompileInternal + case "zinc-tool" => ZincTool case _ => cache.getOrElseUpdate(name, new ConfigRef(name)) } } diff --git a/lm-core/src/main/scala/sbt/librarymanagement/ConfigurationExtra.scala b/lm-core/src/main/scala/sbt/librarymanagement/ConfigurationExtra.scala index a50ea2c58..966df7c9d 100644 --- a/lm-core/src/main/scala/sbt/librarymanagement/ConfigurationExtra.scala +++ b/lm-core/src/main/scala/sbt/librarymanagement/ConfigurationExtra.scala @@ -50,6 +50,7 @@ object Configurations { lazy val ScalaDocTool = Configuration.of("ScalaDocTool", "scala-doc-tool").hide lazy val ScalaReplTool = Configuration.of("ScalaReplTool", "scala-repl-tool").hide lazy val CompilerPlugin = Configuration.of("CompilerPlugin", "plugin").hide + lazy val ZincTool = Configuration.of("ZincTool", "zinc-tool").hide lazy val Component = Configuration.of("Component", "component").hide private[sbt] val DefaultMavenConfiguration = defaultConfiguration(true) diff --git a/lm-core/src/main/scala/sbt/librarymanagement/ScalaArtifacts.scala b/lm-core/src/main/scala/sbt/librarymanagement/ScalaArtifacts.scala index 590c2fde4..4ccb7255d 100644 --- a/lm-core/src/main/scala/sbt/librarymanagement/ScalaArtifacts.scala +++ b/lm-core/src/main/scala/sbt/librarymanagement/ScalaArtifacts.scala @@ -18,6 +18,7 @@ object ScalaArtifacts { final val Scala3TastyInspectorID = "scala3-tasty-inspector" final val Scala3ReplID = "scala3-repl" final val Scala3_8Artifacts = Vector(LibraryID, Scala3LibraryID) + final val scala2SbtBridgeStart = "2.13.12" private[sbt] final val Scala3LibraryPrefix = Scala3LibraryID + "_" private[sbt] final val Scala3CompilerPrefix = Scala3CompilerID + "_" @@ -132,6 +133,29 @@ object ScalaArtifacts { Some(Configurations.ScalaTool.name + "->default,optional(default)") ) .platform(Platform.jvm) + + private[sbt] def hasScala2SbtBridge(sv: String): Boolean = + VersionNumber(sv).matchesSemVer( + SemanticSelector(s"=2.13 >=$scala2SbtBridgeStart") + ) + + private[sbt] def compilerBridgeDependencies( + org: String, + scalaVersion: String + ): Seq[ModuleID] = + if isScala3(scalaVersion) then + Vector( + ModuleID(org, "scala3-sbt-bridge", scalaVersion) + .withConfigurations(Some(s"${Configurations.ZincTool.name}->default,optional(default)")) + .platform(Platform.jvm) + ) + else if hasScala2SbtBridge(scalaVersion) then + Vector( + ModuleID(org, "scala2-sbt-bridge", scalaVersion) + .withConfigurations(Some(s"${Configurations.ZincTool.name}->default,optional(default)")) + .platform(Platform.jvm) + ) + else Nil } object SbtArtifacts { diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index e8490a39e..fd6314e1a 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -744,30 +744,9 @@ object Defaults extends BuildCommon { .ifS(Def.task { val sv = scalaVersion.value val managed = managedScalaInstance.value - val hasSbtBridge = ScalaArtifacts.isScala3(sv) || ZincLmUtil.hasScala2SbtBridge(sv) + val hasSbtBridge = ScalaArtifacts.isScala3(sv) || ScalaArtifacts.hasScala2SbtBridge(sv) hasSbtBridge && managed - })(Def.cachedTask { - // Use scalaDynVersion to resolve dynamic versions (e.g., "3-latest.candidate" -> "3.8.1-RC1") - val sv = scalaDynVersion.value - val conv = fileConverter.value - val s = streams.value - val t = target.value - val r = dependencyResolution.value - val uc = updateConfiguration.value - val jar = ZincLmUtil.fetchDefaultBridgeModule( - scalaOrganization.value, - sv, - r, - uc, - (update / unresolvedWarningConfiguration).value, - s.log - ) - val out = t / "compiler-bridge" / jar.getName() - val outVf = conv.toVirtualFile(out.toPath()) - IO.copyFile(jar, out) - Def.declareOutput(outVf) - Vector(outVf: HashedVirtualFileRef) - })(Def.task(Vector.empty)) + })(Compiler.compilerBridgeFromUpdate)(Def.task(Vector.empty)) .value, scalaCompilerBridgeJars := (Def.taskDyn { val s = streams.value @@ -3190,7 +3169,7 @@ object Classpaths { ivyConfigurations ++= Configurations.auxiliary, ivyConfigurations ++= { if (managedScalaInstance.value && scalaHome.value.isEmpty) - Configurations.ScalaTool :: Configurations.ScalaDocTool :: Configurations.ScalaReplTool :: Nil + Configurations.ScalaTool :: Configurations.ScalaDocTool :: Configurations.ScalaReplTool :: Configurations.ZincTool :: Nil else Nil }, // Coursier needs these @@ -3430,6 +3409,7 @@ object Classpaths { then Nil else ScalaArtifacts.toolDependencies(scalaOrg, version) ++ + ScalaArtifacts.compilerBridgeDependencies(scalaOrg, version) ++ ScalaArtifacts.docToolDependencies(scalaOrg, version) ++ ScalaArtifacts.replToolDependencies(scalaOrg, version) allToolDeps.map(_.platform(Platform.jvm)) ++ pluginAdjust diff --git a/main/src/main/scala/sbt/internal/Compiler.scala b/main/src/main/scala/sbt/internal/Compiler.scala index fe9b61e55..93d1fc5c8 100644 --- a/main/src/main/scala/sbt/internal/Compiler.scala +++ b/main/src/main/scala/sbt/internal/Compiler.scala @@ -140,6 +140,17 @@ object Compiler: ) } + def compilerBridgeFromUpdate: Def.Initialize[Task[Seq[HashedVirtualFileRef]]] = + Def.task { + val fullReport = Keys.update.value + val report = fullReport.configuration(Configurations.ZincTool) + val allJars = report match + case Some(r) => r.modules.flatMap(_.artifacts.map(_._2)) + case None => Nil + val conv = Keys.fileConverter.value + allJars.map(x => (conv.toVirtualFile(x.toPath()): HashedVirtualFileRef)) + } + def scalaInstanceConfigFromUpdate( extraToolConf: Option[Configuration] ): Def.Initialize[Task[ScalaInstanceConfig]] = Def.task { diff --git a/zinc-lm-integration/src/main/scala/sbt/internal/inc/ZincLmUtil.scala b/zinc-lm-integration/src/main/scala/sbt/internal/inc/ZincLmUtil.scala index 7a8b3b53a..2151745b5 100644 --- a/zinc-lm-integration/src/main/scala/sbt/internal/inc/ZincLmUtil.scala +++ b/zinc-lm-integration/src/main/scala/sbt/internal/inc/ZincLmUtil.scala @@ -15,10 +15,8 @@ import sbt.librarymanagement.{ DependencyResolution, ModuleID, ScalaArtifacts, - SemanticSelector, UnresolvedWarningConfiguration, UpdateConfiguration, - VersionNumber, } import sbt.librarymanagement.syntax.* import xsbti.ArtifactInfo.SbtOrganization @@ -27,11 +25,9 @@ import xsbti.compile.{ ClasspathOptions, ScalaInstance as XScalaInstance } object ZincLmUtil { - final val scala2SbtBridgeStart = "2.13.12" + final val scala2SbtBridgeStart = ScalaArtifacts.scala2SbtBridgeStart def hasScala2SbtBridge(sv: String): Boolean = - VersionNumber(sv).matchesSemVer( - SemanticSelector(s"=2.13 >=$scala2SbtBridgeStart") - ) + ScalaArtifacts.hasScala2SbtBridge(sv) /** * Instantiate a Scala compiler that is instrumented to analyze dependencies.