diff options
author | michelou <michelou@epfl.ch> | 2011-11-16 20:35:21 +0000 |
---|---|---|
committer | michelou <michelou@epfl.ch> | 2011-11-16 20:35:21 +0000 |
commit | 44741eee5336b6d8f195d01cf993debf537124c7 (patch) | |
tree | 3044bf16965cbb16837c69a025758cfa93ed2be6 /src | |
parent | 3b0fd925a85f2d5cdab7c1467fb60fce287114f3 (diff) | |
download | scala-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')
-rw-r--r-- | src/compiler/scala/tools/ant/FastScalac.scala | 146 | ||||
-rw-r--r-- | src/compiler/scala/tools/ant/Scalac.scala | 104 |
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() |