[2.x] fix: Fix ProjectMatrix base directory resolution for source dependencies (#8983)

**Problem**

ProjectMatrix.baseSettings computes sourceDirectory and unmanagedBase using base.getAbsoluteFile, which resolves relative paths against the JVM's working directory. This works fine within a single build, but breaks for source dependencies - when an external build loaded via ProjectRef(file("ext/lib"), "lib") uses projectMatrix.in(file(".")), the file(".") resolves to the root project's directory instead of ext/lib/.

As a result, the matrix project picks up wrong sources and compilation fails.

**Solution**
Replace base.getAbsoluteFile with IO.resolve((ThisBuild / baseDirectory).value, base). Since ThisBuild / baseDirectory is set per build unit during loading, this correctly resolves against each build's own root directory.

sourceDirectory and unmanagedBase now derive from the resolved projectMatrixBaseDirectory setting.
This commit is contained in:
BitToby 2026-03-26 04:41:56 +02:00 committed by GitHub
parent bece316725
commit 99471da5f1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 43 additions and 9 deletions

View File

@ -366,11 +366,13 @@ object ProjectMatrix {
private lazy val noScalaLibrary: Seq[Def.Setting[?]] =
Seq(autoScalaLibrary := false, crossPaths := false)
// Resolve the matrix base against the build root rather than using getAbsoluteFile,
// which resolves against CWD and breaks source dependencies (issue #8971).
private lazy val baseSettings: Seq[Def.Setting[?]] = Def.settings(
name := self.id,
sourceDirectory := base.getAbsoluteFile / "src",
unmanagedBase := base.getAbsoluteFile / "lib",
projectMatrixBaseDirectory := base,
projectMatrixBaseDirectory := IO.resolve((ThisBuild / baseDirectory).value, base),
sourceDirectory := projectMatrixBaseDirectory.value / "src",
unmanagedBase := projectMatrixBaseDirectory.value / "lib",
)
private def rowSettings(r: ProjectRow): Seq[Def.Setting[?]] =

View File

@ -25,7 +25,8 @@ lazy val core = (projectMatrix in file("core"))
.settings(
check := {
assert(moduleName.value == "core", s"moduleName is ${moduleName.value}")
assert(projectMatrixBaseDirectory.value == file("core"))
assert(projectMatrixBaseDirectory.value == (ThisBuild / baseDirectory).value / "core",
s"projectMatrixBaseDirectory is ${projectMatrixBaseDirectory.value}")
assert(projectID.value.crossVersion == CrossVersion.full, s"crossVersion is ${projectID.value.crossVersion}")
},
)
@ -38,7 +39,8 @@ lazy val intf = (projectMatrix in file("intf"))
.settings(
check := {
assert(moduleName.value == "intf", s"moduleName is ${moduleName.value}")
assert(projectMatrixBaseDirectory.value == file("intf"))
assert(projectMatrixBaseDirectory.value == (ThisBuild / baseDirectory).value / "intf",
s"projectMatrixBaseDirectory is ${projectMatrixBaseDirectory.value}")
},
)
.jvmPlatform(

View File

@ -44,7 +44,8 @@ lazy val bazApp = (projectMatrix in file("baz-app"))
val cp = (Compile / fullClasspath).value.map(_.data.id)
assert(cp.exists(_.endsWith("baz-core_2.13-0.1.0-SNAPSHOT.jar")), cp)
assert(!cp.exists(_.endsWith("baz-core_3.0.0-M1-0.1.0-SNAPSHOT.jar")), cp)
assert(projectMatrixBaseDirectory.value == file("baz-app"))
assert(projectMatrixBaseDirectory.value == (ThisBuild / baseDirectory).value / "baz-app",
s"projectMatrixBaseDirectory is ${projectMatrixBaseDirectory.value}")
},
)
.jvmPlatform(scalaVersions = Seq(scala213))

View File

@ -19,7 +19,8 @@ lazy val core = (projectMatrix in file("core"))
.settings(
check := {
assert(moduleName.value == "core", s"moduleName is ${moduleName.value}")
assert(projectMatrixBaseDirectory.value == file("core"))
assert(projectMatrixBaseDirectory.value == (ThisBuild / baseDirectory).value / "core",
s"projectMatrixBaseDirectory is ${projectMatrixBaseDirectory.value}")
},
)
.jvmPlatform(scalaVersions = Seq(scala213, scala3))
@ -28,7 +29,8 @@ lazy val intf = (projectMatrix in file("intf"))
.settings(
check := {
assert(moduleName.value == "intf", s"moduleName is ${moduleName.value}")
assert(projectMatrixBaseDirectory.value == file("intf"))
assert(projectMatrixBaseDirectory.value == (ThisBuild / baseDirectory).value / "intf",
s"projectMatrixBaseDirectory is ${projectMatrixBaseDirectory.value}")
},
)
.jvmPlatform(autoScalaLibrary = false)

View File

@ -15,7 +15,8 @@ lazy val core = (projectMatrix in file("core"))
.settings(
check := {
assert(platformTest.value.endsWith("-platform"))
assert(projectMatrixBaseDirectory.value == file("core"))
assert(projectMatrixBaseDirectory.value == (ThisBuild / baseDirectory).value / "core",
s"projectMatrixBaseDirectory is ${projectMatrixBaseDirectory.value}")
},
)
.jvmPlatform(scalaVersions = Seq(scala213, scala212))

View File

@ -0,0 +1,10 @@
// https://github.com/sbt/sbt/issues/8971
ThisBuild / scalaVersion := "3.8.2"
lazy val extLib = ProjectRef(file("ext/lib"), "lib")
lazy val root = (project in file("."))
.settings(
name := "source-dep-matrix",
)
.dependsOn(extLib)

View File

@ -0,0 +1,7 @@
ThisBuild / scalaVersion := "3.8.2"
lazy val lib = (projectMatrix in file("."))
.settings(
name := "lib",
)
.jvmPlatform(scalaVersions = Seq("3.8.2"))

View File

@ -0,0 +1,4 @@
package lib
object Lib:
val greeting: String = "hello from matrix lib"

View File

@ -0,0 +1,3 @@
object Main:
def main(args: Array[String]): Unit =
println(lib.Lib.greeting)

View File

@ -0,0 +1,2 @@
> compile
> run