summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/CompileClient.scala26
-rw-r--r--src/compiler/scala/tools/nsc/CompileServer.scala48
-rw-r--r--src/compiler/scala/tools/nsc/CompilerCommand.scala22
-rw-r--r--src/compiler/scala/tools/nsc/OfflineCompilerCommand.scala30
-rw-r--r--src/compiler/scala/tools/nsc/settings/FscSettings.scala37
-rw-r--r--src/compiler/scala/tools/nsc/settings/MutableSettings.scala2
6 files changed, 115 insertions, 50 deletions
diff --git a/src/compiler/scala/tools/nsc/CompileClient.scala b/src/compiler/scala/tools/nsc/CompileClient.scala
index 9987eb0204..fd4f777890 100644
--- a/src/compiler/scala/tools/nsc/CompileClient.scala
+++ b/src/compiler/scala/tools/nsc/CompileClient.scala
@@ -16,18 +16,21 @@ import sys.SystemProperties.preferIPv4Stack
class StandardCompileClient extends HasCompileSocket with CompileOutputCommon {
lazy val compileSocket: CompileSocket = CompileSocket
- val versionMsg = "Fast " + Properties.versionMsg
- var verbose = false
+ val versionMsg = "Fast " + Properties.versionMsg
+ var verbose = false
def process(args: Array[String]): Int = {
- val fscArgs = args.toList
- val settings = new FscSettings
- val command = new CompilerCommand(fscArgs, settings)
- verbose = settings.verbose.value
- val shutdown = settings.shutdown.value
- val vmArgs = settings.jvmargs.unparse ++ settings.defines.unparse ++ (
- if (settings.preferIPv4.value) List("-D%s=true".format(preferIPv4Stack.key)) else Nil
- )
+ // Trying to get out in front of the log messages in case we're
+ // going from verbose to not verbose.
+ verbose = (args contains "-verbose")
+
+ val settings = new FscSettings(Console.println)
+ val command = new OfflineCompilerCommand(args.toList, settings)
+ val shutdown = settings.shutdown.value
+ val extraVmArgs = if (settings.preferIPv4.value) List("-D%s=true".format(preferIPv4Stack.key)) else Nil
+
+ val vmArgs = settings.jvmargs.unparse ++ settings.defines.unparse ++ extraVmArgs
+ val fscArgs = args.toList ++ command.extraFscArgs
if (settings.version.value) {
Console println versionMsg
@@ -35,7 +38,8 @@ class StandardCompileClient extends HasCompileSocket with CompileOutputCommon {
}
info(versionMsg)
- info(fscArgs.mkString("[Given arguments: ", " ", "]"))
+ info(args.mkString("[Given arguments: ", " ", "]"))
+ info(fscArgs.mkString("[Transformed arguments: ", " ", "]"))
info(vmArgs.mkString("[VM arguments: ", " ", "]"))
val socket =
diff --git a/src/compiler/scala/tools/nsc/CompileServer.scala b/src/compiler/scala/tools/nsc/CompileServer.scala
index a34be6226b..866975b414 100644
--- a/src/compiler/scala/tools/nsc/CompileServer.scala
+++ b/src/compiler/scala/tools/nsc/CompileServer.scala
@@ -21,7 +21,9 @@ import settings.FscSettings
*/
class StandardCompileServer extends SocketServer {
lazy val compileSocket: CompileSocket = CompileSocket
+
private var compiler: Global = null
+ private def clearCompiler() = compiler = null
var reporter: ConsoleReporter = _
var shutdown = false
@@ -58,7 +60,7 @@ class StandardCompileServer extends SocketServer {
(totalMemory - freeMemory).toDouble / maxMemory.toDouble > MaxCharge
}
- protected def newOfflineCompilerCommand(arguments: List[String], settings: Settings) =
+ protected def newOfflineCompilerCommand(arguments: List[String], settings: FscSettings): OfflineCompilerCommand =
new OfflineCompilerCommand(arguments, settings)
/** Problematically, Settings are only considered equal if every setting
@@ -69,7 +71,7 @@ class StandardCompileServer extends SocketServer {
* and which do not interestingly influence compilation products.
*/
def unequalSettings(s1: Settings, s2: Settings): Set[Settings#Setting] = {
- val ignoreSettings = Set("-d", "-encoding", "-verbose")
+ val ignoreSettings = Set("-d", "-encoding", "-currentDir")
def trim (s: Settings): Set[Settings#Setting] = (
s.userSetSettings.toSet[Settings#Setting] filterNot (ss => ignoreSettings exists (ss respondsTo _))
)
@@ -80,7 +82,6 @@ class StandardCompileServer extends SocketServer {
}
def session() {
- printMemoryStats()
val password = compileSocket getPassword port
val guessedPassword = in.readLine()
val input = in.readLine()
@@ -92,29 +93,34 @@ class StandardCompileServer extends SocketServer {
if (input == null || password != guessedPassword)
return
- val args = input.split("\0", -1).toList
- val settings = new FscSettings(fscError)
- val command = newOfflineCompilerCommand(args, settings)
+ val args = input.split("\0", -1).toList
+ val newSettings = new FscSettings(fscError)
+ this.verbose = newSettings.verbose.value
+ val command = newOfflineCompilerCommand(args, newSettings)
+
+ info("Settings after normalizing paths: " + newSettings)
+ printMemoryStats()
// Update the idle timeout if given
- if (!settings.idleMins.isDefault) {
- val mins = settings.idleMins.value
+ if (!newSettings.idleMins.isDefault) {
+ val mins = newSettings.idleMins.value
if (mins == 0) echo("Disabling idle timeout on compile server.")
else echo("Setting idle timeout to " + mins + " minutes.")
this.idleMinutes = mins
}
- if (settings.shutdown.value) {
+ if (newSettings.shutdown.value) {
shutdown = true
return out.println("[Compile server exited]")
}
- if (settings.reset.value) {
- compiler = null
- return out.println("[Compile server was reset]")
+ if (newSettings.reset.value) {
+ clearCompiler()
+ out.println("[Compile server was reset]")
+ if (command.files.isEmpty)
+ return
}
- this.verbose = settings.verbose.value
- reporter = new ConsoleReporter(command.settings, in, out) {
+ reporter = new ConsoleReporter(newSettings, in, out) {
// disable prompts, so that compile server cannot block
override def displayPrompt = ()
}
@@ -124,7 +130,7 @@ class StandardCompileServer extends SocketServer {
info("[Compiler version: " + Properties.versionString + ".]")
return false
}
- val unequal = unequalSettings(command.settings, compiler.settings)
+ val unequal = unequalSettings(newSettings, compiler.settings)
if (unequal.nonEmpty) {
info("[Replacing compiler with new instance because settings are unequal.]")
info("[Asymmetric settings: " + unequal.mkString(", ") + "]")
@@ -133,24 +139,26 @@ class StandardCompileServer extends SocketServer {
}
if (command.shouldStopWithInfo)
- reporter.info(null, command.getInfoMessage(newGlobal(command.settings, reporter)), true)
+ reporter.info(null, command.getInfoMessage(newGlobal(newSettings, reporter)), true)
else if (command.files.isEmpty)
reporter.info(null, command.usageMsg, true)
else {
if (isCompilerReusable) {
- compiler.settings = command.settings
+ info("[Reusing existing Global instance.]")
+ compiler.settings = newSettings
compiler.reporter = reporter
}
else {
- compiler = newGlobal(command.settings, reporter)
+ compiler = newGlobal(newSettings, reporter)
}
val c = compiler
try new c.Run() compile command.files
catch {
case ex @ FatalError(msg) =>
reporter.error(null, "fatal error: " + msg)
- compiler = null
+ clearCompiler()
case ex =>
+ warn("Compile server encountered fatal condition: " + ex)
shutdown = true
throw ex
}
@@ -158,7 +166,7 @@ class StandardCompileServer extends SocketServer {
reporter.printSummary()
if (isMemoryFullEnough) {
info("Nulling out compiler due to memory utilization.")
- compiler = null
+ clearCompiler()
}
}
}
diff --git a/src/compiler/scala/tools/nsc/CompilerCommand.scala b/src/compiler/scala/tools/nsc/CompilerCommand.scala
index 1c0fd8b9de..f2c217e290 100644
--- a/src/compiler/scala/tools/nsc/CompilerCommand.scala
+++ b/src/compiler/scala/tools/nsc/CompilerCommand.scala
@@ -46,22 +46,30 @@ class CompilerCommand(arguments: List[String], val settings: Settings) {
|
""".stripMargin.trim + "\n\n"
+ val shortUsage = "Usage: %s <options> <source files>" format cmdName
+ def createUsagePreface(shouldExplain: Boolean) =
+ if (shouldExplain) shortUsage + "\n" + explainAdvanced else ""
+
/** Creates a help message for a subset of options based on cond */
- def createUsageMsg(label: String, shouldExplain: Boolean, cond: Setting => Boolean): String = {
+ def createUsageMsg(cond: Setting => Boolean): String = {
def helpStr(s: Setting) = format(s.helpSyntax) + " " + s.helpDescription
-
- val usage = "Usage: %s <options> <source files>\n" format cmdName
- val explain = if (shouldExplain) explainAdvanced else ""
- val prefix = label + " options include:\n "
-
// Separating out any debugging options from others for easier reading
val (debug, rest) = (settings.visibleSettings filter cond).toList sortBy (_.name) partition (_.isForDebug)
- (rest map helpStr).mkString(usage + explain + prefix, "\n ", "\n") + (
+ (rest map helpStr).mkString("", "\n ", "\n") + (
if (debug.isEmpty) ""
else (debug map helpStr).mkString("\nAdditional debug settings:\n ", "\n ", "\n")
)
}
+ def createUsageMsg(label: String, shouldExplain: Boolean, cond: Setting => Boolean): String = {
+ val prefix = List(
+ Some(shortUsage),
+ Some(explainAdvanced) filter (_ => shouldExplain),
+ Some(label + " options include:\n ")
+ ).flatten mkString "\n"
+
+ prefix + createUsageMsg(cond)
+ }
/** Messages explaining usage and options */
def usageMsg = createUsageMsg("where possible standard", false, _.isStandard)
diff --git a/src/compiler/scala/tools/nsc/OfflineCompilerCommand.scala b/src/compiler/scala/tools/nsc/OfflineCompilerCommand.scala
index 786bcb1eb5..ef974da965 100644
--- a/src/compiler/scala/tools/nsc/OfflineCompilerCommand.scala
+++ b/src/compiler/scala/tools/nsc/OfflineCompilerCommand.scala
@@ -5,10 +5,38 @@
package scala.tools.nsc
+import settings.FscSettings
+import io.Directory
+
/** A compiler command for the offline compiler.
*
* @author Martin Odersky and Lex Spoon
*/
-class OfflineCompilerCommand(arguments: List[String], settings: Settings) extends CompilerCommand(arguments, settings) {
+class OfflineCompilerCommand(arguments: List[String], settings: FscSettings) extends CompilerCommand(arguments, settings) {
+ import settings.currentDir
+ def extraFscArgs = List(currentDir.name, currentDir.value)
+
+ locally {
+ // if -current-dir is unset, we're on the client and need to obtain it.
+ if (currentDir.isDefault) {
+ // Prefer env variable PWD to system property user.dir because the former
+ // deals better with paths not rooted at / (filesystem mounts.)
+ val baseDirectory = System.getenv("PWD") match {
+ case null => Directory.Current getOrElse Directory("/")
+ case dir => Directory(dir)
+ }
+ currentDir.value = baseDirectory.path
+ }
+ else {
+ // Otherwise we're on the server and will use it to absolutize the paths.
+ settings.absolutize(currentDir.value)
+ }
+ }
+
override def cmdName = "fsc"
+ override def usageMsg = (
+ createUsageMsg("where possible fsc", false, x => x.isStandard && settings.isFscSpecific(x.name)) +
+ "\nStandard scalac options also available:\n " +
+ createUsageMsg(x => x.isStandard && !settings.isFscSpecific(x.name))
+ )
}
diff --git a/src/compiler/scala/tools/nsc/settings/FscSettings.scala b/src/compiler/scala/tools/nsc/settings/FscSettings.scala
index a219148b16..bb62750026 100644
--- a/src/compiler/scala/tools/nsc/settings/FscSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/FscSettings.scala
@@ -8,28 +8,45 @@ package nsc
package settings
import util.ClassPath
+import io.{ Directory, Path, AbstractFile }
class FscSettings(error: String => Unit) extends Settings(error) {
outer =>
- def this() = this(Console.println)
+ locally {
+ disable(prompt)
+ disable(resident)
+ }
+ val currentDir = StringSetting ("-current-dir", "path", "Base directory for resolving relative paths", "").internalOnly()
val reset = BooleanSetting("-reset", "Reset compile server caches")
val shutdown = BooleanSetting("-shutdown", "Shutdown compile server")
val server = StringSetting ("-server", "hostname:portnumber", "Specify compile server socket", "")
- val preferIPv4 = BooleanSetting("-ipv4", "Use IPv4 rather than IPv6 for the server socket")
- val absClasspath = BooleanSetting("-absolute-cp", "Make classpath elements absolute paths before sending to server") .
- withPostSetHook (_ => absolutizeClasspath())
+ val preferIPv4 = BooleanSetting("-ipv4", "Use IPv4 rather than IPv6 for the server socket")
val idleMins = IntSetting ("-max-idle", "Set idle timeout in minutes for fsc (use 0 for no timeout)",
30, Some(0, Int.MaxValue), (_: String) => None)
- disable(prompt)
- disable(resident)
+ // For improved help output, separating fsc options from the others.
+ def fscSpecific = Set[Settings#Setting](
+ currentDir, reset, shutdown, server, preferIPv4, idleMins
+ )
+ val isFscSpecific: String => Boolean = fscSpecific map (_.name)
+
+ /** If a setting (other than a PathSetting) represents a path or paths.
+ * For use in absolutization.
+ */
+ private def holdsPath = Set[Settings#Setting](
+ d, dependencyfile, pluginsDir, Ygenjavap
+ )
- // Make the classpath absolute: for going from client to server.
- private def absolutizeClasspath() {
- userSetSettings collect {
- case x: PathSetting => x.value = ClassPath.makeAbsolute(x.value)
+ /** All user set settings rewritten with absolute paths. */
+ def absolutize(root: Path) {
+ def rewrite(p: String) = (root resolve Path(p)).normalize.path
+ userSetSettings foreach {
+ case p: OutputSetting => p.outputDirs setSingleOutput AbstractFile.getDirectory(rewrite(p.value))
+ case p: PathSetting => p.value = ClassPath.map(p.value, rewrite)
+ case p: StringSetting => if (holdsPath(p)) p.value = rewrite(p.value)
+ case _ => ()
}
}
}
diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
index b485d4725a..12b9ef7154 100644
--- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
@@ -479,7 +479,7 @@ class MutableSettings(val errorFn: String => Unit) extends AbsSettings with Scal
/** Set the output directory. */
class OutputSetting private[nsc](
- outputDirs: OutputDirs,
+ private[nsc] val outputDirs: OutputDirs,
default: String)
extends StringSetting("-d", "directory", "Specify where to place generated class files", default) {
value = default