From e9a60f236b00d417ddd6fd2ac30448f0228b2921 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Thu, 11 Feb 2010 15:10:45 +0000 Subject: More work on classpaths. 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. --- src/compiler/scala/tools/nsc/CompileClient.scala | 1 + src/compiler/scala/tools/nsc/CompilerCommand.scala | 2 +- .../scala/tools/nsc/GenericRunnerCommand.scala | 4 +- .../scala/tools/nsc/MainGenericRunner.scala | 88 +++++++-------------- src/compiler/scala/tools/nsc/Settings.scala | 85 ++++++-------------- src/compiler/scala/tools/nsc/io/AbstractFile.scala | 2 +- src/compiler/scala/tools/nsc/io/Path.scala | 12 ++- src/compiler/scala/tools/nsc/util/ClassPath.scala | 7 ++ .../scala/tools/nsc/util/MsilClassPath.scala | 6 +- src/compiler/scala/tools/util/PathResolver.scala | 90 +++++++++++++--------- .../scala/tools/partest/nest/CompileManager.scala | 17 ++-- src/scalap/scala/tools/scalap/Main.scala | 1 + tools/pathResolver | 9 ++- 13 files changed, 147 insertions(+), 177 deletions(-) diff --git a/src/compiler/scala/tools/nsc/CompileClient.scala b/src/compiler/scala/tools/nsc/CompileClient.scala index 4b387298f4..71f7ea811e 100644 --- a/src/compiler/scala/tools/nsc/CompileClient.scala +++ b/src/compiler/scala/tools/nsc/CompileClient.scala @@ -108,6 +108,7 @@ class StandardCompileClient { Console println fromServer loop } + loop } wasError } diff --git a/src/compiler/scala/tools/nsc/CompilerCommand.scala b/src/compiler/scala/tools/nsc/CompilerCommand.scala index 95a2fff8de..5d0c0a0196 100644 --- a/src/compiler/scala/tools/nsc/CompilerCommand.scala +++ b/src/compiler/scala/tools/nsc/CompilerCommand.scala @@ -81,7 +81,7 @@ class CompilerCommand( case x => List(x) } - settings processArguments expandedArguments + settings.processArguments(expandedArguments, true) } else (true, Nil) } diff --git a/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala b/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala index fa0b5bce9c..a0c70ef72a 100644 --- a/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala +++ b/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala @@ -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) } diff --git a/src/compiler/scala/tools/nsc/MainGenericRunner.scala b/src/compiler/scala/tools/nsc/MainGenericRunner.scala index 0b93be582c..80af84e857 100644 --- a/src/compiler/scala/tools/nsc/MainGenericRunner.scala +++ b/src/compiler/scala/tools/nsc/MainGenericRunner.scala @@ -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,21 +25,32 @@ import Properties.{ versionString, copyrightString } object MainGenericRunner { def main(args: Array[String]) { def errorFn(str: String) = Console println str + 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) val command = new GenericRunnerCommand(args.toList, errorFn) - val settings = command.settings - def sampleCompiler = new Global(settings) + 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)) - // 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 + processSettings() if (settings.version.value) return errorFn("Scala code runner %s -- %s".format(versionString, copyrightString)) @@ -46,58 +58,11 @@ object MainGenericRunner { 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 createLoop(): InterpreterLoop = { - val loop = new InterpreterLoop - loop main settings - loop - } + 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 { diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala index 3c24d86a99..e5fd9299eb 100644 --- a/src/compiler/scala/tools/nsc/Settings.scala +++ b/src/compiler/scala/tools/nsc/Settings.scala @@ -14,6 +14,7 @@ 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) @@ -21,9 +22,21 @@ class Settings(errorFn: String => Unit) extends ScalacSettings { /** 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 ("@", "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)") diff --git a/src/compiler/scala/tools/nsc/io/AbstractFile.scala b/src/compiler/scala/tools/nsc/io/AbstractFile.scala index af93cafb68..216579e376 100644 --- a/src/compiler/scala/tools/nsc/io/AbstractFile.scala +++ b/src/compiler/scala/tools/nsc/io/AbstractFile.scala @@ -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 diff --git a/src/compiler/scala/tools/nsc/io/Path.scala b/src/compiler/scala/tools/nsc/io/Path.scala index 2b7f2620d6..b43697d4ce 100644 --- a/src/compiler/scala/tools/nsc/io/Path.scala +++ b/src/compiler/scala/tools/nsc/io/Path.scala @@ -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) diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala index 3f6bed5227..c0c1f7a417 100644 --- a/src/compiler/scala/tools/nsc/util/ClassPath.scala +++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala @@ -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] = { diff --git a/src/compiler/scala/tools/nsc/util/MsilClassPath.scala b/src/compiler/scala/tools/nsc/util/MsilClassPath.scala index 2de334c370..b61fffafaf 100644 --- a/src/compiler/scala/tools/nsc/util/MsilClassPath.scala +++ b/src/compiler/scala/tools/nsc/util/MsilClassPath.scala @@ -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) { } \ No newline at end of file diff --git a/src/compiler/scala/tools/util/PathResolver.scala b/src/compiler/scala/tools/util/PathResolver.scala index 72dcac36fe..a7ccc0f240 100644 --- a/src/compiler/scala/tools/util/PathResolver.scala +++ b/src/compiler/scala/tools/util/PathResolver.scala @@ -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 ) } diff --git a/src/partest/scala/tools/partest/nest/CompileManager.scala b/src/partest/scala/tools/partest/nest/CompileManager.scala index e9d9d65390..8d440b398f 100644 --- a/src/partest/scala/tools/partest/nest/CompileManager.scala +++ b/src/partest/scala/tools/partest/nest/CompileManager.scala @@ -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) } ) } diff --git a/src/scalap/scala/tools/scalap/Main.scala b/src/scalap/scala/tools/scalap/Main.scala index 9534b2f84e..b9c2ab0cc8 100644 --- a/src/scalap/scala/tools/scalap/Main.scala +++ b/src/scalap/scala/tools/scalap/Main.scala @@ -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 diff --git a/tools/pathResolver b/tools/pathResolver index 4deb8595e9..efff45ea62 100755 --- a/tools/pathResolver +++ b/tools/pathResolver @@ -1,4 +1,11 @@ #!/bin/sh # -scala scala.tools.util.PathResolver $* \ No newline at end of file +WHICH=`which scala` +BASE=`dirname $WHICH` +LIBDIR=$BASE/../lib + +echo Using ${WHICH}. +echo + +java -cp "${LIBDIR}/*" scala.tools.util.PathResolver $* -- cgit v1.2.3