From 99471da5f1cf452dea4ffbbebd05a44047a7511c Mon Sep 17 00:00:00 2001 From: BitToby <218712309+bittoby@users.noreply.github.com> Date: Thu, 26 Mar 2026 04:41:56 +0200 Subject: [PATCH] [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. --- main/src/main/scala/sbt/ProjectMatrix.scala | 8 +++++--- sbt-app/src/sbt-test/project-matrix/full/build.sbt | 6 ++++-- .../src/sbt-test/project-matrix/jvm-sandwich/build.sbt | 3 ++- sbt-app/src/sbt-test/project-matrix/jvm/build.sbt | 6 ++++-- .../src/sbt-test/project-matrix/projectAxes/build.sbt | 3 ++- .../src/sbt-test/project-matrix/source-dep/build.sbt | 10 ++++++++++ .../project-matrix/source-dep/ext/lib/build.sbt | 7 +++++++ .../source-dep/ext/lib/src/main/scala/lib/Lib.scala | 4 ++++ .../source-dep/src/main/scala/Main.scala | 3 +++ sbt-app/src/sbt-test/project-matrix/source-dep/test | 2 ++ 10 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 sbt-app/src/sbt-test/project-matrix/source-dep/build.sbt create mode 100644 sbt-app/src/sbt-test/project-matrix/source-dep/ext/lib/build.sbt create mode 100644 sbt-app/src/sbt-test/project-matrix/source-dep/ext/lib/src/main/scala/lib/Lib.scala create mode 100644 sbt-app/src/sbt-test/project-matrix/source-dep/src/main/scala/Main.scala create mode 100644 sbt-app/src/sbt-test/project-matrix/source-dep/test diff --git a/main/src/main/scala/sbt/ProjectMatrix.scala b/main/src/main/scala/sbt/ProjectMatrix.scala index ecb44a548..c77ad41f5 100644 --- a/main/src/main/scala/sbt/ProjectMatrix.scala +++ b/main/src/main/scala/sbt/ProjectMatrix.scala @@ -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[?]] = diff --git a/sbt-app/src/sbt-test/project-matrix/full/build.sbt b/sbt-app/src/sbt-test/project-matrix/full/build.sbt index 9abee4af3..9beae849a 100644 --- a/sbt-app/src/sbt-test/project-matrix/full/build.sbt +++ b/sbt-app/src/sbt-test/project-matrix/full/build.sbt @@ -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( diff --git a/sbt-app/src/sbt-test/project-matrix/jvm-sandwich/build.sbt b/sbt-app/src/sbt-test/project-matrix/jvm-sandwich/build.sbt index 7afc5a4a2..472116a7b 100644 --- a/sbt-app/src/sbt-test/project-matrix/jvm-sandwich/build.sbt +++ b/sbt-app/src/sbt-test/project-matrix/jvm-sandwich/build.sbt @@ -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)) diff --git a/sbt-app/src/sbt-test/project-matrix/jvm/build.sbt b/sbt-app/src/sbt-test/project-matrix/jvm/build.sbt index 1c422e7a3..3ee8a9578 100644 --- a/sbt-app/src/sbt-test/project-matrix/jvm/build.sbt +++ b/sbt-app/src/sbt-test/project-matrix/jvm/build.sbt @@ -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) diff --git a/sbt-app/src/sbt-test/project-matrix/projectAxes/build.sbt b/sbt-app/src/sbt-test/project-matrix/projectAxes/build.sbt index 298b760bb..c7870d2b4 100644 --- a/sbt-app/src/sbt-test/project-matrix/projectAxes/build.sbt +++ b/sbt-app/src/sbt-test/project-matrix/projectAxes/build.sbt @@ -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)) diff --git a/sbt-app/src/sbt-test/project-matrix/source-dep/build.sbt b/sbt-app/src/sbt-test/project-matrix/source-dep/build.sbt new file mode 100644 index 000000000..4cd63d118 --- /dev/null +++ b/sbt-app/src/sbt-test/project-matrix/source-dep/build.sbt @@ -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) diff --git a/sbt-app/src/sbt-test/project-matrix/source-dep/ext/lib/build.sbt b/sbt-app/src/sbt-test/project-matrix/source-dep/ext/lib/build.sbt new file mode 100644 index 000000000..9e5c68ec1 --- /dev/null +++ b/sbt-app/src/sbt-test/project-matrix/source-dep/ext/lib/build.sbt @@ -0,0 +1,7 @@ +ThisBuild / scalaVersion := "3.8.2" + +lazy val lib = (projectMatrix in file(".")) + .settings( + name := "lib", + ) + .jvmPlatform(scalaVersions = Seq("3.8.2")) diff --git a/sbt-app/src/sbt-test/project-matrix/source-dep/ext/lib/src/main/scala/lib/Lib.scala b/sbt-app/src/sbt-test/project-matrix/source-dep/ext/lib/src/main/scala/lib/Lib.scala new file mode 100644 index 000000000..e6b37d6d1 --- /dev/null +++ b/sbt-app/src/sbt-test/project-matrix/source-dep/ext/lib/src/main/scala/lib/Lib.scala @@ -0,0 +1,4 @@ +package lib + +object Lib: + val greeting: String = "hello from matrix lib" diff --git a/sbt-app/src/sbt-test/project-matrix/source-dep/src/main/scala/Main.scala b/sbt-app/src/sbt-test/project-matrix/source-dep/src/main/scala/Main.scala new file mode 100644 index 000000000..4ed1136f7 --- /dev/null +++ b/sbt-app/src/sbt-test/project-matrix/source-dep/src/main/scala/Main.scala @@ -0,0 +1,3 @@ +object Main: + def main(args: Array[String]): Unit = + println(lib.Lib.greeting) diff --git a/sbt-app/src/sbt-test/project-matrix/source-dep/test b/sbt-app/src/sbt-test/project-matrix/source-dep/test new file mode 100644 index 000000000..ee07fc8f6 --- /dev/null +++ b/sbt-app/src/sbt-test/project-matrix/source-dep/test @@ -0,0 +1,2 @@ +> compile +> run