[2.x] fix: Fixes global plugin loading (#9391)

**Problem**
Global plugin loading doesn't work.

**Solution**
1. Use ModuleID from to supply the location of global-plugin module.
2. Update pluginData with the global plugin classpath.
This commit is contained in:
eugene yokota 2026-06-28 14:57:18 -04:00 committed by GitHub
parent 3d99cffd5a
commit 0ef972706c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 54 additions and 42 deletions

View File

@ -805,6 +805,8 @@ lazy val mainProj = (project in file("main"))
exclude[ReversedMissingMethodProblem](
"sbt.internal.server.BuildServerReporter.sendFailureReport"
),
exclude[IncompatibleMethTypeProblem]("sbt.internal.GlobalPluginData.*"),
exclude[IncompatibleResultTypeProblem]("sbt.internal.GlobalPluginData.*"),
),
)
.dependsOn(lmCore, lmCoursierShadedPublishing)

View File

@ -9,6 +9,8 @@
package sbt
package internal
import java.io.File
import java.net.URI
import sbt.librarymanagement.{
Configuration,
Configurations,
@ -23,21 +25,21 @@ import Configurations.{ Compile, Runtime }
import sbt.ProjectExtra.{ extract, runUnloadHooks, setProject }
import sbt.SlashSyntax0.*
import sbt.librarymanagement.LibraryManagementCodec.given
import java.io.File
object GlobalPlugin {
// constructs a sequence of settings that may be appended to a project's settings to
// statically add the global plugin as a classpath dependency.
// static here meaning that the relevant tasks for the global plugin have already been evaluated
def inject(gp: GlobalPluginData): Seq[Setting[?]] =
val gpWithJar = gp.exportedJarUris.headOption
.fold(gp.projectID)(uri => gp.projectID.from(uri.toString))
Seq[Setting[?]](
projectDependencies ++= gp.projectID +: gp.dependencies,
projectDependencies ++= gpWithJar +: gp.dependencies,
resolvers := {
val rs = resolvers.value
(rs ++ gp.resolvers).distinct
},
globalPluginUpdate := gp.updateReport,
// TODO: these shouldn't be required (but are): the project* settings above should take care of this
injectInternalClasspath(Runtime, gp.internalClasspath),
injectInternalClasspath(Compile, gp.internalClasspath)
)
@ -76,13 +78,16 @@ object GlobalPlugin {
val taskInit = Def.task {
val intcp = (Runtime / internalDependencyClasspath).value
val prods = (Runtime / exportedProducts).value
val converter = fileConverter.value
val exportedJarUris = prods.map(a => converter.toPath(a.data).toUri).toVector
GlobalPluginData(
projectID.value,
projectDependencies.value,
resolvers.value.toVector,
(Runtime / fullClasspath).value,
(prods ++ intcp).distinct
(prods ++ intcp).distinct,
exportedJarUris
)(updateReport.value)
}
val resolvedTaskInit = taskInit.mapReferenced(Project.replaceThis(p))
@ -120,7 +125,8 @@ final case class GlobalPluginData(
dependencies: Seq[ModuleID],
resolvers: Vector[Resolver],
fullClasspath: Classpath,
internalClasspath: Classpath
internalClasspath: Classpath,
exportedJarUris: Vector[URI],
)(val updateReport: UpdateReport)
final case class GlobalPlugin(
data: GlobalPluginData,

View File

@ -1411,41 +1411,43 @@ private[sbt] object Load {
case None => Nil
/** These are the settings defined when loading a project "meta" build. */
val autoPluginSettings: Seq[Setting[?]] = inScope(GlobalScope.rescope(LocalRootProject))(
Seq(
sbtPlugin :== true,
isMetaBuild :== true,
pluginData := Def.uncached {
val prod = (Configurations.Runtime / exportedProducts).value
val internalCp = (Configurations.Runtime / internalDependencyClasspath).value
val cp = (Configurations.Runtime / fullClasspath).value
val opts = (Configurations.Compile / scalacOptions).value
val javaOpts = (Configurations.Compile / javacOptions).value
val unmanagedSrcDirs = (Configurations.Compile / unmanagedSourceDirectories).value
val unmanagedSrcs = (Configurations.Compile / unmanagedSources).value
val managedSrcDirs = (Configurations.Compile / managedSourceDirectories).value
val managedSrcs = (Configurations.Compile / managedSources).value
val buildTarget = (Configurations.Compile / bspTargetIdentifier).value
val converter = fileConverter.value
PluginData(
removeEntries(cp, prod),
prod,
Some(fullResolvers.value.toVector),
Some(update.value),
opts,
javaOpts,
unmanagedSrcDirs,
unmanagedSrcs,
managedSrcDirs,
managedSrcs,
Some(buildTarget),
converter,
internalCp,
)
},
onLoadMessage := ("loading project definition from " + baseDirectory.value)
def autoPluginSettings(config: LoadBuildConfiguration): Seq[Setting[?]] =
inScope(GlobalScope.rescope(LocalRootProject))(
Seq(
sbtPlugin :== true,
isMetaBuild :== true,
pluginData := Def.uncached {
val gpClasspath = globalPluginClasspath(config.globalPlugin)
val prod = (Configurations.Runtime / exportedProducts).value
val internalCp = (Configurations.Runtime / internalDependencyClasspath).value
val cp = (Configurations.Runtime / fullClasspath).value
val opts = (Configurations.Compile / scalacOptions).value
val javaOpts = (Configurations.Compile / javacOptions).value
val unmanagedSrcDirs = (Configurations.Compile / unmanagedSourceDirectories).value
val unmanagedSrcs = (Configurations.Compile / unmanagedSources).value
val managedSrcDirs = (Configurations.Compile / managedSourceDirectories).value
val managedSrcs = (Configurations.Compile / managedSources).value
val buildTarget = (Configurations.Compile / bspTargetIdentifier).value
val converter = fileConverter.value
PluginData(
(removeEntries(cp, prod) ++ gpClasspath).distinct,
prod,
Some(fullResolvers.value.toVector),
Some(update.value),
opts,
javaOpts,
unmanagedSrcDirs,
unmanagedSrcs,
managedSrcDirs,
managedSrcs,
Some(buildTarget),
converter,
internalCp,
)
},
onLoadMessage := ("loading project definition from " + baseDirectory.value)
)
)
)
private def removeEntries(
cp: Def.Classpath,
@ -1459,7 +1461,7 @@ private[sbt] object Load {
def enableSbtPlugin(config: LoadBuildConfiguration): LoadBuildConfiguration =
config.copy(
injectSettings = config.injectSettings.copy(
global = autoPluginSettings ++ config.injectSettings.global,
global = autoPluginSettings(config) ++ config.injectSettings.global,
project = config.pluginManagement.inject ++ config.injectSettings.project
)
)

View File

@ -13,10 +13,12 @@ lazy val root = (project in file("."))
TaskKey[Unit]("checkClassifiersModule") := Def.uncached {
val mod = (updateSbtClassifiers / classifiersModule).value
val deps = mod.dependencies
val actual = deps.map(m => s"${m.organization}:${m.name}").sorted.toSet
val actual = deps
.filter(m => m.organization != "org.scala-sbt")
.map(m => s"${m.organization}:${m.name}")
.sorted.toSet
val expected = Set(
"org.scala-sbt:sbt",
"junit:junit",
"com.eed3si9n:sbt-buildinfo_sbt2_3",
"org.hamcrest:hamcrest-core",