mirror of https://github.com/sbt/sbt.git
[2.x] fix: Runner should fail on JDK < 17 for sbt 2.x (#8825)
**Problem** Running sbt 2.x with JDK 8 produces a confusing "server was not detected" error because the JDK version check only required JDK 8+ and only ran in the non-native-client path. **Solution** Move java_version detection before the native client decision and add checkJava17ForSbt2 that requires JDK 17+ when sbt major version >= 2. Fixes #8813 * [2.x] fix: Fail early when sbt 2.x is run with JDK < 17 (sbtw) Move JDK version check before native client decision in sbtw and require JDK 17+ when build.properties declares sbt 2.x. * [2.x] fix: Fail early when sbt 2.x is run with JDK < 17 (sbt.bat) Move checkjava before native client decision in sbt.bat and require JDK 17+ when build.properties declares sbt 2.x. * [2.x] test: Add minimumJdkVersion helper and unit tests for sbtw Extract JDK version check logic into Runner.minimumJdkVersion for testability. Add RunnerSpec with tests for sbt 1.x, 2.x, and 3.x version detection. * [2.x] test: Bump fake java to JDK 17 for integration tests The fake java script used by launcher integration tests reported JDK 8. Since sbt 2.x now requires JDK 17+, the citest2 (sbt 2.x) integration tests would fail with the new JDK version check. * Simulate JDK 9+ rt.jar handling in fake java script Instead of silently ignoring --rt-ext-dir (which causes sbt.bat to mkdir on an empty string), properly simulate JDK 9+ behavior by creating a temp directory with java9-rt-ext- prefix and a dummy rt.jar inside it.
This commit is contained in:
parent
034834bd71
commit
28d877f633
|
|
@ -976,6 +976,7 @@ lazy val sbtwProj = (project in file("sbtw"))
|
|||
crossPaths := false,
|
||||
Compile / mainClass := Some("sbtw.Main"),
|
||||
libraryDependencies += "com.github.scopt" %% "scopt" % "4.1.0",
|
||||
libraryDependencies += scalaVerify % Test,
|
||||
Utils.noPublish,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,28 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
if '--version' in sys.argv or '-version' in sys.argv:
|
||||
print('openjdk version "1.8.0_212"')
|
||||
print('openjdk version "17.0.12" 2024-07-16')
|
||||
elif '--rt-ext-dir' in sys.argv:
|
||||
# Simulate JDK 9+ rt.jar ext dir: output a directory path containing
|
||||
# "java9-rt-ext-" that the launcher scripts look for via grep/findstr.
|
||||
ext_dir = os.path.join(tempfile.gettempdir(), 'java9-rt-ext-fake')
|
||||
os.makedirs(ext_dir, exist_ok=True)
|
||||
# Create a dummy rt.jar so the launcher won't try to --export-rt
|
||||
rt_jar = os.path.join(ext_dir, 'rt.jar')
|
||||
if not os.path.exists(rt_jar):
|
||||
open(rt_jar, 'w').close()
|
||||
print(ext_dir)
|
||||
elif '--export-rt' in sys.argv:
|
||||
# Simulate rt.jar export: create the file at the specified path
|
||||
idx = sys.argv.index('--export-rt')
|
||||
if idx + 1 < len(sys.argv):
|
||||
rt_path = sys.argv[idx + 1]
|
||||
os.makedirs(os.path.dirname(rt_path), exist_ok=True)
|
||||
open(rt_path, 'w').close()
|
||||
else:
|
||||
for arg in sys.argv[1:]:
|
||||
print(repr(arg)[1:-1])
|
||||
|
|
|
|||
|
|
@ -617,13 +617,13 @@ if !sbt_args_print_sbt_script_version! equ 1 (
|
|||
goto :eof
|
||||
)
|
||||
|
||||
call :checkjava
|
||||
|
||||
if !run_native_client! equ 1 if not defined sbt_args_print_version (
|
||||
goto :runnative !SBT_ARGS!
|
||||
goto :eof
|
||||
)
|
||||
|
||||
call :checkjava
|
||||
|
||||
if defined sbt_args_sbt_jar (
|
||||
set "sbt_jar=!sbt_args_sbt_jar!"
|
||||
) else (
|
||||
|
|
@ -1008,9 +1008,24 @@ exit /B 0
|
|||
|
||||
:checkjava
|
||||
set /a required_version=8
|
||||
rem sbt 2.x requires JDK 17+
|
||||
set "_sbt_check_ver=!build_props_sbt_version!"
|
||||
if not defined _sbt_check_ver set "_sbt_check_ver=!init_sbt_version!"
|
||||
if defined _sbt_check_ver (
|
||||
for /F "delims=.-_ tokens=1" %%m in ("!_sbt_check_ver!") do (
|
||||
if %%m GEQ 2 set /a required_version=17
|
||||
)
|
||||
)
|
||||
set "_sbt_check_ver="
|
||||
if /I !JAVA_VERSION! GEQ !required_version! (
|
||||
exit /B 0
|
||||
)
|
||||
if !required_version! GEQ 17 (
|
||||
>&2 echo.
|
||||
>&2 echo [error] sbt 2.x requires JDK 17 or above, but you have JDK !JAVA_VERSION!
|
||||
>&2 echo.
|
||||
exit /B 1
|
||||
)
|
||||
>&2 echo.
|
||||
>&2 echo The Java Development Kit ^(JDK^) installation you have is not up to date.
|
||||
>&2 echo sbt requires at least version !required_version!+, you have
|
||||
|
|
|
|||
18
sbt
18
sbt
|
|
@ -506,6 +506,18 @@ checkJava() {
|
|||
fi
|
||||
}
|
||||
|
||||
# sbt 2.x requires JDK 17+
|
||||
checkJava17ForSbt2() {
|
||||
local sbtV="$build_props_sbt_version"
|
||||
[[ "$sbtV" == "" ]] && sbtV="$init_sbt_version"
|
||||
[[ "$sbtV" == "" ]] && return
|
||||
local sbtMajor=$(echo "$sbtV" | sed 's/^\([0-9]*\).*/\1/')
|
||||
if (( sbtMajor >= 2 )) && [[ "$java_version" != "no_java" ]] && (( java_version < 17 )); then
|
||||
echoerr "[error] sbt 2.x requires JDK 17 or above, but you have JDK $java_version"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
copyRt() {
|
||||
local at_least_9="$(expr $java_version ">=" 9)"
|
||||
if [[ "$at_least_9" == "1" ]]; then
|
||||
|
|
@ -916,13 +928,15 @@ if [[ $print_sbt_script_version ]]; then
|
|||
exit 0
|
||||
fi
|
||||
|
||||
java_version="$(jdk_version)"
|
||||
vlog "[process_args] java_version = '$java_version'"
|
||||
checkJava17ForSbt2
|
||||
|
||||
if [[ "$(isRunNativeClient)" == "true" ]] && [[ -z "$print_version" ]]; then
|
||||
set -- "${residual_args[@]}"
|
||||
argumentCount=$#
|
||||
runNativeClient
|
||||
else
|
||||
java_version="$(jdk_version)"
|
||||
vlog "[process_args] java_version = '$java_version'"
|
||||
addDefaultMemory
|
||||
addSbtScriptProperty
|
||||
addJdkWorkaround
|
||||
|
|
|
|||
|
|
@ -41,6 +41,16 @@ object Main:
|
|||
return 1
|
||||
|
||||
val buildPropsVersion = ConfigLoader.sbtVersionFromBuildProperties(cwd)
|
||||
|
||||
val javaCmd = Runner.findJavaCmd(opts.javaHome)
|
||||
val javaVer = Runner.javaVersion(javaCmd)
|
||||
val minJdk = Runner.minimumJdkVersion(buildPropsVersion)
|
||||
if javaVer > 0 && javaVer < minJdk then
|
||||
if minJdk >= 17 then
|
||||
System.err.println("[error] sbt 2.x requires JDK 17 or above, but you have JDK " + javaVer)
|
||||
else System.err.println("[error] sbt requires at least JDK 8+, you have " + javaVer)
|
||||
return 1
|
||||
|
||||
val clientOpt = opts.client || sys.env.get("SBT_NATIVE_CLIENT").contains("true")
|
||||
val useNativeClient = shouldRunNativeClient(opts.copy(client = clientOpt), buildPropsVersion)
|
||||
|
||||
|
|
@ -48,12 +58,6 @@ object Main:
|
|||
val scriptPath = sbtBinDir.getAbsolutePath.replace("\\", "/") + "/sbt.bat"
|
||||
return Runner.runNativeClient(sbtBinDir, scriptPath, opts)
|
||||
|
||||
val javaCmd = Runner.findJavaCmd(opts.javaHome)
|
||||
val javaVer = Runner.javaVersion(javaCmd)
|
||||
if javaVer > 0 && javaVer < 8 then
|
||||
System.err.println("[error] sbt requires at least JDK 8+, you have " + javaVer)
|
||||
return 1
|
||||
|
||||
val sbtJar = opts.sbtJar
|
||||
.filter(p => new File(p).isFile)
|
||||
.getOrElse(new File(sbtBinDir, "sbt-launch.jar").getAbsolutePath)
|
||||
|
|
|
|||
|
|
@ -38,6 +38,11 @@ object Runner:
|
|||
else major
|
||||
catch { case _: Exception => 0 }
|
||||
|
||||
/** Returns the minimum JDK version required for the given sbt version. */
|
||||
def minimumJdkVersion(sbtVersion: Option[String]): Int =
|
||||
val isSbt2 = sbtVersion.exists(v => v.takeWhile(_.isDigit).toIntOption.exists(_ >= 2))
|
||||
if isSbt2 then 17 else 8
|
||||
|
||||
def buildSbtOpts(opts: LauncherOptions): Seq[String] =
|
||||
var s: Seq[String] = Nil
|
||||
if opts.debug then s = s :+ "-debug"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
package sbtw
|
||||
|
||||
object RunnerSpec extends verify.BasicTestSuite:
|
||||
test("minimumJdkVersion should require JDK 17 for sbt 2.x") {
|
||||
assert(Runner.minimumJdkVersion(Some("2.0.0-RC9")) == 17)
|
||||
}
|
||||
|
||||
test("minimumJdkVersion should require JDK 17 for sbt 2.x snapshot") {
|
||||
assert(Runner.minimumJdkVersion(Some("2.0.0-SNAPSHOT")) == 17)
|
||||
}
|
||||
|
||||
test("minimumJdkVersion should require JDK 8 for sbt 1.x") {
|
||||
assert(Runner.minimumJdkVersion(Some("1.10.7")) == 8)
|
||||
}
|
||||
|
||||
test("minimumJdkVersion should require JDK 8 when version is absent") {
|
||||
assert(Runner.minimumJdkVersion(None) == 8)
|
||||
}
|
||||
|
||||
test("minimumJdkVersion should require JDK 17 for future sbt 3.x") {
|
||||
assert(Runner.minimumJdkVersion(Some("3.0.0")) == 17)
|
||||
}
|
||||
end RunnerSpec
|
||||
Loading…
Reference in New Issue