Skip to content

Commit

Permalink
Merge pull request #2450 from tgodzik/rtjarring
Browse files Browse the repository at this point in the history
bugfix: Use proper rt.jar if it exists
  • Loading branch information
tgodzik authored Sep 26, 2024
2 parents 97b71d9 + 35068a7 commit 34c545b
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 5 deletions.
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"))
}
}

0 comments on commit 34c545b

Please sign in to comment.