Skip to content

Commit

Permalink
Merge pull request scala#10801 from szeiger/wip/2.13.x-system
Browse files Browse the repository at this point in the history
Support alternative JVM system images (via `-system`, like javac)
  • Loading branch information
SethTisue authored Aug 21, 2024
2 parents 4b0c2a5 + 98726c0 commit 52b2013
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 12 deletions.
2 changes: 1 addition & 1 deletion src/compiler/scala/tools/nsc/Global.scala
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ class Global(var currentSettings: Settings, reporter0: Reporter)
def optimizerClassPath(base: ClassPath): ClassPath =
base match {
case AggregateClassPath(entries) if entries.head.isInstanceOf[CtSymClassPath] =>
JrtClassPath(release = None, unsafe = None, closeableRegistry) match {
JrtClassPath(release = None, settings.systemPathValue, unsafe = None, closeableRegistry) match {
case jrt :: Nil => AggregateClassPath(entries.drop(1).prepended(jrt))
case _ => base
}
Expand Down
25 changes: 17 additions & 8 deletions src/compiler/scala/tools/nsc/classpath/DirectoryClassPath.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package scala.tools.nsc.classpath
import java.io.{Closeable, File}
import java.net.{URI, URL}
import java.nio.file._
import java.util.Collections

import scala.jdk.CollectionConverters._
import scala.reflect.internal.JDK9Reflectors
Expand Down Expand Up @@ -137,9 +138,9 @@ trait JFileDirectoryLookup[FileEntryType <: ClassRepresentation] extends Directo
}

object JrtClassPath {
private val jrtClassPathCache = new FileBasedCache[Unit, JrtClassPath]()
private val jrtClassPathCache = new FileBasedCache[Option[String], JrtClassPath]()
private val ctSymClassPathCache = new FileBasedCache[String, CtSymClassPath]()
def apply(release: Option[String], unsafe: Option[List[String]], closeableRegistry: CloseableRegistry): List[ClassPath] =
def apply(release: Option[String], systemPath: Option[String], unsafe: Option[List[String]], closeableRegistry: CloseableRegistry): List[ClassPath] =
if (!isJavaAtLeast("9")) Nil
else {
// TODO escalate errors once we're sure they are fatal
Expand All @@ -155,14 +156,14 @@ object JrtClassPath {
val ct = createCt(version, closeableRegistry)
unsafe match {
case Some(pkgs) if pkgs.nonEmpty =>
createJrt(closeableRegistry) match {
createJrt(systemPath, closeableRegistry) match {
case Nil => ct
case jrts => ct.appended(new FilteringJrtClassPath(jrts.head, pkgs: _*))
}
case _ => ct
}
case _ =>
createJrt(closeableRegistry)
createJrt(systemPath, closeableRegistry)
}
}
private def createCt(v: String, closeableRegistry: CloseableRegistry): List[ClassPath] =
Expand All @@ -176,10 +177,15 @@ object JrtClassPath {
} catch {
case NonFatal(_) => Nil
}
private def createJrt(closeableRegistry: CloseableRegistry): List[JrtClassPath] =
private def createJrt(systemPath: Option[String], closeableRegistry: CloseableRegistry): List[JrtClassPath] =
try {
val fs = FileSystems.getFileSystem(URI.create("jrt:/"))
val classPath = jrtClassPathCache.getOrCreate((), Nil, () => new JrtClassPath(fs), closeableRegistry, checkStamps = false)
val classPath = jrtClassPathCache.getOrCreate(systemPath, Nil, () => {
val fs = systemPath match {
case Some(javaHome) => FileSystems.newFileSystem(URI.create("jrt:/"), Collections.singletonMap("java.home", javaHome))
case None => FileSystems.getFileSystem(URI.create("jrt:/"))
}
new JrtClassPath(fs, systemPath.isDefined)
}, closeableRegistry, checkStamps = false)
List(classPath)
} catch {
case _: ProviderNotFoundException | _: FileSystemNotFoundException => Nil
Expand Down Expand Up @@ -207,7 +213,7 @@ final class FilteringJrtClassPath(delegate: JrtClassPath, allowed: String*) exte
*
* The implementation assumes that no classes exist in the empty package.
*/
final class JrtClassPath(fs: FileSystem) extends ClassPath with NoSourcePaths {
final class JrtClassPath(fs: FileSystem, closeFS: Boolean) extends ClassPath with NoSourcePaths with Closeable {
type F = Path
private val dir: Path = fs.getPath("/packages")

Expand Down Expand Up @@ -253,6 +259,9 @@ final class JrtClassPath(fs: FileSystem) extends ClassPath with NoSourcePaths {
}.take(1).toList.headOption
}
}

def close(): Unit =
if (closeFS) fs.close()
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ trait StandardScalaSettings { _: MutableSettings =>
val javaextdirs = PathSetting ("-javaextdirs", "Override java extdirs classpath.", Defaults.javaExtDirs) withAbbreviation "--java-extension-directories"
val sourcepath = PathSetting ("-sourcepath", "Specify location(s) of source files.", "") withAbbreviation "--source-path" // Defaults.scalaSourcePath
val rootdir = PathSetting ("-rootdir", "The absolute path of the project root directory, usually the git/scm checkout. Used by -Wconf.", "") withAbbreviation "--root-directory"
val systemPath = PathSetting ("-system", "Override location of Java system modules", "") withAbbreviation "--system"

/** Other settings.
*/
Expand Down Expand Up @@ -74,11 +75,13 @@ trait StandardScalaSettings { _: MutableSettings =>
val current = setting.value.toInt
if (!isJavaAtLeast("9") && current > 8) errorFn.apply("-release is only supported on JVM 9 and higher")
if (target.valueSetByUser.map(_.toInt > current).getOrElse(false)) errorFn("-release cannot be less than -target")
if (systemPath.isSetByUser) errorFn("-release cannot be used with -system")
//target.value = setting.value // this would trigger deprecation
}
.withAbbreviation("--release")
.withAbbreviation("-java-output-version")
def releaseValue: Option[String] = release.valueSetByUser
def systemPathValue: Option[String] = systemPath.valueSetByUser
val target =
ChoiceSetting("-target", "target", "Target platform for object files.", AllTargetVersions, "8")
.withPreSetHook(normalizeTarget)
Expand All @@ -89,7 +92,6 @@ trait StandardScalaSettings { _: MutableSettings =>
// .withAbbreviation("--Xtarget")
// .withAbbreviation("-Xtarget")
.withAbbreviation("-Xunchecked-java-output-version")
.withDeprecationMessage("Use -release instead to compile against the correct platform API.")
def targetValue: String = target.valueSetByUser.orElse(releaseValue).getOrElse(target.value)
val unchecked = BooleanSetting ("-unchecked", "Enable additional warnings where generated code depends on assumptions. See also -Wconf.") withAbbreviation "--unchecked" withPostSetHook { s =>
if (s.value) Wconf.tryToSet(List(s"cat=unchecked:w"))
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/scala/tools/util/PathResolver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ final class PathResolver(settings: Settings, closeableRegistry: CloseableRegistr
sourcesInPath(sourcePath) // 7. The Scala source path.
)

private def jrt: List[ClassPath] = JrtClassPath.apply(settings.releaseValue, settings.unsafe.valueSetByUser, closeableRegistry)
private def jrt: List[ClassPath] = JrtClassPath.apply(settings.releaseValue, settings.systemPathValue, settings.unsafe.valueSetByUser, closeableRegistry)

lazy val containers = basis.flatten.distinct

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class JrtClassPathTest {
val elements = new ClassPathFactory(settings, closeableRegistry).classesInPath(resolver.Calculated.javaBootClassPath)
AggregateClassPath(elements)
}
else JrtClassPath(None, None, closeableRegistry).head
else JrtClassPath(None, None, None, closeableRegistry).head

assertEquals(Nil, cp.classes(""))
assertTrue(cp.packages("java").toString, cp.packages("java").exists(_.name == "java.lang"))
Expand Down

0 comments on commit 52b2013

Please sign in to comment.