summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authormichelou <michelou@epfl.ch>2011-11-16 20:35:21 +0000
committermichelou <michelou@epfl.ch>2011-11-16 20:35:21 +0000
commit44741eee5336b6d8f195d01cf993debf537124c7 (patch)
tree3044bf16965cbb16837c69a025758cfa93ed2be6 /src/compiler
parent3b0fd925a85f2d5cdab7c1467fb60fce287114f3 (diff)
downloadscala-44741eee5336b6d8f195d01cf993debf537124c7.tar.gz
scala-44741eee5336b6d8f195d01cf993debf537124c7.tar.bz2
scala-44741eee5336b6d8f195d01cf993debf537124c7.zip
Updated/fixed the following two Scala Ant tasks:
scalac (ant.Scalac) - added attributes `dependencyfile`, `explaintypes`, `nobootcp`, `nowarn` and `usejavacp` - added support for nested element `compilerarg` (see Ant manual) in order to pass prefix settings (eg. -J-Xbootclasspath, -Ddebug=true) to nsc.CompileClient - updated list of permissible values for compiler phases fsc (ant.FastScalac) - added attributes `ip4` and `maxIdle` in addition to `reset`, `server` and `shutdown` (and forwards them to nsc.CompileClient) - also forwards prefix settings `jvmargs` and `defines`, and boolean settings `explaintypes`, `nospecialization`, `nowarn`, `optimise`, `unchecked` and `usejavacp` to nsc.CompileClient - fixed CompileClient.process if-test Nota Bene I added the following element to partest.PartestTask (commit is pending) in order to automatically test the Scala Ant tasks: <anttests dir="${partest.dir}/${partest.srcdir}/ant" includes="*build.xml"/> Here is the output: [user@localhost scala]$ ant test.ant Buildfile: /home/user/workspace/scala/build.xml [echo] Forking with JVM opts: -Xms1536M [...] init: [echo] Build number is '2.10.0.r26022-b20111116212958' [echo] Built 16 November 2011, 21:29:58 [...] [...] test.ant: [partest] Running ant task tests [partest] testing: [...]/files/ant/fsc-build.xml [ OK ] [partest] testing: [...]/files/ant/scaladoc-build.xml [ OK ] [partest] testing: [...]/files/ant/scalac-build.xml [ OK ] [partest] Test suite finished with no failures. BUILD SUCCESSFUL Total time: 12 seconds
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/ant/FastScalac.scala146
-rw-r--r--src/compiler/scala/tools/ant/Scalac.scala104
2 files changed, 182 insertions, 68 deletions
diff --git a/src/compiler/scala/tools/ant/FastScalac.scala b/src/compiler/scala/tools/ant/FastScalac.scala
index ca60a55f02..96d242ae07 100644
--- a/src/compiler/scala/tools/ant/FastScalac.scala
+++ b/src/compiler/scala/tools/ant/FastScalac.scala
@@ -8,6 +8,11 @@
package scala.tools.ant
+import org.apache.tools.ant.Project
+
+import scala.tools.nsc.Settings
+import scala.tools.nsc.settings.FscSettings
+
/** An Ant task to compile with the fast Scala compiler (`fsc`).
*
* In addition to the attributes shared with the `Scalac` task, this task
@@ -15,6 +20,8 @@ package scala.tools.ant
* - `reset`
* - `server`
* - `shutdown`
+ * - `ipv4`
+ * - `maxIdle`
*
* @author Stephane Micheloud
*/
@@ -26,6 +33,10 @@ class FastScalac extends Scalac {
private var shutdownServer: Boolean = false
+ private var useIPv4: Boolean = false
+
+ private var idleMinutes: Option[Int] = None
+
/*============================================================================*\
** Properties setters **
\*============================================================================*/
@@ -48,64 +59,95 @@ class FastScalac extends Scalac {
*/
def setShutdown(input: Boolean) { shutdownServer = input }
+ /** Sets the `ipv4` attribute. Used by [[http://ant.apache.org Ant]].
+ *
+ * @param input The value for `ipv4`.
+ */
+ def setIPv4(input: Boolean) { useIPv4 = input }
+
+ /** Sets the `maxIdle` attribute. Used by [[http://ant.apache.org Ant]].
+ *
+ * @param input The value for `maxIdle`.
+ */
+ def setMaxIdle(input: Int) { if (0 <= input) idleMinutes = Some(input) }
+
/*============================================================================*\
** The execute method **
\*============================================================================*/
+ override protected def newSettings(error: String=>Unit): Settings =
+ new FscSettings(error)
+
/** Performs the compilation. */
- override def execute() = {
+ override def execute() {
val (settings, sourceFiles, javaOnly) = initialize
- val s = settings
-
- if (!sourceFiles.isEmpty && !javaOnly) {
- def trim(xs: List[String]) = xs filter (x => x.length > 0)
- val reset = settings.BooleanSetting("-reset", "Reset compile server caches")
- val shutdown = settings.BooleanSetting("-shutdown", "Shutdown compile server")
-
- reset.value = resetCaches
- shutdown.value = shutdownServer
-
- /** XXX Since fsc is largely unmaintained, the set of options being
- * individually assessed here is likely to bear little relationship to
- * the current set of options. Most likely this manifests in confusing
- * and very difficult to debug behavior in fsc. We should warn or fix.
- */
- val stringSettings =
- List(s.outdir, s.classpath, s.bootclasspath, s.extdirs, s.encoding) flatMap (x => List(x.name, x.value))
-
- val serverOption =
- serverAddr.toList flatMap (x => List("-server", x)) // '-server' option
-
- val choiceSettings =
- List(s.debuginfo, s.target) map (x => "%s:%s".format(x.name, x.value))
-
- val booleanSettings =
- List(s.debug, s.deprecation, s.verbose, reset, shutdown) map (x => if (x.value) List(x.name) else Nil) flatten
-
- val phaseSetting = {
- val s = settings.log
- if (s.value.isEmpty) Nil
- else List("%s:%s".format(s.name, s.value.mkString(",")))
- }
-
- val cmdOptions =
- stringSettings ::: serverOption ::: choiceSettings ::: booleanSettings ::: phaseSetting
-
- val args = (cmdOptions ::: (sourceFiles map (_.toString))).toArray
- try {
- if (scala.tools.nsc.CompileClient.process(args) && failonerror)
- buildError("Compile failed; see the compiler error output for details.")
- }
- catch {
- case exception: Throwable if exception.getMessage ne null =>
- exception.printStackTrace()
- buildError("Compile failed because of an internal compiler error (" +
- exception.getMessage + "); see the error output for details.")
- case exception =>
- exception.printStackTrace()
- buildError("Compile failed because of an internal compiler error " +
- "(no error message provided); see the error output for details.")
- }
+ if (sourceFiles.isEmpty || javaOnly)
+ return
+
+ // initialize fsc specific settings
+ val s = settings.asInstanceOf[FscSettings] // safe (newSettings)
+ s.reset.value = resetCaches
+ if (!serverAddr.isEmpty) s.server.value = serverAddr.get
+ s.shutdown.value = shutdownServer
+ s.preferIPv4.value = useIPv4
+ if (!idleMinutes.isEmpty) s.idleMins.value = idleMinutes.get
+
+ val prefixSettings =
+ List(
+ /*scalac*/
+ s.jvmargs, s.defines
+ ) flatMap (_.value)
+
+ val stringSettings =
+ List(
+ /*scalac*/
+ s.bootclasspath, s.classpath, s.extdirs, s.dependencyfile, s.encoding,
+ s.outdir, s.sourcepath,
+ /*fsc*/
+ s.server
+ ) filter (_.value != "") flatMap (x => List(x.name, x.value))
+
+ val choiceSettings =
+ List(
+ /*scalac*/
+ s.debuginfo, s.target
+ ) map (x => "%s:%s".format(x.name, x.value))
+
+ val booleanSettings =
+ List(
+ /*scalac*/
+ s.debug, s.deprecation, s.explaintypes, s.nospecialization, s.nowarn,
+ s.optimise, s.unchecked, s.usejavacp, s.verbose,
+ /*fsc*/
+ s.preferIPv4, s.reset, s.shutdown
+ ) filter (_.value) map (_.name)
+
+ val intSettings =
+ List(
+ /*fsc*/
+ s.idleMins
+ ) filter (x => x.value != x.default) flatMap (x => List(x.name, x.value.toString))
+
+ val phaseSetting = {
+ val s = settings.log
+ if (s.value.isEmpty) Nil
+ else List("%s:%s".format(s.name, s.value.mkString(",")))
+ }
+
+ val cmdOptions =
+ prefixSettings ::: stringSettings ::: choiceSettings ::: booleanSettings ::: intSettings ::: phaseSetting
+
+ val args = (cmdOptions ::: (sourceFiles map (_.toString))).toArray
+ log("FastScalac args="+args.mkString(" "), Project.MSG_DEBUG)
+ try {
+ if (!scala.tools.nsc.CompileClient.process(args) && failonerror)
+ buildError("Compile failed; see the compiler error output for details.")
+ }
+ catch {
+ case ex: Throwable =>
+ ex.printStackTrace()
+ val msg = if (ex.getMessage == null) "no error message provided" else ex.getMessage
+ buildError("Compile failed because of an internal compiler error (" + msg + "); see the error output for details.")
}
}
}
diff --git a/src/compiler/scala/tools/ant/Scalac.scala b/src/compiler/scala/tools/ant/Scalac.scala
index eee286e5dd..72330615cc 100644
--- a/src/compiler/scala/tools/ant/Scalac.scala
+++ b/src/compiler/scala/tools/ant/Scalac.scala
@@ -8,15 +8,18 @@
package scala.tools.ant
-import java.io.{File,PrintWriter,BufferedWriter,FileWriter}
+import java.io.{File, PrintWriter, BufferedWriter, FileWriter}
import org.apache.tools.ant.{ BuildException, Project, AntClassLoader }
import org.apache.tools.ant.taskdefs.Java
import org.apache.tools.ant.types.{Path, Reference}
import org.apache.tools.ant.util.{FileUtils, GlobPatternMapper,
- SourceFileScanner}
+ SourceFileScanner, facade}
+import org.apache.tools.ant.util.facade.{FacadeTaskHelper,
+ ImplementationSpecificArgument}
import scala.tools.nsc.{Global, Settings, CompilerCommand}
+import scala.tools.nsc.io.{Path => SPath}
import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
/** An Ant task to compile with the new Scala compiler (NSC).
@@ -33,6 +36,7 @@ import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
* - `bootclasspathref`,
* - `extdirs`,
* - `extdirsref`,
+ * - `dependencyfile`,
* - `encoding`,
* - `target`,
* - `force`,
@@ -41,9 +45,13 @@ import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
* - `logphase`,
* - `debuginfo`,
* - `addparams`,
+ * - `explaintypes`,
* - `deprecation`,
+ * - `nobootcp`,
+ * - `nowarn`,
* - `optimise`,
* - `unchecked`,
+ * - `usejavacp`,
* - `failonerror`,
* - `scalacdebugging`,
* - `assemname`,
@@ -54,7 +62,8 @@ import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
* - `classpath`,
* - `sourcepath`,
* - `bootclasspath`,
- * - `extdirs`.
+ * - `extdirs`,
+ * - `compilerarg`.
*
* @author Gilles Dubochet, Stephane Micheloud
*/
@@ -80,10 +89,11 @@ class Scalac extends ScalaMatchingTask with ScalacShared {
/** Defines valid values for properties that refer to compiler phases. */
object CompilerPhase extends PermissibleValue {
- val values = List("namer", "typer", "pickler", "uncurry", "tailcalls",
- "explicitouter", "erasure", "lambdalift",
- "flatten", "constructors", "mixin", "icode", "jvm",
- "terminal")
+ val values = List("namer", "typer", "pickler", "refchecks", "liftcode",
+ "uncurry", "tailcalls", "specialize", "explicitouter",
+ "erasure", "lazyvals", "lambdalift", "constructors",
+ "flatten", "mixin", "cleanup", "icode", "inliner",
+ "closelim", "dce", "jvm", "terminal")
}
/** Defines valid values for the `target` property. */
@@ -116,6 +126,8 @@ class Scalac extends ScalaMatchingTask with ScalacShared {
/** The external extensions path to use for this compilation. */
protected var extdirs: Option[Path] = None
+ /** The dependency tracking file. */
+ protected var dependencyfile: Option[String] = None
/** The character encoding of the files to compile. */
protected var encoding: Option[String] = None
@@ -138,12 +150,20 @@ class Scalac extends ScalaMatchingTask with ScalacShared {
protected var debugInfo: Option[String] = None
/** Instruct the compiler to use additional parameters */
protected var addParams: String = ""
+ /** Instruct the compiler to explain type errors in more detail. */
+ protected var explaintypes: Option[Boolean] = None
/** Instruct the compiler to generate deprecation information. */
protected var deprecation: Option[Boolean] = None
+ /** Instruct the compiler to not use the boot classpath for the scala jars. */
+ protected var nobootcp: Option[Boolean] = None
+ /** Instruct the compiler to generate no warnings. */
+ protected var nowarn: Option[Boolean] = None
/** Instruct the compiler to run optimizations. */
protected var optimise: Option[Boolean] = None
/** Instruct the compiler to generate unchecked information. */
protected var unchecked: Option[Boolean] = None
+ /** Instruct the compiler to use `java.class.path` in classpath resolution. */
+ protected var usejavacp: Option[Boolean] = None
/** Indicates whether compilation errors will fail the build; defaults to true. */
protected var failonerror: Boolean = true
@@ -156,6 +176,9 @@ class Scalac extends ScalaMatchingTask with ScalacShared {
* (not only the number of files). */
protected var scalacDebugging: Boolean = false
+ /** Encapsulates implementation of specific command line arguments. */
+ protected var scalacCompilerArgs = new FacadeTaskHelper("compilerarg")
+
/** Helpers */
private def setOrAppend(old: Option[Path], arg: Path): Option[Path] = old match {
case Some(x) => x append arg ; Some(x)
@@ -251,8 +274,7 @@ class Scalac extends ScalaMatchingTask with ScalacShared {
bootclasspath = setOrAppend(bootclasspath, input)
}
- /** Sets the `bootclasspath` as a nested sourcepath Ant
- * parameter.
+ /** Sets the `bootclasspath` as a nested bootclasspath Ant parameter.
* @return A source path to be configured. */
def createBootclasspath(): Path = createNewPath(bootclasspath _, p => bootclasspath = p)
@@ -264,10 +286,11 @@ class Scalac extends ScalaMatchingTask with ScalacShared {
/** Sets the external extensions path attribute. Used by [[http://ant.apache.org Ant]].
* @param input The value of `extdirs`. */
- def setExtdirs(input: Path) =
+ def setExtdirs(input: Path) {
extdirs = setOrAppend(extdirs, input)
+ }
- /** Sets the `extdirs` as a nested sourcepath Ant parameter.
+ /** Sets the `extdirs` as a nested extdirs Ant parameter.
* @return An extensions path to be configured. */
def createExtdirs(): Path = createNewPath(extdirs _, p => extdirs = p)
@@ -276,10 +299,17 @@ class Scalac extends ScalaMatchingTask with ScalacShared {
def setExtdirsref(input: Reference) =
createExtdirs().setRefid(input)
+ /** Sets the `dependencyfile` attribute. Used by [[http://ant.apache.org Ant]].
+ * @param input The value of `dependencyfile`. */
+ def setDependencyfile(input: String) {
+ dependencyfile = Some(input)
+ }
+
/** Sets the `encoding` attribute. Used by [[http://ant.apache.org Ant]].
* @param input The value of `encoding`. */
- def setEncoding(input: String): Unit =
+ def setEncoding(input: String) {
encoding = Some(input)
+ }
/** Sets the `target` attribute. Used by [[http://ant.apache.org Ant]].
* @param input The value for `target`. */
@@ -330,12 +360,30 @@ class Scalac extends ScalaMatchingTask with ScalacShared {
* @param input The value for `addparams`. */
def setAddparams(input: String) { addParams = input }
+ /** Set the `explaintypes` info attribute.
+ * @param input One of the flags `yes/no` or `on/off`. */
+ def setExplaintypes(input: String) {
+ explaintypes = Flag toBoolean input orElse buildError("Unknown explaintypes flag '" + input + "'")
+ }
+
/** Set the `deprecation` info attribute.
* @param input One of the flags `yes/no` or `on/off`. */
def setDeprecation(input: String) {
deprecation = Flag toBoolean input orElse buildError("Unknown deprecation flag '" + input + "'")
}
+ /** Set the `nobootcp` info attribute.
+ * @param input One of the flags `yes/no` or `on/off`. */
+ def setNobootcp(input: String) {
+ nobootcp = Flag toBoolean input orElse buildError("Unknown nobootcp flag '" + input + "'")
+ }
+
+ /** Set the `nowarn` info attribute.
+ * @param input One of the flags `yes/no` or `on/off`. */
+ def setNowarn(input: String) {
+ nowarn = Flag toBoolean input orElse buildError("Unknown nowarn flag '" + input + "'")
+ }
+
/** Set the `optimise` info attribute.
* @param input One of the flags `yes/no` or `on/off`. */
def setOptimise(input: String) {
@@ -348,6 +396,12 @@ class Scalac extends ScalaMatchingTask with ScalacShared {
unchecked = Flag toBoolean input orElse buildError("Unknown unchecked flag '" + input + "'")
}
+ /** Set the `usejavacp` info attribute.
+ * @param input One of the flags `yes/no` or `on/off`. */
+ def setUsejavacp(input: String) {
+ usejavacp = Flag toBoolean input orElse buildError("Unknown usejavacp flag '" + input + "'")
+ }
+
/** Sets the `failonerror` attribute. Used by [[http://ant.apache.org Ant]].
* @param input The value for `failonerror`. */
def setFailonerror(input: Boolean) { failonerror = input }
@@ -361,6 +415,14 @@ class Scalac extends ScalaMatchingTask with ScalacShared {
def setAssemname(input: String) { assemname = Some(input) }
def setAssemrefs(input: String) { assemrefs = Some(input) }
+ /** Sets the `compilerarg` as a nested compilerarg Ant parameter.
+ * @return A compiler argument to be configured. */
+ def createCompilerArg(): ImplementationSpecificArgument = {
+ val arg = new ImplementationSpecificArgument()
+ scalacCompilerArgs addImplementationArgument arg
+ arg
+ }
+
/*============================================================================*\
** Properties getters **
\*============================================================================*/
@@ -457,7 +519,7 @@ class Scalac extends ScalaMatchingTask with ScalacShared {
/** Initializes settings and source files */
protected def initialize: (Settings, List[File], Boolean) = {
if (scalacDebugging)
- log("Base directory is `%s`".format(scala.tools.nsc.io.Path("").normalize))
+ log("Base directory is `%s`".format(SPath("").normalize))
// Tests if all mandatory attributes are set and valid.
if (origin.isEmpty) buildError("Attribute 'srcdir' is not set.")
@@ -522,6 +584,7 @@ class Scalac extends ScalaMatchingTask with ScalacShared {
if (!bootclasspath.isEmpty)
settings.bootclasspath.value = asString(getBootclasspath)
if (!extdirs.isEmpty) settings.extdirs.value = asString(getExtdirs)
+ if (!dependencyfile.isEmpty) settings.dependencyfile.value = dependencyfile.get
if (!encoding.isEmpty) settings.encoding.value = encoding.get
if (!backend.isEmpty) settings.target.value = backend.get
if (!logging.isEmpty && logging.get == "verbose")
@@ -532,13 +595,22 @@ class Scalac extends ScalaMatchingTask with ScalacShared {
}
if (!logPhase.isEmpty) settings.log.value = logPhase
if (!debugInfo.isEmpty) settings.debuginfo.value = debugInfo.get
+ if (!explaintypes.isEmpty) settings.explaintypes.value = explaintypes.get
if (!deprecation.isEmpty) settings.deprecation.value = deprecation.get
+ if (!nobootcp.isEmpty) settings.nobootcp.value = nobootcp.get
+ if (!nowarn.isEmpty) settings.nowarn.value = nowarn.get
if (!optimise.isEmpty) settings.XO.value = optimise.get
if (!unchecked.isEmpty) settings.unchecked.value = unchecked.get
+ if (!usejavacp.isEmpty) settings.usejavacp.value = usejavacp.get
if (!assemname.isEmpty) settings.assemname.value = assemname.get
if (!assemrefs.isEmpty) settings.assemrefs.value = assemrefs.get
+ val jvmargs = scalacCompilerArgs.getArgs filter (_ startsWith "-J")
+ if (!jvmargs.isEmpty) settings.jvmargs.value = jvmargs.toList
+ val defines = scalacCompilerArgs.getArgs filter (_ startsWith "-D")
+ if (!defines.isEmpty) settings.defines.value = defines.toList
+
log("Scalac params = '" + addParams + "'", Project.MSG_DEBUG)
// let CompilerCommand processes all params
@@ -550,8 +622,8 @@ class Scalac extends ScalaMatchingTask with ScalacShared {
command.settings.dependenciesFile.value match {
case "none" =>
case x =>
- val depFilePath = scala.tools.nsc.io.Path(x)
- command.settings.dependenciesFile.value = scala.tools.nsc.io.Path(getProject.getBaseDir).normalize resolve depFilePath path
+ val depFilePath = SPath(x)
+ command.settings.dependenciesFile.value = SPath(getProject.getBaseDir).normalize resolve depFilePath path
}
(command.settings, sourceFiles, javaOnly)
@@ -588,7 +660,7 @@ class Scalac extends ScalaMatchingTask with ScalacShared {
java setClassname MainClass
// Write all settings to a temporary file
- def writeSettings() : File = {
+ def writeSettings(): File = {
def escapeArgument(arg : String) = if (arg matches ".*\\s.*") '"' + arg + '"' else arg
val file = File.createTempFile("scalac-ant-",".args")
file.deleteOnExit()