mirror of https://github.com/sbt/sbt.git
fix: Fixes client-side run
**Problem** Client-side run currently fails on JDK 8 because sbtn creates args file even though JDK 8 does not support it. This is likely because sbtn is compiled using GraalVM on a modern JDK. **Solution** This adds a new fork option canUseArgumentsFile to delegate the args file decision to the server, and default to false if the value is missing. This retroactively fixes sbt 2.x client-side run.
This commit is contained in:
parent
b5ab0e137e
commit
3a8a891d71
|
|
@ -1460,6 +1460,9 @@ object Defaults extends BuildCommon {
|
|||
}
|
||||
def forkOptionsTask: Initialize[Task[ForkOptions]] =
|
||||
Def.task {
|
||||
val canUseArgumentsFile = sys.props
|
||||
.getOrElse("java.vm.specification.version", "1")
|
||||
.toFloat >= 9.0
|
||||
ForkOptions(
|
||||
javaHome = javaHome.value,
|
||||
outputStrategy = outputStrategy.value,
|
||||
|
|
@ -1468,7 +1471,8 @@ object Defaults extends BuildCommon {
|
|||
workingDirectory = Some(baseDirectory.value),
|
||||
runJVMOptions = javaOptions.value.toVector,
|
||||
connectInput = connectInput.value,
|
||||
envVars = envVars.value
|
||||
envVars = envVars.value,
|
||||
canUseArgumentsFile = Some(canUseArgumentsFile)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
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 canUseArgumentsFile Use arguments file
|
||||
*/
|
||||
final class ForkOptions private (
|
||||
val javaHome: Option[java.io.File],
|
||||
|
|
@ -25,22 +26,24 @@ final class ForkOptions private (
|
|||
val workingDirectory: Option[java.io.File],
|
||||
val runJVMOptions: Vector[String],
|
||||
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 {
|
||||
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
|
||||
})
|
||||
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 = {
|
||||
"ForkOptions(" + javaHome + ", " + outputStrategy + ", " + bootJars + ", " + workingDirectory + ", " + runJVMOptions + ", " + connectInput + ", " + envVars + ")"
|
||||
"ForkOptions(" + javaHome + ", " + outputStrategy + ", " + bootJars + ", " + workingDirectory + ", " + runJVMOptions + ", " + connectInput + ", " + envVars + ", " + canUseArgumentsFile + ")"
|
||||
}
|
||||
private[this] 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 = {
|
||||
new ForkOptions(javaHome, outputStrategy, bootJars, workingDirectory, runJVMOptions, connectInput, envVars)
|
||||
private[this] 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, canUseArgumentsFile)
|
||||
}
|
||||
def withJavaHome(javaHome: Option[java.io.File]): ForkOptions = {
|
||||
copy(javaHome = javaHome)
|
||||
|
|
@ -72,10 +75,18 @@ final class ForkOptions private (
|
|||
def withEnvVars(envVars: scala.collection.immutable.Map[String, String]): ForkOptions = {
|
||||
copy(envVars = envVars)
|
||||
}
|
||||
def withCanUseArgumentsFile(canUseArgumentsFile: Option[Boolean]): ForkOptions = {
|
||||
copy(canUseArgumentsFile = canUseArgumentsFile)
|
||||
}
|
||||
def withCanUseArgumentsFile(canUseArgumentsFile: Boolean): ForkOptions = {
|
||||
copy(canUseArgumentsFile = Option(canUseArgumentsFile))
|
||||
}
|
||||
}
|
||||
object 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: 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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,4 +27,7 @@ type ForkOptions {
|
|||
|
||||
## The environment variables to provide to the forked process. By default, none are provided.
|
||||
envVars: StringStringMap! = raw"Map()" @since("0.1.0")
|
||||
|
||||
## Use arguments file
|
||||
canUseArgumentsFile: Boolean @since("1.11.6")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,9 @@ final class Fork(val commandName: String, val runnerClass: Option[String]) {
|
|||
val (classpathEnv, options) = Fork.fitClasspath(preOptions)
|
||||
val command = executable +: options
|
||||
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))
|
||||
else
|
||||
new JProcessBuilder(command.toArray: _*)
|
||||
|
|
@ -137,9 +139,7 @@ object Fork {
|
|||
* - the command line length would exceed MaxConcatenatedOptionLength
|
||||
*/
|
||||
private def shouldUseArgumentsFile(options: Seq[String]): Boolean =
|
||||
(sys.props.getOrElse("java.vm.specification.version", "1").toFloat >= 9.0) &&
|
||||
booleanOpt("sbt.argsfile").getOrElse(true) &&
|
||||
(options.mkString.length > MaxConcatenatedOptionLength)
|
||||
options.mkString.length > MaxConcatenatedOptionLength
|
||||
|
||||
/**
|
||||
* Create an arguments file from a sequence of command line arguments
|
||||
|
|
|
|||
Loading…
Reference in New Issue