From 0906b2d7acd86cc6f2987912b110b3b5d248c3d6 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sun, 15 Dec 2024 02:47:35 -0500 Subject: [PATCH 1/2] fix: Use JDK path, not JRE path **Problem** There are a few places where javaHome or java path is set, using java.home system property. The problem is that it points to JRE, not JDK, so it would break on Java compilation etc. **Solution** If the path ends with jre, go up one directory. --- .../main/scala/sbt/internal/util/Util.scala | 9 ++++++-- main/src/main/scala/sbt/Defaults.scala | 5 ++--- main/src/main/scala/sbt/internal/Load.scala | 4 ++-- .../internal/bsp/BuildServerConnection.scala | 3 ++- .../test/scala/testpkg/BuildServerTest.scala | 22 ++++++++++++------- 5 files changed, 27 insertions(+), 16 deletions(-) diff --git a/internal/util-core/src/main/scala/sbt/internal/util/Util.scala b/internal/util-core/src/main/scala/sbt/internal/util/Util.scala index 1ba2156f7..85952ec7d 100644 --- a/internal/util-core/src/main/scala/sbt/internal/util/Util.scala +++ b/internal/util-core/src/main/scala/sbt/internal/util/Util.scala @@ -8,11 +8,12 @@ package sbt.internal.util +import java.nio.file.{ Path, Paths } import java.util.Locale import scala.collection.concurrent.TrieMap -object Util { +object Util: def makeList[T](size: Int, value: T): List[T] = List.fill(size)(value) def separate[T, A, B](ps: Seq[T])(f: T => Either[A, B]): (Seq[A], Seq[B]) = { @@ -78,4 +79,8 @@ object Util { val cache = TrieMap.empty[A1, A2] x => cache.getOrElseUpdate(x, f(x)) } -} + + lazy val javaHome: Path = + if sys.props("java.home").endsWith("jre") then Paths.get(sys.props("java.home")).getParent() + else Paths.get(sys.props("java.home")) +end Util diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 89d02e61a..f5f57c957 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -9,7 +9,7 @@ package sbt import java.io.{ File, PrintWriter } -import java.nio.file.{ Files, Paths, Path => NioPath } +import java.nio.file.{ Files, Path => NioPath } import java.util.Optional import java.util.concurrent.TimeUnit import lmcoursier.CoursierDependencyResolution @@ -245,13 +245,12 @@ object Defaults extends BuildCommon { val base = app.baseDirectory.getCanonicalFile.toPath val boot = app.provider.scalaProvider.launcher.bootDirectory.toPath val ih = app.provider.scalaProvider.launcher.ivyHome.toPath - val javaHome = Paths.get(sys.props("java.home")) ListMap( "OUT" -> out, "BASE" -> base, "SBT_BOOT" -> boot, "IVY_HOME" -> ih, - "JAVA_HOME" -> javaHome + "JAVA_HOME" -> Util.javaHome, ) private[sbt] lazy val globalIvyCore: Seq[Setting[?]] = diff --git a/main/src/main/scala/sbt/internal/Load.scala b/main/src/main/scala/sbt/internal/Load.scala index 25d91b642..cb6232c03 100755 --- a/main/src/main/scala/sbt/internal/Load.scala +++ b/main/src/main/scala/sbt/internal/Load.scala @@ -33,7 +33,7 @@ import xsbti.{ FileConverter, HashedVirtualFileRef, VirtualFile } import xsbti.compile.{ ClasspathOptionsUtil, Compilers } import java.io.File import java.net.URI -import java.nio.file.{ Path, Paths } +import java.nio.file.Path import scala.annotation.tailrec import scala.collection.mutable import sbt.internal.util.Util @@ -71,7 +71,7 @@ private[sbt] object Load { val scalaProvider = app.provider.scalaProvider val launcher = scalaProvider.launcher val stagingDirectory = getStagingDirectory(state, globalBase).getCanonicalFile - val javaHome = Paths.get(sys.props("java.home")) + val javaHome = Util.javaHome val out = baseDirectory.toPath.resolve("target").resolve("out") val rootPaths = Map( "OUT" -> out, diff --git a/protocol/src/main/scala/sbt/internal/bsp/BuildServerConnection.scala b/protocol/src/main/scala/sbt/internal/bsp/BuildServerConnection.scala index 65f9fe120..306e17d92 100644 --- a/protocol/src/main/scala/sbt/internal/bsp/BuildServerConnection.scala +++ b/protocol/src/main/scala/sbt/internal/bsp/BuildServerConnection.scala @@ -9,6 +9,7 @@ package sbt.internal.bsp import sbt.internal.bsp.codec.JsonProtocol.BspConnectionDetailsFormat +import sbt.internal.util.Util import sbt.io.IO import sjsonnew.support.scalajson.unsafe.{ CompactPrinter, Converter } @@ -25,7 +26,7 @@ object BuildServerConnection { private[sbt] def writeConnectionFile(sbtVersion: String, baseDir: File): Unit = { val bspConnectionFile = new File(baseDir, ".bsp/sbt.json") - val javaHome = System.getProperty("java.home") + val javaHome = Util.javaHome val classPath = System.getProperty("java.class.path") val sbtScript = Option(System.getProperty("sbt.script")) diff --git a/server-test/src/test/scala/testpkg/BuildServerTest.scala b/server-test/src/test/scala/testpkg/BuildServerTest.scala index bdb06fa22..3b6913256 100644 --- a/server-test/src/test/scala/testpkg/BuildServerTest.scala +++ b/server-test/src/test/scala/testpkg/BuildServerTest.scala @@ -234,7 +234,6 @@ class BuildServerTest extends AbstractServerTest { val buildTarget = buildTargetUri("javaProj", "Compile") compile(buildTarget) - assertMessage( "build/publishDiagnostics", "Hello.java", @@ -257,16 +256,17 @@ class BuildServerTest extends AbstractServerTest { val testFile = new File(svr.baseDirectory, s"java-proj/src/main/java/example/Hello.java") val otherBuildFile = new File(svr.baseDirectory, "force-java-out-of-process-compiler.sbt") - // Setting `javaHome` will force SBT to shell out to an external Java compiler instead + // Setting `javaHome` will force sbt to shell out to an external Java compiler instead // of using the local compilation service offered by the JVM running this SBT instance. IO.write( otherBuildFile, """ + |def jdk: File = sbt.internal.Util.javaHome.toFile() |lazy val javaProj = project | .in(file("java-proj")) | .settings( | javacOptions += "-Xlint:all", - | javaHome := Some(file(System.getProperty("java.home"))) + | javaHome := Some(jdk) | ) |""".stripMargin ) @@ -278,16 +278,17 @@ class BuildServerTest extends AbstractServerTest { "build/publishDiagnostics", "Hello.java", """"severity":2""", - """found raw type: List""" - )(message = "should send publishDiagnostics with severity 2 for Hello.java") + """found raw type""" + )(message = "should send publishDiagnostics with severity 2 for Hello.java", debug = false) assertMessage( "build/publishDiagnostics", "Hello.java", """"severity":1""", - """incompatible types: int cannot be converted to String""" + """incompatible types: int cannot be converted""" )( - message = "should send publishDiagnostics with severity 1 for Hello.java" + message = "should send publishDiagnostics with severity 1 for Hello.java", + debug = true ) // Note the messages changed slightly in both cases. That's interesting… @@ -690,9 +691,14 @@ class BuildServerTest extends AbstractServerTest { def assertion = svr.waitForString(duration) { msg => if (debug) println(msg) + if debug then + parts.foreach: p => + if msg.contains(p) then println(s"> $msg contains $p") + else () parts.forall(msg.contains) } - if (message.nonEmpty) assert(assertion, message) else assert(assertion) + if message.nonEmpty then assert(assertion, message) + else assert(assertion) } private def reloadWorkspace(): Int = From e854909592d6da8cf5fde820a153c8bd0c25f517 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sun, 15 Dec 2024 14:59:02 -0500 Subject: [PATCH 2/2] Use JAVA_HOME when available --- .../util-core/src/main/scala/sbt/internal/util/Util.scala | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/internal/util-core/src/main/scala/sbt/internal/util/Util.scala b/internal/util-core/src/main/scala/sbt/internal/util/Util.scala index 85952ec7d..76647737b 100644 --- a/internal/util-core/src/main/scala/sbt/internal/util/Util.scala +++ b/internal/util-core/src/main/scala/sbt/internal/util/Util.scala @@ -81,6 +81,9 @@ object Util: } lazy val javaHome: Path = - if sys.props("java.home").endsWith("jre") then Paths.get(sys.props("java.home")).getParent() - else Paths.get(sys.props("java.home")) + sys.env.get("JAVA_HOME") match + case Some(home) => Paths.get(home) + case None => + if sys.props("java.home").endsWith("jre") then Paths.get(sys.props("java.home")).getParent() + else Paths.get(sys.props("java.home")) end Util