Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bugfix: Use proper rt.jar if it exists #2450

Merged
merged 2 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions backend/src/main/scala/bloop/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -873,9 +873,19 @@ object Compiler {
case Array("-release", "8") => true
case _ => false
}
val updatedClasspath =
if (needsRtJar) inputs.classpath ++ RtJarCache.create(JavaRuntime.version, logger)
else inputs.classpath
val possibleRtJar =
if (needsRtJar)
inputs.javacBin
.flatMap { binary =>
Try {
val javaHome = binary.getParent.getParent
javaHome.resolve("jre/lib/rt.jar")
}.toOption
}
.filter(_.exists)
.orElse(RtJarCache.create(JavaRuntime.version, logger))
else None
val updatedClasspath = inputs.classpath ++ possibleRtJar
val classpathVirtual = updatedClasspath.map(path => converter.toVirtualFile(path.underlying))
CompileOptions
.create()
Expand Down
81 changes: 79 additions & 2 deletions frontend/src/test/scala/bloop/JavaVersionSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ object JavaVersionSpec extends bloop.testing.BaseSuite {

private val jvmManager = coursierapi.JvmManager.create()

def checkFlag(scalacOpts: List[String], jdkVersion: String = "8") = {
def checkFlag(scalacOpts: List[String], jdkVersion: String = "8", shouldFail: Boolean = false) = {
val javaHome = jvmManager.get(jdkVersion).toPath()
val jvmConfig = Some(Config.JvmConfig(Some(javaHome), Nil))
TestUtil.withinWorkspace { workspace =>
Expand All @@ -29,7 +29,7 @@ object JavaVersionSpec extends bloop.testing.BaseSuite {
val projects = List(`A`)
val state = loadState(workspace, projects, logger)
val compiledState = state.compile(`A`)
if (jdkVersion == "8") {
if (jdkVersion == "8" || shouldFail) {
assertExitStatus(compiledState, ExitStatus.CompilationError)
val targetFoo = TestUtil.universalPath("a/src/main/scala/Foo.scala")
assertNoDiff(
Expand Down Expand Up @@ -63,7 +63,84 @@ object JavaVersionSpec extends bloop.testing.BaseSuite {
checkFlag(Nil, jdkVersion = "11")
}

test("doesnt-compile-with-11") {
checkFlag(List("-release", "8"), jdkVersion = "11", shouldFail = true)
checkFlag(List("-release:8"), jdkVersion = "11", shouldFail = true)
}

test("compiles-with-17") {
checkFlag(Nil, jdkVersion = "17")
}

test("doesnt-compile-with-17") {
checkFlag(List("-release", "8"), jdkVersion = "17", shouldFail = true)
checkFlag(List("-release:8"), jdkVersion = "17", shouldFail = true)
}

def checkRtJar(jdkVersion: String, scalacOpts: List[String] = Nil) = {
val javaHome = jvmManager.get(jdkVersion).toPath()
val jvmConfig = Some(Config.JvmConfig(Some(javaHome), Nil))
TestUtil.withinWorkspace { workspace =>
val sources = List(
"""/main/scala/Foo.scala
|import java.net.http.HttpClient
|class Foo{
| val output: HttpClient = ???
|}
""".stripMargin
)

val logger = new RecordingLogger(ansiCodesSupported = false)
val `A` =
TestProject(workspace, "a", sources, jvmConfig = jvmConfig, scalacOptions = scalacOpts)
val projects = List(`A`)
val state = loadState(workspace, projects, logger)
val compiledState = state.compile(`A`)
if (jdkVersion == "8") {
assertExitStatus(compiledState, ExitStatus.CompilationError)
val targetFoo = TestUtil.universalPath("a/src/main/scala/Foo.scala")
assertNoDiff(
logger.renderErrors(),
s"""|[E2] $targetFoo:3:15
| not found: type HttpClient
| L3: val output: HttpClient = ???
| ^
|[E1] $targetFoo:1:17
| object http is not a member of package java.net
| L1: import java.net.http.HttpClient
| ^
|$targetFoo: L1 [E1], L3 [E2]
|Failed to compile 'a'
|""".stripMargin
)
} else {
assertExitStatus(compiledState, ExitStatus.Ok)
}
}
}

if (!CrossPlatform.isM1) {
test("doesnt-compile") {
checkRtJar(jdkVersion = "8")
}
}

test("compiles-11") {
checkRtJar(jdkVersion = "11")

}

test("compiles-17") {
checkRtJar(jdkVersion = "17")
}

/* Current limitation: this should fail but the generated rt.jar contains all JDK 11 classes.
* However, most tools generating json configuration will set proper javaHome with JDK 8.
* Only if a user sets the flags themselves this will wrongly compile classes coming
* from future JDKs (but not added APIs).
*/
test("compiles-wrongly") {
checkRtJar(jdkVersion = "11", List("-release", "8"))
checkRtJar(jdkVersion = "17", List("-release", "8"))
}
}
Loading