Merge branch '1.11.x' into wip/merge-1.11.x

This commit is contained in:
Eugene Yokota 2025-09-17 23:33:19 -04:00
commit 64dcdafc07
13 changed files with 70 additions and 43 deletions

View File

@ -35,7 +35,9 @@ jobs:
distribution: "zulu" distribution: "zulu"
java-version: "8" java-version: "8"
cache: sbt cache: sbt
- uses: sbt/setup-sbt@f20dc1bc1f8be605c44ffbcec6f17f708a4af9d1 # v1.1.12 - uses: sbt/setup-sbt@v1
with:
sbt-runner-version: 1.11.5
- name: Set up Python 3.12 - name: Set up Python 3.12
uses: actions/setup-python@v6 uses: actions/setup-python@v6
with: with:
@ -70,7 +72,7 @@ jobs:
# test launcher script # test launcher script
cd launcher-package cd launcher-package
bin/coursier resolve bin/coursier resolve
../sbt -Dsbt.build.version=$TEST_SBT_VER integrationTest/test sbt -Dsbt.build.version=$TEST_SBT_VER integrationTest/test
# This fails due to the JLine issue # This fails due to the JLine issue
# cd citest && ./test.sh # cd citest && ./test.sh
- name: Client test (Windows) - name: Client test (Windows)

View File

@ -14,7 +14,7 @@ jobs:
JVM_OPTS: -Xms800M -Xmx2G -Xss6M -XX:ReservedCodeCacheSize=128M -server -Dsbt.io.virtual=false -Dfile.encoding=UTF-8 JVM_OPTS: -Xms800M -Xmx2G -Xss6M -XX:ReservedCodeCacheSize=128M -server -Dsbt.io.virtual=false -Dfile.encoding=UTF-8
SBT_ETC_FILE: $HOME/etc/sbt/sbtopts SBT_ETC_FILE: $HOME/etc/sbt/sbtopts
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v5
- name: Setup JDK - name: Setup JDK
uses: actions/setup-java@v5 uses: actions/setup-java@v5
with: with:

View File

@ -34,6 +34,18 @@ $ sbt
sbt:sbtRoot> publishLocal sbt:sbtRoot> publishLocal
``` ```
### Instruction to build sbtn
```bash
$ sbt nativeImage
```
On macOS, the following can be used to target ARM64:
```bash
$ ARCHS=arm64 sbt nativeImage
```
### Instruction to build all modules from source ### Instruction to build all modules from source
When working on a change that requires changing one or more sub modules, the source code for these modules can be pulled in by running the following script When working on a change that requires changing one or more sub modules, the source code for these modules can be pulled in by running the following script
@ -71,29 +83,6 @@ $ sbt
> compile > compile
``` ```
### Nightly builds
_Note: The following section may require an update._
The latest development versions are available as nightly builds on sbt-maven-snapshots (<https://repo.scala-sbt.org/scalasbt/maven-snapshots>) repo, which is a redirect proxy whose underlying repository is subject to change it could be Bintray, Linux box, etc.
To use a nightly build:
1. Find out a version from [/org/scala-sbt/sbt/](https://repo.scala-sbt.org/scalasbt/maven-snapshots/org/scala-sbt/sbt/).
2. Put the version, for example `sbt.version=1.5.0-bin-20201121T081131` in `project/build.properties`.
sbt launcher will resolve the specified sbt core artifacts. Because of the aforementioned redirection, this resolution is going to be very slow for the first time you run sbt, and then it should be ok for subsequent runs.
Unless you're debugging the `sbt` script or the launcher JAR, you should be able to use any recent stable version of sbt installation as the launcher following the [Setup][Setup] instructions first.
If you're overriding the repositories via `~/.sbt/repositories`, make sure that there's a following entry:
```
[repositories]
...
sbt-maven-snapshots: https://repo.scala-sbt.org/scalasbt/maven-snapshots/, bootOnly
```
### Clearing out boot and local cache ### Clearing out boot and local cache
sbt consists of lots of JAR files. When running sbt locally, these JAR artifacts are cached in the `boot` directory under `$HOME/.sbt/boot/scala-2.12.6/org.scala-sbt/sbt/1.$MINOR.$PATCH-SNAPSHOT` directory. sbt consists of lots of JAR files. When running sbt locally, these JAR artifacts are cached in the `boot` directory under `$HOME/.sbt/boot/scala-2.12.6/org.scala-sbt/sbt/1.$MINOR.$PATCH-SNAPSHOT` directory.

View File

@ -867,6 +867,13 @@ lazy val sbtClientProj = (project in file("client"))
} }
outputDir.resolve("sbtn").toFile outputDir.resolve("sbtn").toFile
}, },
nativeImageCommand := {
val orig = nativeImageCommand.value
sys.env.get("ARCHS") match {
case Some(a) => Seq("arch", s"-$a") ++ orig
case None => orig
}
},
nativeImageOptions ++= Seq( nativeImageOptions ++= Seq(
"--no-fallback", "--no-fallback",
s"--initialize-at-run-time=sbt.client", s"--initialize-at-run-time=sbt.client",

View File

@ -121,7 +121,7 @@ val root = (project in file(".")).
file file
}, },
// update sbt.sh at root // update sbt.sh at root
sbtnVersion := "1.11.5", sbtnVersion := "1.11.6",
sbtnJarsBaseUrl := "https://github.com/sbt/sbtn-dist/releases/download", sbtnJarsBaseUrl := "https://github.com/sbt/sbtn-dist/releases/download",
sbtnJarsMappings := { sbtnJarsMappings := {
val baseUrl = sbtnJarsBaseUrl.value val baseUrl = sbtnJarsBaseUrl.value

View File

@ -1258,6 +1258,9 @@ object Defaults extends BuildCommon {
} }
def forkOptionsTask: Initialize[Task[ForkOptions]] = def forkOptionsTask: Initialize[Task[ForkOptions]] =
Def.task { Def.task {
val canUseArgumentsFile = sys.props
.getOrElse("java.vm.specification.version", "1")
.toFloat >= 9.0
ForkOptions( ForkOptions(
javaHome = javaHome.value, javaHome = javaHome.value,
outputStrategy = outputStrategy.value, outputStrategy = outputStrategy.value,
@ -1266,7 +1269,8 @@ object Defaults extends BuildCommon {
workingDirectory = Some(baseDirectory.value), workingDirectory = Some(baseDirectory.value),
runJVMOptions = javaOptions.value.toVector, runJVMOptions = javaOptions.value.toVector,
connectInput = connectInput.value, connectInput = connectInput.value,
envVars = envVars.value envVars = envVars.value,
canUseArgumentsFile = Some(canUseArgumentsFile)
) )
} }

View File

@ -428,7 +428,7 @@ private[sbt] object ClasspathImpl {
private def trim(a: Array[String]): List[String] = a.toList.map(_.trim) private def trim(a: Array[String]): List[String] = a.toList.map(_.trim)
def allConfigs(conf: Configuration): Seq[Configuration] = def allConfigs(conf: Configuration): Seq[Configuration] =
Dag.topologicalSort(conf)(_.extendsConfigs) Dag.reverseTopologicalSort(conf)(_.extendsConfigs)
def getConfigurations(p: ResolvedReference, data: Def.Settings): Seq[Configuration] = def getConfigurations(p: ResolvedReference, data: Def.Settings): Seq[Configuration] =
(p / ivyConfigurations).get(data).getOrElse(Nil) (p / ivyConfigurations).get(data).getOrElse(Nil)

View File

@ -16,7 +16,7 @@ object Dependencies {
private val sbtIO = "org.scala-sbt" %% "io" % ioVersion private val sbtIO = "org.scala-sbt" %% "io" % ioVersion
val launcherVersion = "1.4.4" val launcherVersion = "1.5.1"
val launcherInterface = "org.scala-sbt" % "launcher-interface" % launcherVersion val launcherInterface = "org.scala-sbt" % "launcher-interface" % launcherVersion
val rawLauncher = "org.scala-sbt" % "launcher" % launcherVersion val rawLauncher = "org.scala-sbt" % "launcher" % launcherVersion
val testInterface = "org.scala-sbt" % "test-interface" % "1.0" val testInterface = "org.scala-sbt" % "test-interface" % "1.0"

View File

@ -17,6 +17,7 @@ package sbt
* @param connectInput If true, the standard input of the forked process is connected to the standard input of this process. Otherwise, it is connected to an empty input stream. * @param connectInput If true, the standard input of the forked process is connected to the standard input of this process. Otherwise, it is connected to an empty input stream.
Connecting input streams can be problematic, especially on versions before Java 7. Connecting input streams can be problematic, especially on versions before Java 7.
* @param envVars The environment variables to provide to the forked process. By default, none are provided. * @param envVars The environment variables to provide to the forked process. By default, none are provided.
* @param canUseArgumentsFile Use arguments file
*/ */
final class ForkOptions private ( final class ForkOptions private (
val javaHome: Option[java.io.File], val javaHome: Option[java.io.File],
@ -25,22 +26,24 @@ final class ForkOptions private (
val workingDirectory: Option[java.io.File], val workingDirectory: Option[java.io.File],
val runJVMOptions: Vector[String], val runJVMOptions: Vector[String],
val connectInput: Boolean, val connectInput: Boolean,
val envVars: scala.collection.immutable.Map[String, String]) extends Serializable { val envVars: scala.collection.immutable.Map[String, String],
val canUseArgumentsFile: Option[Boolean]) extends Serializable {
private def this() = this(None, None, Vector(), None, Vector(), false, Map()) private def this() = this(None, None, Vector(), None, Vector(), false, Map(), None)
private def this(javaHome: Option[java.io.File], outputStrategy: Option[sbt.OutputStrategy], bootJars: Vector[java.io.File], workingDirectory: Option[java.io.File], runJVMOptions: Vector[String], connectInput: Boolean, envVars: scala.collection.immutable.Map[String, String]) = this(javaHome, outputStrategy, bootJars, workingDirectory, runJVMOptions, connectInput, envVars, None)
override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match { override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match {
case x: ForkOptions => (this.javaHome == x.javaHome) && (this.outputStrategy == x.outputStrategy) && (this.bootJars == x.bootJars) && (this.workingDirectory == x.workingDirectory) && (this.runJVMOptions == x.runJVMOptions) && (this.connectInput == x.connectInput) && (this.envVars == x.envVars) case x: ForkOptions => (this.javaHome == x.javaHome) && (this.outputStrategy == x.outputStrategy) && (this.bootJars == x.bootJars) && (this.workingDirectory == x.workingDirectory) && (this.runJVMOptions == x.runJVMOptions) && (this.connectInput == x.connectInput) && (this.envVars == x.envVars) && (this.canUseArgumentsFile == x.canUseArgumentsFile)
case _ => false case _ => false
}) })
override def hashCode: Int = { override def hashCode: Int = {
37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.ForkOptions".##) + javaHome.##) + outputStrategy.##) + bootJars.##) + workingDirectory.##) + runJVMOptions.##) + connectInput.##) + envVars.##) 37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.ForkOptions".##) + javaHome.##) + outputStrategy.##) + bootJars.##) + workingDirectory.##) + runJVMOptions.##) + connectInput.##) + envVars.##) + canUseArgumentsFile.##)
} }
override def toString: String = { override def toString: String = {
"ForkOptions(" + javaHome + ", " + outputStrategy + ", " + bootJars + ", " + workingDirectory + ", " + runJVMOptions + ", " + connectInput + ", " + envVars + ")" "ForkOptions(" + javaHome + ", " + outputStrategy + ", " + bootJars + ", " + workingDirectory + ", " + runJVMOptions + ", " + connectInput + ", " + envVars + ", " + canUseArgumentsFile + ")"
} }
private def copy(javaHome: Option[java.io.File] = javaHome, outputStrategy: Option[sbt.OutputStrategy] = outputStrategy, bootJars: Vector[java.io.File] = bootJars, workingDirectory: Option[java.io.File] = workingDirectory, runJVMOptions: Vector[String] = runJVMOptions, connectInput: Boolean = connectInput, envVars: scala.collection.immutable.Map[String, String] = envVars): ForkOptions = { private def copy(javaHome: Option[java.io.File] = javaHome, outputStrategy: Option[sbt.OutputStrategy] = outputStrategy, bootJars: Vector[java.io.File] = bootJars, workingDirectory: Option[java.io.File] = workingDirectory, runJVMOptions: Vector[String] = runJVMOptions, connectInput: Boolean = connectInput, envVars: scala.collection.immutable.Map[String, String] = envVars, canUseArgumentsFile: Option[Boolean] = canUseArgumentsFile): ForkOptions = {
new ForkOptions(javaHome, outputStrategy, bootJars, workingDirectory, runJVMOptions, connectInput, envVars) new ForkOptions(javaHome, outputStrategy, bootJars, workingDirectory, runJVMOptions, connectInput, envVars, canUseArgumentsFile)
} }
def withJavaHome(javaHome: Option[java.io.File]): ForkOptions = { def withJavaHome(javaHome: Option[java.io.File]): ForkOptions = {
copy(javaHome = javaHome) copy(javaHome = javaHome)
@ -72,10 +75,18 @@ final class ForkOptions private (
def withEnvVars(envVars: scala.collection.immutable.Map[String, String]): ForkOptions = { def withEnvVars(envVars: scala.collection.immutable.Map[String, String]): ForkOptions = {
copy(envVars = envVars) copy(envVars = envVars)
} }
def withCanUseArgumentsFile(canUseArgumentsFile: Option[Boolean]): ForkOptions = {
copy(canUseArgumentsFile = canUseArgumentsFile)
}
def withCanUseArgumentsFile(canUseArgumentsFile: Boolean): ForkOptions = {
copy(canUseArgumentsFile = Option(canUseArgumentsFile))
}
} }
object ForkOptions { object ForkOptions {
def apply(): ForkOptions = new ForkOptions() def apply(): ForkOptions = new ForkOptions()
def apply(javaHome: Option[java.io.File], outputStrategy: Option[sbt.OutputStrategy], bootJars: Vector[java.io.File], workingDirectory: Option[java.io.File], runJVMOptions: Vector[String], connectInput: Boolean, envVars: scala.collection.immutable.Map[String, String]): ForkOptions = new ForkOptions(javaHome, outputStrategy, bootJars, workingDirectory, runJVMOptions, connectInput, envVars) def apply(javaHome: Option[java.io.File], outputStrategy: Option[sbt.OutputStrategy], bootJars: Vector[java.io.File], workingDirectory: Option[java.io.File], runJVMOptions: Vector[String], connectInput: Boolean, envVars: scala.collection.immutable.Map[String, String]): ForkOptions = new ForkOptions(javaHome, outputStrategy, bootJars, workingDirectory, runJVMOptions, connectInput, envVars)
def apply(javaHome: java.io.File, outputStrategy: sbt.OutputStrategy, bootJars: Vector[java.io.File], workingDirectory: java.io.File, runJVMOptions: Vector[String], connectInput: Boolean, envVars: scala.collection.immutable.Map[String, String]): ForkOptions = new ForkOptions(Option(javaHome), Option(outputStrategy), bootJars, Option(workingDirectory), runJVMOptions, connectInput, envVars) def apply(javaHome: java.io.File, outputStrategy: sbt.OutputStrategy, bootJars: Vector[java.io.File], workingDirectory: java.io.File, runJVMOptions: Vector[String], connectInput: Boolean, envVars: scala.collection.immutable.Map[String, String]): ForkOptions = new ForkOptions(Option(javaHome), Option(outputStrategy), bootJars, Option(workingDirectory), runJVMOptions, connectInput, envVars)
def apply(javaHome: Option[java.io.File], outputStrategy: Option[sbt.OutputStrategy], bootJars: Vector[java.io.File], workingDirectory: Option[java.io.File], runJVMOptions: Vector[String], connectInput: Boolean, envVars: scala.collection.immutable.Map[String, String], canUseArgumentsFile: Option[Boolean]): ForkOptions = new ForkOptions(javaHome, outputStrategy, bootJars, workingDirectory, runJVMOptions, connectInput, envVars, canUseArgumentsFile)
def apply(javaHome: java.io.File, outputStrategy: sbt.OutputStrategy, bootJars: Vector[java.io.File], workingDirectory: java.io.File, runJVMOptions: Vector[String], connectInput: Boolean, envVars: scala.collection.immutable.Map[String, String], canUseArgumentsFile: Boolean): ForkOptions = new ForkOptions(Option(javaHome), Option(outputStrategy), bootJars, Option(workingDirectory), runJVMOptions, connectInput, envVars, Option(canUseArgumentsFile))
} }

View File

@ -27,4 +27,7 @@ type ForkOptions {
## The environment variables to provide to the forked process. By default, none are provided. ## The environment variables to provide to the forked process. By default, none are provided.
envVars: StringStringMap! = raw"Map()" @since("0.1.0") envVars: StringStringMap! = raw"Map()" @since("0.1.0")
## Use arguments file
canUseArgumentsFile: Boolean @since("1.11.6")
} }

View File

@ -52,7 +52,11 @@ final class Fork(val commandName: String, val runnerClass: Option[String]) {
val (classpathEnv, options) = Fork.fitClasspath(preOptions) val (classpathEnv, options) = Fork.fitClasspath(preOptions)
val command = executable +: options val command = executable +: options
val jpb = val jpb =
if (Fork.shouldUseArgumentsFile(options)) if (
config.canUseArgumentsFile.getOrElse(false) &&
Fork.booleanOpt("sbt.argsfile").getOrElse(true) &&
Fork.shouldUseArgumentsFile(options)
)
new JProcessBuilder(executable, Fork.createArgumentsFile(options)) new JProcessBuilder(executable, Fork.createArgumentsFile(options))
else else
new JProcessBuilder(command.toArray*) new JProcessBuilder(command.toArray*)
@ -144,9 +148,7 @@ object Fork {
* - the command line length would exceed MaxConcatenatedOptionLength * - the command line length would exceed MaxConcatenatedOptionLength
*/ */
private def shouldUseArgumentsFile(options: Seq[String]): Boolean = private def shouldUseArgumentsFile(options: Seq[String]): Boolean =
(sys.props.getOrElse("java.vm.specification.version", "1").toFloat >= 9.0) && options.mkString.length > MaxConcatenatedOptionLength
booleanOpt("sbt.argsfile").getOrElse(true) &&
(options.mkString.length > MaxConcatenatedOptionLength)
/** /**
* Create an arguments file from a sequence of command line arguments * Create an arguments file from a sequence of command line arguments

4
sbt
View File

@ -1,7 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set +e set +e
declare builtin_sbt_version="1.11.5" declare builtin_sbt_version="1.11.6"
declare -a residual_args declare -a residual_args
declare -a java_args declare -a java_args
declare -a scalac_args declare -a scalac_args
@ -25,7 +25,7 @@ declare use_sbtn=
declare use_jvm_client= declare use_jvm_client=
declare no_server= declare no_server=
declare sbtn_command="$SBTN_CMD" declare sbtn_command="$SBTN_CMD"
declare sbtn_version="1.11.5" declare sbtn_version="1.11.6"
declare use_colors=1 declare use_colors=1
declare is_this_dir_sbt="" declare is_this_dir_sbt=""

View File

@ -17,6 +17,15 @@ object Dag {
import scala.collection.mutable import scala.collection.mutable
import scala.jdk.CollectionConverters.* import scala.jdk.CollectionConverters.*
/**
* Returns a reverse topological ordering of the graph rooted at `root`.
* In this ordering, each node appears before all of its ancestors (i.e., children are listed before their parents).
*
* @see [[https://github.com/sbt/sbt/issues/8249]]
*/
def reverseTopologicalSort[T](root: T)(dependencies: T => Iterable[T]): List[T] =
topologicalSort(root)(dependencies).reverse
def topologicalSort[T](root: T)(dependencies: T => Iterable[T]): List[T] = def topologicalSort[T](root: T)(dependencies: T => Iterable[T]): List[T] =
topologicalSort(root :: Nil)(dependencies) topologicalSort(root :: Nil)(dependencies)