diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 2e2d8afbf..f5a080bb8 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -1428,7 +1428,11 @@ object Defaults extends BuildCommon with DefExtra { /** Fork options for run-like tasks: the forked process inherits sbt's working directory. */ private[sbt] def runForkOptionsTask: Initialize[Task[ForkOptions]] = - Def.task(forkOptionsTask.value.withWorkingDirectory(None)) + Def.task { + // this uses Compile / run / baseDirectory, which defaults to ThisBuild / baseDirectory + forkOptionsTask.value + .withWorkingDirectory(Some(baseDirectory.value)) + } def testExecutionTask(task: Scoped): Initialize[Task[Tests.Execution]] = Def.task { @@ -2609,7 +2613,8 @@ object Defaults extends BuildCommon with DefExtra { private lazy val newRunnerSettings: Seq[Setting[?]] = Seq( runner := Def.uncached(ClassLoaders.runner.value), - forkOptions := Def.uncached(runForkOptionsTask.value) + forkOptions := Def.uncached(runForkOptionsTask.value), + baseDirectory := (ThisBuild / baseDirectory).value, ) lazy val baseTasks: Seq[Setting[?]] = projectTasks ++ packageBase diff --git a/sbt-app/src/sbt-test/run/fork-working-directory/app/Hello.scala b/sbt-app/src/sbt-test/run/fork-working-directory/app/Hello.scala new file mode 100644 index 000000000..189419512 --- /dev/null +++ b/sbt-app/src/sbt-test/run/fork-working-directory/app/Hello.scala @@ -0,0 +1,10 @@ +package example + +import java.io.File +import java.nio.file.{ Files, Path } + +@main +def hello(arg: String*): Unit = + val x = new File(".").getAbsolutePath + println(s"hi $x") + Files.createFile(Path.of("flag")) diff --git a/sbt-app/src/sbt-test/run/fork-working-directory/changes/a.sbt b/sbt-app/src/sbt-test/run/fork-working-directory/changes/a.sbt new file mode 100644 index 000000000..184b248ae --- /dev/null +++ b/sbt-app/src/sbt-test/run/fork-working-directory/changes/a.sbt @@ -0,0 +1,17 @@ +scalaVersion := "3.8.4" + +@transient +lazy val check = taskKey[Unit]("") + +lazy val root = rootProject + .autoAggregate + +lazy val app = project + .settings( + check := { + val b = (ThisBuild / baseDirectory).value + val fo = (Compile / run / forkOptions).value + assert(fo.workingDirectory == Some(b), s"${fo.workingDirectory}") + }, + Compile / run / fork := true, + ) diff --git a/sbt-app/src/sbt-test/run/fork-working-directory/changes/b.sbt b/sbt-app/src/sbt-test/run/fork-working-directory/changes/b.sbt new file mode 100644 index 000000000..c7aa50511 --- /dev/null +++ b/sbt-app/src/sbt-test/run/fork-working-directory/changes/b.sbt @@ -0,0 +1,20 @@ +scalaVersion := "3.8.4" + +@transient +lazy val check = taskKey[Unit]("") + +lazy val root = rootProject + .autoAggregate + +lazy val app = project + .settings( + check := { + val b = baseDirectory.value + val fo = (Compile / run / forkOptions).value + assert(fo.workingDirectory == Some(b), s"${fo.workingDirectory}") + }, + Compile / run / fork := true, + // app's own baseDirectory is explicitly requested as run's working + // directory, so `app/run` is expected to execute from app/. + Compile / run / baseDirectory := baseDirectory.value, + ) diff --git a/sbt-app/src/sbt-test/run/fork-working-directory/test b/sbt-app/src/sbt-test/run/fork-working-directory/test new file mode 100644 index 000000000..21c968dfa --- /dev/null +++ b/sbt-app/src/sbt-test/run/fork-working-directory/test @@ -0,0 +1,20 @@ +# app sets Compile / run / baseDirectory to its own baseDirectory, so +# `app/run` is expected to execute with app/ as its working directory. + +$ copy-file changes/a.sbt build.sbt +> reload +> app/check + +> app/run +$ exists flag +$ absent app/flag +$ delete flag + +$ copy-file changes/b.sbt build.sbt +> reload +> app/check + +> app/run +$ exists app/flag +$ absent flag +$ delete app/flag