More work on classpaths. This commit also unbreaks fsc, for
which we must have no test cases at all. In the short term there will probably be a few more minor disruptions since with classpaths constructed a half dozen different ways, achieving consistency requires flushing out the undocumented accidents upon which any given island might depend. Review by community. git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@20866 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
parent
0a474e7966
commit
b326352d56
|
@ -108,6 +108,7 @@ class StandardCompileClient {
|
|||
Console println fromServer
|
||||
loop
|
||||
}
|
||||
loop
|
||||
}
|
||||
wasError
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ class CompilerCommand(
|
|||
case x => List(x)
|
||||
}
|
||||
|
||||
settings processArguments expandedArguments
|
||||
settings.processArguments(expandedArguments, true)
|
||||
}
|
||||
else (true, Nil)
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ package scala.tools.nsc
|
|||
|
||||
/** A command for ScriptRunner */
|
||||
class GenericRunnerCommand(
|
||||
allargs: List[String],
|
||||
val allargs: List[String],
|
||||
override val settings: GenericRunnerSettings,
|
||||
error: String => Unit)
|
||||
extends CompilerCommand(allargs, settings, error, false, false)
|
||||
|
@ -29,7 +29,7 @@ extends CompilerCommand(allargs, settings, error, false, false)
|
|||
*
|
||||
* we can safely process arguments since we passed the superclass shouldProcessArguments=false
|
||||
*/
|
||||
val (thingToRun, arguments) = (settings processArguments allargs)._2 match {
|
||||
val (thingToRun, arguments) = (settings.processArguments(allargs, false))._2 match {
|
||||
case Nil => (None, Nil)
|
||||
case hd :: tl => (Some(hd), tl)
|
||||
}
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
|
||||
package scala.tools.nsc
|
||||
|
||||
import java.io.{ File, IOException }
|
||||
import java.io.IOException
|
||||
import java.lang.{ClassNotFoundException, NoSuchMethodException}
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
import java.net.{ URL, MalformedURLException }
|
||||
import scala.tools.util.PathResolver
|
||||
|
||||
import io.{ File }
|
||||
import util.{ ClassPath, ScalaClassLoader }
|
||||
import File.pathSeparator
|
||||
import Properties.{ versionString, copyrightString }
|
||||
|
@ -24,80 +25,44 @@ import Properties.{ versionString, copyrightString }
|
|||
object MainGenericRunner {
|
||||
def main(args: Array[String]) {
|
||||
def errorFn(str: String) = Console println str
|
||||
|
||||
val command = new GenericRunnerCommand(args.toList, errorFn)
|
||||
val settings = command.settings
|
||||
def sampleCompiler = new Global(settings)
|
||||
|
||||
if (!command.ok)
|
||||
return errorFn("%s\n%s".format(command.usageMsg, sampleCompiler.pluginOptionsHelp))
|
||||
|
||||
// append the jars in ${scala.home}/lib to the classpath, as well as "." if none was given.
|
||||
val needDot = settings.classpath.value == ""
|
||||
settings appendToClasspath PathResolver.genericRunnerClassPath
|
||||
if (needDot)
|
||||
settings appendToClasspath "."
|
||||
|
||||
settings.defines.applyToCurrentJVM
|
||||
|
||||
if (settings.version.value)
|
||||
return errorFn("Scala code runner %s -- %s".format(versionString, copyrightString))
|
||||
|
||||
if (command.shouldStopWithInfo)
|
||||
return errorFn(command getInfoMessage sampleCompiler)
|
||||
|
||||
def exitSuccess: Nothing = exit(0)
|
||||
def exitFailure(msg: Any = null): Nothing = {
|
||||
if (msg != null) errorFn(msg.toString)
|
||||
exit(1)
|
||||
}
|
||||
def exitCond(b: Boolean): Nothing =
|
||||
if (b) exitSuccess else exitFailure(null)
|
||||
|
||||
def fileToURL(f: File): Option[URL] =
|
||||
try { Some(f.toURI.toURL) }
|
||||
catch { case e => Console.println(e); None }
|
||||
|
||||
def paths(str: String): List[URL] =
|
||||
for (
|
||||
file <- ClassPath.expandPath(str) map (new File(_)) if file.exists;
|
||||
val url = fileToURL(file); if !url.isEmpty
|
||||
) yield url.get
|
||||
|
||||
def jars(dirs: String): List[URL] =
|
||||
for (
|
||||
libdir <- ClassPath.expandPath(dirs) map (new File(_)) if libdir.isDirectory;
|
||||
jarfile <- libdir.listFiles if jarfile.isFile && jarfile.getName.endsWith(".jar");
|
||||
val url = fileToURL(jarfile); if !url.isEmpty
|
||||
) yield url.get
|
||||
|
||||
def specToURL(spec: String): Option[URL] =
|
||||
try { Some(new URL(spec)) }
|
||||
catch { case e: MalformedURLException => Console.println(e); None }
|
||||
|
||||
def urls(specs: String): List[URL] =
|
||||
if (specs == null || specs.length == 0) Nil
|
||||
else for (
|
||||
spec <- specs.split(" ").toList;
|
||||
val url = specToURL(spec); if !url.isEmpty
|
||||
) yield url.get
|
||||
|
||||
val classpath: List[URL] = (
|
||||
paths(settings.bootclasspath.value) :::
|
||||
paths(settings.classpath.value) :::
|
||||
jars(settings.extdirs.value) :::
|
||||
urls(settings.Xcodebase.value)
|
||||
).distinct
|
||||
def exitCond(b: Boolean): Nothing = if (b) exitSuccess else exitFailure(null)
|
||||
|
||||
def createLoop(): InterpreterLoop = {
|
||||
val loop = new InterpreterLoop
|
||||
loop main settings
|
||||
loop
|
||||
val command = new GenericRunnerCommand(args.toList, errorFn)
|
||||
import command.settings
|
||||
def sampleCompiler = new Global(settings) // def so its not created unless needed
|
||||
|
||||
def processSettings() {
|
||||
// append the jars in ${scala.home}/lib to the classpath, as well as "." if none was given.
|
||||
val needDot = settings.classpath.value == ""
|
||||
settings appendToClasspath PathResolver.genericRunnerClassPath
|
||||
if (needDot)
|
||||
settings appendToClasspath "."
|
||||
|
||||
// XXX is this accomplishing anything?
|
||||
settings.defines.applyToCurrentJVM
|
||||
}
|
||||
|
||||
if (!command.ok)
|
||||
return errorFn("%s\n%s".format(command.usageMsg, sampleCompiler.pluginOptionsHelp))
|
||||
|
||||
processSettings()
|
||||
|
||||
if (settings.version.value)
|
||||
return errorFn("Scala code runner %s -- %s".format(versionString, copyrightString))
|
||||
|
||||
if (command.shouldStopWithInfo)
|
||||
return errorFn(command getInfoMessage sampleCompiler)
|
||||
|
||||
val classpath: List[URL] = PathResolver urlsFromSettings settings distinct
|
||||
|
||||
def dashe = settings.execute.value
|
||||
def dashi = settings.loadfiles.value
|
||||
def slurp = dashi map (file => io.File(file).slurp()) mkString "\n"
|
||||
def slurp = dashi map (file => File(file).slurp()) mkString "\n"
|
||||
|
||||
/** Was code given in a -e argument? */
|
||||
if (!settings.execute.isDefault) {
|
||||
|
@ -116,7 +81,10 @@ object MainGenericRunner {
|
|||
exitCond(ScriptRunner.runCommand(settings, code, fullArgs))
|
||||
}
|
||||
else command.thingToRun match {
|
||||
case None => createLoop()
|
||||
case None =>
|
||||
// Questionably, we start the interpreter when there are no arguments.
|
||||
new InterpreterLoop main settings
|
||||
|
||||
case Some(thingToRun) =>
|
||||
val isObjectName =
|
||||
settings.howtorun.value match {
|
||||
|
|
|
@ -14,16 +14,29 @@ import Settings._
|
|||
import annotation.elidable
|
||||
import scala.tools.util.PathResolver
|
||||
import scala.collection.mutable.ListBuffer
|
||||
import scala.collection.immutable.TreeSet
|
||||
|
||||
class Settings(errorFn: String => Unit) extends ScalacSettings {
|
||||
def this() = this(Console.println)
|
||||
|
||||
/** Iterates over the arguments applying them to settings where applicable.
|
||||
* Then verifies setting dependencies are met.
|
||||
*
|
||||
* This temporarily takes a boolean indicating whether to keep
|
||||
* processing if an argument is seen which is not a command line option.
|
||||
* This is an expedience for the moment so that you can say
|
||||
*
|
||||
* scalac -d /tmp foo.scala -optimise
|
||||
*
|
||||
* while also allowing
|
||||
*
|
||||
* scala Program opt opt
|
||||
*
|
||||
* to get their arguments.
|
||||
*
|
||||
* Returns (success, List of unprocessed arguments)
|
||||
*/
|
||||
def processArguments(arguments: List[String]): (Boolean, List[String]) = {
|
||||
def processArguments(arguments: List[String], processAll: Boolean): (Boolean, List[String]) = {
|
||||
var args = arguments
|
||||
val residualArgs = new ListBuffer[String]
|
||||
|
||||
|
@ -40,10 +53,9 @@ class Settings(errorFn: String => Unit) extends ScalacSettings {
|
|||
args = args.tail
|
||||
}
|
||||
else {
|
||||
// XXX have to rework MainGenericRunner. If we return early we break
|
||||
// the ability to have command line options follow source files, but if
|
||||
// we don't the command line is processed too early.
|
||||
// return (checkDependencies, args)
|
||||
if (!processAll)
|
||||
return (checkDependencies, args)
|
||||
|
||||
residualArgs += args.head
|
||||
args = args.tail
|
||||
}
|
||||
|
@ -51,52 +63,7 @@ class Settings(errorFn: String => Unit) extends ScalacSettings {
|
|||
|
||||
(checkDependencies, residualArgs.toList)
|
||||
}
|
||||
def processArgumentString(params: String) = processArguments(splitParams(params))
|
||||
|
||||
// optionizes a system property
|
||||
private def syspropopt(name: String): Option[String] = Option(System.getProperty(name))
|
||||
private def sysenvopt(name: String): Option[String] = Option(System.getenv(name))
|
||||
|
||||
// given any number of possible path segments, flattens down to a
|
||||
// :-separated style path
|
||||
private def concatPath(segments: Option[String]*): String =
|
||||
segments.toList.flatMap(x => x) mkString pathSeparator
|
||||
|
||||
protected def classpathDefault =
|
||||
sysenvopt("CLASSPATH") getOrElse "."
|
||||
|
||||
protected def bootclasspathDefault =
|
||||
concatPath(syspropopt("sun.boot.class.path"), guessedScalaBootClassPath)
|
||||
// syspropopt("sun.boot.class.path") getOrElse ""
|
||||
// XXX scala-library.jar was being added to both boot and regular classpath until 8/18/09
|
||||
// Removing from boot classpath caused build/quick/bin/scala to fail.
|
||||
// Note to self, figure out how/why the bootclasspath is tied up with the locker/quick/pack.
|
||||
|
||||
protected def extdirsDefault =
|
||||
concatPath(syspropopt("java.ext.dirs"), guessedScalaExtDirs)
|
||||
|
||||
protected def assemExtdirsDefault =
|
||||
concatPath(guessedScalaExtDirs)
|
||||
|
||||
protected def pluginsDirDefault =
|
||||
guess(List("misc", "scala-devel", "plugins"), _.isDirectory) getOrElse ""
|
||||
|
||||
def mkPath(base: String, segments: String*) = new File(base, segments.mkString(File.separator))
|
||||
def scalaHome: Option[String] = Option(Properties.scalaHome)
|
||||
|
||||
// examine path relative to scala home and return Some(path) if it meets condition
|
||||
private def guess(xs: List[String], cond: (File) => Boolean): Option[String] = {
|
||||
if (scalaHome.isEmpty) return None
|
||||
val f = mkPath(scalaHome.get, xs: _*)
|
||||
if (cond(f)) Some(f.getAbsolutePath) else None
|
||||
}
|
||||
|
||||
private def guessedScalaBootClassPath: Option[String] =
|
||||
guess(List("lib", "scala-library.jar"), _.isFile) orElse
|
||||
guess(List("classes", "library"), _.isDirectory)
|
||||
|
||||
private def guessedScalaExtDirs: Option[String] =
|
||||
guess(List("lib"), _.isDirectory)
|
||||
def processArgumentString(params: String) = processArguments(splitParams(params), true)
|
||||
|
||||
override def hashCode() = settingSet.hashCode
|
||||
override def equals(that: Any) = that match {
|
||||
|
@ -786,9 +753,7 @@ object Settings {
|
|||
trait ScalacSettings {
|
||||
self: Settings =>
|
||||
|
||||
import scala.tools.util.PathResolver
|
||||
import PathResolver.{ Defaults, Environment }
|
||||
import collection.immutable.TreeSet
|
||||
|
||||
/** A list of all settings */
|
||||
protected var allsettings: Set[Setting] = TreeSet[Setting]()
|
||||
|
@ -816,8 +781,8 @@ trait ScalacSettings {
|
|||
*/
|
||||
// argfiles is only for the help message
|
||||
val argfiles = BooleanSetting ("@<file>", "A text file containing compiler arguments (options and source files)")
|
||||
val bootclasspath = StringSetting ("-bootclasspath", "path", "Override location of bootstrap class files", bootclasspathDefault)
|
||||
val classpath = StringSetting ("-classpath", "path", "Specify where to find user class files", classpathDefault) .
|
||||
val bootclasspath = StringSetting ("-bootclasspath", "path", "Override location of bootstrap class files", "")
|
||||
val classpath = StringSetting ("-classpath", "path", "Specify where to find user class files", "") .
|
||||
withAbbreviation("-cp") .
|
||||
withPostSetHook(self => if (Ylogcp.value) Console.println("Updated classpath to '%s'".format(self.value)))
|
||||
val outdir = OutputSetting (outputDirs, ".")
|
||||
|
@ -825,7 +790,7 @@ trait ScalacSettings {
|
|||
val deprecation = BooleanSetting ("-deprecation", "Output source locations where deprecated APIs are used")
|
||||
val encoding = StringSetting ("-encoding", "encoding", "Specify character encoding used by source files", Properties.sourceEncoding)
|
||||
val explaintypes = BooleanSetting ("-explaintypes", "Explain type errors in more detail")
|
||||
val extdirs = StringSetting ("-extdirs", "dirs", "Override location of installed extensions", extdirsDefault)
|
||||
val extdirs = StringSetting ("-extdirs", "dirs", "Override location of installed extensions", "")
|
||||
val debuginfo = DebugSetting ("-g", "Specify level of generated debugging info", List("none", "source", "line", "vars", "notailcalls"), "vars", "vars")
|
||||
val help = BooleanSetting ("-help", "Print a synopsis of standard options")
|
||||
val make = ChoiceSetting ("-make", "Specify recompilation detection strategy", List("all", "changed", "immediate", "transitive", "transitivenocp"), "all") .
|
||||
|
@ -842,8 +807,8 @@ trait ScalacSettings {
|
|||
val version = BooleanSetting ("-version", "Print product version and exit")
|
||||
|
||||
/** New to classpaths */
|
||||
val javabootclasspath = StringSetting ("-javabootclasspath", "path", "Override java boot classpath.", Environment.javaBootClassPath)
|
||||
val javaextdirs = StringSetting ("-javaextdirs", "path", "Override java extdirs classpath.", Environment.javaExtDirs)
|
||||
val javabootclasspath = StringSetting ("-javabootclasspath", "path", "Override java boot classpath.", "")
|
||||
val javaextdirs = StringSetting ("-javaextdirs", "path", "Override java extdirs classpath.", "")
|
||||
|
||||
/**
|
||||
* -X "Advanced" settings
|
||||
|
@ -851,7 +816,7 @@ trait ScalacSettings {
|
|||
val Xhelp = BooleanSetting ("-X", "Print a synopsis of advanced options")
|
||||
val assemname = StringSetting ("-Xassem-name", "file", "Name of the output assembly (only relevant with -target:msil)", "").dependsOn(target, "msil")
|
||||
val assemrefs = StringSetting ("-Xassem-path", "path", "List of assemblies referenced by the program (only relevant with -target:msil)", ".").dependsOn(target, "msil")
|
||||
val assemextdirs = StringSetting ("-Xassem-extdirs", "dirs", "List of directories containing assemblies, defaults to `lib'", assemExtdirsDefault).dependsOn(target, "msil")
|
||||
val assemextdirs = StringSetting ("-Xassem-extdirs", "dirs", "List of directories containing assemblies, defaults to `lib'", Defaults.scalaLibDir.path).dependsOn(target, "msil")
|
||||
val sourcedir = StringSetting ("-Xsourcedir", "directory", "When -target:msil, the source folder structure is mirrored in output directory.", ".").dependsOn(target, "msil")
|
||||
val checkInit = BooleanSetting ("-Xcheckinit", "Add runtime checks on field accessors. Uninitialized accesses result in an exception being thrown.")
|
||||
val noassertions = BooleanSetting ("-Xdisable-assertions", "Generate no assertions and assumptions")
|
||||
|
@ -868,7 +833,7 @@ trait ScalacSettings {
|
|||
val disable = MultiStringSetting("-Xplugin-disable", "plugin", "Disable a plugin")
|
||||
val showPlugins = BooleanSetting ("-Xplugin-list", "Print a synopsis of loaded plugins")
|
||||
val require = MultiStringSetting("-Xplugin-require", "plugin", "Abort unless a plugin is available")
|
||||
val pluginsDir = StringSetting ("-Xpluginsdir", "path", "Location to find compiler plugins", pluginsDirDefault)
|
||||
val pluginsDir = StringSetting ("-Xpluginsdir", "path", "Path to search compiler plugins", Defaults.scalaPluginPath)
|
||||
val print = PhasesSetting ("-Xprint", "Print out program after")
|
||||
val writeICode = BooleanSetting ("-Xprint-icode", "Log internal icode to *.icode files")
|
||||
val Xprintpos = BooleanSetting ("-Xprint-pos", "Print tree positions (as offsets)")
|
||||
|
|
|
@ -110,7 +110,7 @@ abstract class AbstractFile extends AnyRef with Iterable[AbstractFile] {
|
|||
else true
|
||||
|
||||
/** Does this abstract file represent something which can contain classfiles? */
|
||||
def isClassContainer = isDirectory || Path.isJarOrZip(sfile)
|
||||
def isClassContainer = isDirectory || (file != null && Path.isJarOrZip(sfile))
|
||||
|
||||
/** Create a file on disk, if one does not exist already. */
|
||||
def create: Unit
|
||||
|
|
|
@ -30,7 +30,17 @@ import scala.util.Random.nextASCIIString
|
|||
|
||||
object Path
|
||||
{
|
||||
def isJarOrZip(f: Path) = (f hasExtension "zip") || (f hasExtension "jar")
|
||||
private val ZipMagicNumber = List[Byte](80, 75, 3, 4)
|
||||
|
||||
/** If examineFile is true, it will look at the first four bytes of the file
|
||||
* and see if the magic number indicates it may be a jar or zip.
|
||||
*/
|
||||
def isJarOrZip(f: Path): Boolean = isJarOrZip(f, false)
|
||||
def isJarOrZip(f: Path, examineFile: Boolean): Boolean = (
|
||||
(f hasExtension "zip")
|
||||
|| (f hasExtension "jar")
|
||||
|| (examineFile && f.isFile && (f.toFile.bytes().take(4).toList == ZipMagicNumber))
|
||||
)
|
||||
|
||||
// not certain these won't be problematic, but looks good so far
|
||||
implicit def string2path(s: String): Path = apply(s)
|
||||
|
|
|
@ -148,6 +148,10 @@ abstract class ClassPath[T] {
|
|||
*/
|
||||
def name: String
|
||||
|
||||
/** An URL representing this classpath.
|
||||
*/
|
||||
def asURLs: List[URL]
|
||||
|
||||
/** Info which should be propagated to any sub-classpaths.
|
||||
*/
|
||||
def context: ClassPathContext[T]
|
||||
|
@ -206,6 +210,7 @@ abstract class ClassPath[T] {
|
|||
*/
|
||||
class SourcePath[T](dir: AbstractFile, val context: ClassPathContext[T]) extends ClassPath[T] {
|
||||
def name = dir.name
|
||||
def asURLs = List(dir.sfile.toURL)
|
||||
val sourcepaths: List[AbstractFile] = List(dir)
|
||||
|
||||
lazy val classes: List[ClassRep] = dir partialMap {
|
||||
|
@ -225,6 +230,7 @@ class SourcePath[T](dir: AbstractFile, val context: ClassPathContext[T]) extends
|
|||
*/
|
||||
class DirectoryClassPath(dir: AbstractFile, val context: ClassPathContext[AbstractFile]) extends ClassPath[AbstractFile] {
|
||||
def name = dir.name
|
||||
def asURLs = List(dir.sfile.toURL)
|
||||
val sourcepaths: List[AbstractFile] = Nil
|
||||
|
||||
lazy val classes: List[ClassRep] = dir partialMap {
|
||||
|
@ -248,6 +254,7 @@ class MergedClassPath[T](
|
|||
extends ClassPath[T] {
|
||||
|
||||
def name = entries.head.name
|
||||
def asURLs = entries flatMap (_.asURLs)
|
||||
lazy val sourcepaths: List[AbstractFile] = entries flatMap (_.sourcepaths)
|
||||
|
||||
lazy val classes: List[AnyClassRep] = {
|
||||
|
|
|
@ -99,6 +99,7 @@ class AssemblyClassPath(types: Array[MSILType], namespace: String, val context:
|
|||
if (i < 0) namespace
|
||||
else namespace drop (i + 1)
|
||||
}
|
||||
def asURLs = List(new java.net.URL(name))
|
||||
|
||||
private lazy val first: Int = {
|
||||
var m = 0
|
||||
|
@ -152,7 +153,4 @@ class AssemblyClassPath(types: Array[MSILType], namespace: String, val context:
|
|||
* MSILType values.
|
||||
*/
|
||||
class MsilClassPath(ext: String, user: String, source: String, context: MsilContext)
|
||||
extends MergedClassPath[MSILType](
|
||||
MsilClassPath.assembleEntries(ext, user, source, context),
|
||||
context
|
||||
)
|
||||
extends MergedClassPath[MSILType](MsilClassPath.assembleEntries(ext, user, source, context), context) { }
|
|
@ -45,7 +45,7 @@ object PathResolver {
|
|||
}
|
||||
|
||||
def classPathEnv = envOrElse("CLASSPATH", "")
|
||||
def toolPathEnv = envOrElse("TOOL_CLASSPATH", "")
|
||||
def toolPathEnv = envOrElse("TOOL_CLASSPATH", "") // XXX this should go
|
||||
def classPathProp = propOrElse("java.class.path", "")
|
||||
def javaBootClassPath = propOrElse("sun.boot.class.path", searchForBootClasspath)
|
||||
def javaExtDirs = propOrElse("java.ext.dirs", "")
|
||||
|
@ -53,7 +53,8 @@ object PathResolver {
|
|||
def scalaHome = propOrElse("scala.home", "")
|
||||
def scalaExtDirs = propOrElse("scala.ext.dirs", "") // XXX not in spec
|
||||
|
||||
def classPath = List(classPathProp, classPathEnv) find (_ != "") getOrElse "."
|
||||
// XXX note "." not used yet
|
||||
def classPath = if (classPathProp != "") classPathProp else classPathEnv
|
||||
|
||||
override def toString = """
|
||||
|object Environment {
|
||||
|
@ -64,10 +65,11 @@ object PathResolver {
|
|||
| javaExtDirs = %s
|
||||
| userHome = %s
|
||||
| scalaHome = %s
|
||||
| scalaExtDirs = %s
|
||||
|}""".trim.stripMargin.format(
|
||||
ppcp(classPathEnv), ppcp(toolPathEnv), ppcp(classPathProp), ppcp(javaBootClassPath),
|
||||
ppcp(javaExtDirs), userHome, scalaHome
|
||||
)
|
||||
ppcp(classPathEnv), ppcp(toolPathEnv), ppcp(classPathProp), ppcp(javaBootClassPath),
|
||||
ppcp(javaExtDirs), userHome, scalaHome, ppcp(scalaExtDirs)
|
||||
)
|
||||
}
|
||||
|
||||
/** Default values based on those in Environment as interpretered according
|
||||
|
@ -97,11 +99,12 @@ object PathResolver {
|
|||
def scalaExtDirs = Environment.scalaExtDirs
|
||||
def scalaToolPath = Environment.toolPathEnv match {
|
||||
case "" => scalaBootClassPath
|
||||
// XXX doubtful this is accomplishing anything
|
||||
case x => expandToPath(x.replaceAll("""\$\{SCALA_HOME\}""", scalaHome))
|
||||
}
|
||||
|
||||
def pluginSearchPath = List("misc", "scala-devel", "plugins")
|
||||
def scalaPluginDir = pluginSearchPath map (scalaHomeDir / _) find (_.isDirectory) map (_.path) getOrElse ""
|
||||
def scalaPluginDirs = List("misc", "scala-devel", "plugins")
|
||||
def scalaPluginPath = joincp(scalaPluginDirs map (scalaHomeDir / _ path))
|
||||
|
||||
// The class path that a runner script uses to interpret a program is called the “execution class path”.
|
||||
// The execution class path is the concatenation of the following sub-path.
|
||||
|
@ -125,9 +128,9 @@ object PathResolver {
|
|||
| scalaHome = %s
|
||||
| scalaLibFound = %s
|
||||
| scalaBootClassPath = %s
|
||||
| scalaPluginDir = %s
|
||||
| scalaPluginPath = %s
|
||||
|}""".trim.stripMargin.format(
|
||||
scalaHome, scalaLibFound, ppcp(scalaBootClassPath), scalaPluginDir
|
||||
scalaHome, scalaLibFound, ppcp(scalaBootClassPath), ppcp(scalaPluginPath)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -144,16 +147,41 @@ object PathResolver {
|
|||
if (Environment.scalaHome == "") Environment.classPath
|
||||
else Defaults.scalaBootClassPath
|
||||
}
|
||||
|
||||
private def classPathContainersFromSettings(settings: Settings, context: JavaContext) = {
|
||||
val pr = new PathResolver(settings)
|
||||
import context._
|
||||
import pr.Calculated._
|
||||
|
||||
// XXX how do the contents of lib/* break down between bootclasspath and extdirs?
|
||||
// XXX and what exactly is codebase for?
|
||||
val sources = List(
|
||||
classesInPath(javaBootClassPath), // -javabootclasspath multiple entries, no expansion
|
||||
contentsOfDirsInPath(scalaBootClassPath), // -bootclasspath ???
|
||||
contentsOfDirsInPath(javaExtDirs), // -javaextdirs multiple dirs, each expands to contents
|
||||
contentsOfDirsInPath(scalaExtDirs), // -extdirs ???
|
||||
classesInExpandedPath(classPath), // -classpath multiple entries, first expanding *s
|
||||
classesAtAllURLS(codeBase), // -Xcodebase ??? multiple URLs
|
||||
sourcesInPath(sourcePath) // -sourcepath multiple source entries, no expansion
|
||||
)
|
||||
|
||||
if (settings.Ylogcp.value)
|
||||
Console.println("PathResolver calculated classpath:\n" + pr.Calculated)
|
||||
|
||||
sources
|
||||
}
|
||||
def urlsFromSettings(settings: Settings): List[URL] = urlsFromSettings(settings, DefaultJavaContext)
|
||||
def urlsFromSettings(settings: Settings, context: JavaContext): List[URL] =
|
||||
classPathContainersFromSettings(settings, context).flatten flatMap (_.asURLs)
|
||||
|
||||
private def contextFromSettings(s: Settings) =
|
||||
if (s.inline.value) new JavaContext else DefaultJavaContext
|
||||
|
||||
def fromArgumentString(argString: String): JavaClassPath =
|
||||
fromArgumentList(argString.trim split """\s+""" toList)
|
||||
fromArgumentList(splitParams(argString, _ => ()))
|
||||
|
||||
def fromArgumentList(args: List[String]): JavaClassPath = {
|
||||
val settings = new Settings()
|
||||
settings processArguments args
|
||||
settings.processArguments(args, false)
|
||||
fromSettings(settings, contextFromSettings(settings))
|
||||
}
|
||||
|
||||
|
@ -161,21 +189,8 @@ object PathResolver {
|
|||
fromSettings(settings, contextFromSettings(settings))
|
||||
|
||||
def fromSettings(settings: Settings, context: JavaContext): JavaClassPath = {
|
||||
import context._
|
||||
import settings._
|
||||
|
||||
val sources = List(
|
||||
classesInPath(bootclasspath.value), // -bootclasspath multiple entries, no expansion
|
||||
contentsOfDirsInPath(extdirs.value), // -extdirs multiple dirs, each expands to contents
|
||||
classesInExpandedPath(classpath.value), // -classpath multiple entries, first expanding *s
|
||||
classesAtAllURLS(Xcodebase.value), // -Xcodebase multiple URLs
|
||||
sourcesInPath(sourcepath.value) // -sourcepath multiple source entries, no expansion
|
||||
)
|
||||
|
||||
if (Ylogcp.value)
|
||||
Console.println("Created JavaClassPath from:\n" + (new PathResolver(settings)).Calculated)
|
||||
|
||||
new JavaClassPath(sources, context)
|
||||
val containers = classPathContainersFromSettings(settings, context)
|
||||
new JavaClassPath(containers, context)
|
||||
}
|
||||
|
||||
def fromPathString(path: String): JavaClassPath = fromPathString(path, DefaultJavaContext)
|
||||
|
@ -193,7 +208,7 @@ object PathResolver {
|
|||
}
|
||||
else {
|
||||
val settings = new Settings()
|
||||
val rest = settings.processArguments(args.toList)._2
|
||||
val rest = settings.processArguments(args.toList, false)._2
|
||||
val pr = new PathResolver(settings)
|
||||
println(" COMMAND: 'scala %s'".format(args.mkString(" ")))
|
||||
println("RESIDUAL: 'scala %s'\n".format(rest.mkString(" ")))
|
||||
|
@ -289,12 +304,12 @@ class PathResolver(settings: Settings) {
|
|||
*/
|
||||
object Calculated {
|
||||
def javaBootClassPath = cmdLineOrElse("javabootclasspath", Environment.javaBootClassPath)
|
||||
def javaExtDirs = cmdLineOrElse("javaextdirs", Environment.javaExtDirs)
|
||||
def scalaBootClassPath = cmdLineOrElse("bootclasspath", Defaults.scalaBootClassPath)
|
||||
def javaExtDirs = cmdLineOrElse("javaextdirs", Environment.javaExtDirs)
|
||||
def scalaExtDirs = cmdLineOrElse("extdirs", Defaults.scalaExtDirs)
|
||||
def classPath = cmdLineOrElse("classpath", Environment.classPath)
|
||||
def sourcePath = cmdLineOrElse("sourcepath", "")
|
||||
def codeBase = cmdLineOrElse("Ycodebase", "") // XXX
|
||||
def classPath = cmdLineOrElse("cp", Environment.classPath)
|
||||
def codeBase = cmdLineOrElse("Ycodebase", "")
|
||||
|
||||
def referencePath = List(
|
||||
// 1. The value of -javabootclasspath if it is set, or the Java bootstrap class path.
|
||||
|
@ -310,26 +325,25 @@ class PathResolver(settings: Settings) {
|
|||
scalaExtDirs,
|
||||
// 5. The first available path below.
|
||||
// * The value of -classpath or -cp.
|
||||
// * ---> XXX what about java.class.path?
|
||||
// * The value of the CLASSPATH environment variable.
|
||||
// * The current directory (that is the location of ".").
|
||||
//
|
||||
// XXX doesn't mention java.class.path
|
||||
classPath
|
||||
if (classPath == "") "." else classPath
|
||||
)
|
||||
|
||||
override def toString = """
|
||||
|object Calculated {
|
||||
| javaBootClassPath = %s
|
||||
| javaExtDirs = %s
|
||||
| scalaBootClassPath = %s
|
||||
| javaExtDirs = %s
|
||||
| scalaExtDirs = %s
|
||||
| classPath = %s
|
||||
| sourcePath = %s
|
||||
| codeBase = %s
|
||||
| classPath = %s
|
||||
|}""".trim.stripMargin.format(
|
||||
ppcp(javaBootClassPath), ppcp(javaExtDirs),
|
||||
ppcp(scalaBootClassPath), ppcp(scalaExtDirs),
|
||||
ppcp(sourcePath), codeBase, ppcp(classPath)
|
||||
ppcp(javaBootClassPath), ppcp(scalaBootClassPath),
|
||||
ppcp(javaExtDirs), ppcp(scalaExtDirs),
|
||||
ppcp(classPath), ppcp(sourcePath), codeBase
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,10 @@ package nest
|
|||
|
||||
import scala.tools.nsc.{Global, Settings, CompilerCommand, FatalError}
|
||||
import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
|
||||
import scala.tools.util.PathResolver
|
||||
|
||||
import java.io.{File, BufferedReader, PrintWriter, FileReader, FileWriter, StringWriter}
|
||||
import File.pathSeparator
|
||||
|
||||
class ExtConsoleReporter(override val settings: Settings, reader: BufferedReader, var writer: PrintWriter) extends ConsoleReporter(settings, reader, writer) {
|
||||
def this(settings: Settings) = {
|
||||
|
@ -24,13 +26,10 @@ abstract class SimpleCompiler {
|
|||
def compile(out: Option[File], files: List[File], kind: String, log: File): Boolean
|
||||
}
|
||||
|
||||
class TestSettings(fileMan: FileManager) extends {
|
||||
override val bootclasspathDefault =
|
||||
System.getProperty("sun.boot.class.path", "") + File.pathSeparator +
|
||||
fileMan.LATEST_LIB
|
||||
override val extdirsDefault =
|
||||
System.getProperty("java.ext.dirs", "")
|
||||
} with Settings(x => ())
|
||||
class TestSettings(fileMan: FileManager) extends Settings(x => ()) {
|
||||
javabootclasspath.value =
|
||||
PathResolver.Environment.javaBootClassPath + (pathSeparator + fileMan.LATEST_LIB)
|
||||
}
|
||||
|
||||
class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler {
|
||||
def newGlobal(settings: Settings, reporter: Reporter): Global =
|
||||
|
@ -63,14 +62,14 @@ class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler {
|
|||
if (opt1.isEmpty) ""
|
||||
else {
|
||||
def absolutize(path: String): List[String] = {
|
||||
val args = (path substring 9 split File.pathSeparator).toList
|
||||
val args = (path substring 9 split pathSeparator).toList
|
||||
val plugins = args map (arg =>
|
||||
if (new File(arg).isAbsolute) arg
|
||||
else fileManager.TESTROOT+File.separator+arg
|
||||
)
|
||||
plugins
|
||||
}
|
||||
" -Xplugin:"+((opt1 flatMap absolutize) mkString File.pathSeparator)
|
||||
" -Xplugin:"+((opt1 flatMap absolutize) mkString pathSeparator)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -281,6 +281,7 @@ object Main {
|
|||
* The short name of the package (without prefix)
|
||||
*/
|
||||
def name: String = ""
|
||||
def asURLs = Nil
|
||||
val context = DefaultJavaContext
|
||||
val classes: List[ClassRep] = Nil
|
||||
val packages: List[ClassPath[AbstractFile]] = Nil
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
|
||||
scala scala.tools.util.PathResolver $*
|
||||
WHICH=`which scala`
|
||||
BASE=`dirname $WHICH`
|
||||
LIBDIR=$BASE/../lib
|
||||
|
||||
echo Using ${WHICH}.
|
||||
echo
|
||||
|
||||
java -cp "${LIBDIR}/*" scala.tools.util.PathResolver $*
|
||||
|
|
Loading…
Reference in New Issue