mirror of https://github.com/sbt/sbt.git
Use `-Dsbt.script` to start sbt server
In order to start the sbt server we must use the sbt script because it is the only way to load the .sbtopts and the .jvmopts file properly. To do so the sbt script can pass a -Dsbt.script prop to the java server. It is used in the NetworkClient to start the server, and it is replicated in the BuildServerConnection file (.bsp/sbt.json).
This commit is contained in:
parent
5f4798fa76
commit
c9ca2d4afa
|
|
@ -1045,7 +1045,8 @@ object NetworkClient {
|
|||
private[client] val noStdErr = "--no-stderr"
|
||||
private[client] val sbtBase = "--sbt-base-directory"
|
||||
private[client] def parseArgs(args: Array[String]): Arguments = {
|
||||
var sbtScript = if (Properties.isWin) "sbt.bat" else "sbt"
|
||||
val defaultSbtScript = if (Properties.isWin) "sbt.bat" else "sbt"
|
||||
var sbtScript = Properties.propOrNone("sbt.script")
|
||||
var launchJar: Option[String] = None
|
||||
var bsp = false
|
||||
val commandArgs = new mutable.ArrayBuffer[String]
|
||||
|
|
@ -1067,11 +1068,10 @@ object NetworkClient {
|
|||
sbtScript = a
|
||||
.split("--sbt-script=")
|
||||
.lastOption
|
||||
.map(_.replaceAllLiterally("%20", " "))
|
||||
.getOrElse(sbtScript)
|
||||
.orElse(sbtScript)
|
||||
case "--sbt-script" if i + 1 < sanitized.length =>
|
||||
i += 1
|
||||
sbtScript = sanitized(i).replaceAllLiterally("%20", " ")
|
||||
sbtScript = Some(sanitized(i))
|
||||
case a if a.startsWith("--sbt-launch-jar=") =>
|
||||
launchJar = a
|
||||
.split("--sbt-launch-jar=")
|
||||
|
|
@ -1091,12 +1091,17 @@ object NetworkClient {
|
|||
}
|
||||
val base = new File("").getCanonicalFile
|
||||
if (!sbtArguments.contains("-Dsbt.io.virtual=true")) sbtArguments += "-Dsbt.io.virtual=true"
|
||||
if (!sbtArguments.exists(_.startsWith("-Dsbt.script"))) {
|
||||
sbtScript.foreach { sbtScript =>
|
||||
sbtArguments += s"-Dsbt.script=$sbtScript"
|
||||
}
|
||||
}
|
||||
new Arguments(
|
||||
base,
|
||||
sbtArguments.toSeq,
|
||||
commandArgs.toSeq,
|
||||
completionArguments.toSeq,
|
||||
sbtScript,
|
||||
sbtScript.getOrElse(defaultSbtScript).replaceAllLiterally("%20", " "),
|
||||
bsp,
|
||||
launchJar
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,12 +7,13 @@
|
|||
|
||||
package sbt.internal.bsp
|
||||
|
||||
import java.io.File
|
||||
|
||||
import sbt.internal.bsp
|
||||
import sbt.internal.bsp.codec.JsonProtocol.BspConnectionDetailsFormat
|
||||
import sbt.io.IO
|
||||
import sjsonnew.support.scalajson.unsafe.{ CompactPrinter, Converter }
|
||||
|
||||
import java.io.File
|
||||
import java.nio.file.{ Files, Paths }
|
||||
|
||||
object BuildServerConnection {
|
||||
final val name = "sbt"
|
||||
final val bspVersion = "2.0.0-M5"
|
||||
|
|
@ -21,26 +22,45 @@ object BuildServerConnection {
|
|||
private final val SbtLaunchJar = "sbt-launch(-.*)?\\.jar".r
|
||||
|
||||
private[sbt] def writeConnectionFile(sbtVersion: String, baseDir: File): Unit = {
|
||||
import bsp.codec.JsonProtocol._
|
||||
val bspConnectionFile = new File(baseDir, ".bsp/sbt.json")
|
||||
val javaHome = System.getProperty("java.home")
|
||||
val classPath = System.getProperty("java.class.path")
|
||||
val sbtLaunchJar = classPath
|
||||
.split(File.pathSeparator)
|
||||
.find(jar => SbtLaunchJar.findFirstIn(jar).nonEmpty)
|
||||
.map(_.replaceAllLiterally(" ", "%20"))
|
||||
val argv =
|
||||
Vector(
|
||||
s"$javaHome/bin/java",
|
||||
"-Xms100m",
|
||||
"-Xmx100m",
|
||||
"-classpath",
|
||||
classPath,
|
||||
"xsbt.boot.Boot",
|
||||
"-bsp"
|
||||
) ++ sbtLaunchJar.map(jar => s"--sbt-launch-jar=$jar")
|
||||
val argv = Option(System.getProperty("sbt.script"))
|
||||
.map(_.replaceAllLiterally("%20", " "))
|
||||
.orElse(sbtScriptInPath) match {
|
||||
case Some(sbtScript) =>
|
||||
Vector(sbtScript, "-bsp", s"-Dsbt.script=${sbtScript.replaceAllLiterally(" ", "%20")}")
|
||||
case None =>
|
||||
// IntelliJ can start sbt even if the sbt script is not accessible from $PATH.
|
||||
// To do so it uses its own bundled sbt-launch.jar.
|
||||
// In that case, we must pass the path of the sbt-launch.jar to the BSP connection
|
||||
// so that the server can be started.
|
||||
// A known problem in that situation is that the .sbtopts and .jvmopts are not loaded.
|
||||
val javaHome = System.getProperty("java.home")
|
||||
val classPath = System.getProperty("java.class.path")
|
||||
val sbtLaunchJar = classPath
|
||||
.split(File.pathSeparator)
|
||||
.find(jar => SbtLaunchJar.findFirstIn(jar).nonEmpty)
|
||||
.map(_.replaceAllLiterally(" ", "%20"))
|
||||
|
||||
Vector(
|
||||
s"$javaHome/bin/java",
|
||||
"-Xms100m",
|
||||
"-Xmx100m",
|
||||
"-classpath",
|
||||
classPath,
|
||||
"xsbt.boot.Boot",
|
||||
"-bsp"
|
||||
) ++ sbtLaunchJar.map(jar => s"--sbt-launch-jar=$jar")
|
||||
}
|
||||
val details = BspConnectionDetails(name, sbtVersion, bspVersion, languages, argv)
|
||||
val json = Converter.toJson(details).get
|
||||
IO.write(bspConnectionFile, CompactPrinter(json), append = false)
|
||||
}
|
||||
|
||||
private def sbtScriptInPath: Option[String] = {
|
||||
// For those who use an old sbt script, the -Dsbt.script is not set
|
||||
// As a fallback we try to find the sbt script in $PATH
|
||||
val envPath = Option(System.getenv("PATH")).getOrElse("")
|
||||
val allPaths = envPath.split(File.pathSeparator).map(Paths.get(_))
|
||||
allPaths.map(_.resolve("sbt")).find(Files.exists(_)).map(_.toString)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
11
sbt
11
sbt
|
|
@ -299,6 +299,16 @@ addDefaultMemory() {
|
|||
fi
|
||||
}
|
||||
|
||||
addSbtScriptProperty () {
|
||||
if [[ "${java_args[@]}" == -Dsbt.script=* ]]; then
|
||||
:
|
||||
else
|
||||
sbt_script=$0
|
||||
sbt_script=${sbt_script/ /%20}
|
||||
addJava "-Dsbt.script=$sbt_script"
|
||||
fi
|
||||
}
|
||||
|
||||
require_arg () {
|
||||
local type="$1"
|
||||
local opt="$2"
|
||||
|
|
@ -769,6 +779,7 @@ else
|
|||
java_version="$(jdk_version)"
|
||||
vlog "[process_args] java_version = '$java_version'"
|
||||
addDefaultMemory
|
||||
addSbtScriptProperty
|
||||
set -- "${residual_args[@]}"
|
||||
argumentCount=$#
|
||||
run
|
||||
|
|
|
|||
Loading…
Reference in New Issue