diff options
author | Iulian Dragos <jaguarul@gmail.com> | 2009-05-18 17:36:50 +0000 |
---|---|---|
committer | Iulian Dragos <jaguarul@gmail.com> | 2009-05-18 17:36:50 +0000 |
commit | 3de51d6b76e87aad67a5f0b5177650cb78178b08 (patch) | |
tree | 205e8aa24c1b192c70cb56267317fd03e723ae2b | |
parent | e789f9ac8f55e9ac97834b7261d281388562c53d (diff) | |
download | scala-3de51d6b76e87aad67a5f0b5177650cb78178b08.tar.gz scala-3de51d6b76e87aad67a5f0b5177650cb78178b08.tar.bz2 scala-3de51d6b76e87aad67a5f0b5177650cb78178b08.zip |
Added support for multiple output directories (...
Added support for multiple output directories (no support for command line, only progammatically -- i.e. IDE).
-rw-r--r-- | src/compiler/scala/tools/nsc/Global.scala | 4 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/Settings.scala | 95 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala | 8 |
3 files changed, 100 insertions, 7 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 73b2f6aff7..3771ede167 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -828,8 +828,8 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable /** Returns the file with the given suffix for the given class. */ def getFile(clazz: Symbol, suffix: String): File = { - val outdirname = settings.outdir.value - var outdir = new File(if (outdirname == "") "." else outdirname) + val outdirname = settings.outputDirs.outputDirFor(clazz.sourceFile) + var outdir = new File(if (outdirname == "") "." else outdirname.path) val filename = clazz.fullNameString('.') var start = 0 var end = filename.indexOf('.', start) diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala index 31261b87e6..5f15cd804e 100644 --- a/src/compiler/scala/tools/nsc/Settings.scala +++ b/src/compiler/scala/tools/nsc/Settings.scala @@ -7,6 +7,8 @@ package scala.tools.nsc import java.io.File +import io.AbstractFile +import util.SourceFile import Settings._ class Settings(errorFn: String => Unit) extends ScalacSettings { @@ -73,6 +75,16 @@ class Settings(errorFn: String => Unit) extends ScalacSettings { true } + + /** A list pairing source directories with their output directory. + * This option is not available on the command line, but can be set by + * other tools (IDEs especially). The command line specifies a single + * output directory that is used for all source files, denoted by a + * '*' in this list. + */ + lazy val outputDirs = new OutputDirs + + /** Try to add additional command line parameters. * Returns unconsumed arguments. */ @@ -203,6 +215,7 @@ class Settings(errorFn: String => Unit) extends ScalacSettings { lazy val DebugSetting = untupled(tupled(sdebug _) andThen add[DebugSetting]) lazy val PhasesSetting = untupled(tupled(phase _) andThen add[PhasesSetting]) lazy val DefinesSetting = add(defines()) + lazy val OutputSetting = untupled(tupled(output _) andThen add[OutputSetting]) } object Settings @@ -218,6 +231,72 @@ object Settings val choices : List[T] = Nil } + /** A class for holding mappings from source directories to + * their output location. This functionality can be accessed + * only programmatically. The command line compiler uses a + * single output location, but tools may use this functionality + * to set output location per source directory. + */ + class OutputDirs { + /** Pairs of source directory - destination directory. */ + private var outputDirs: List[(AbstractFile, AbstractFile)] = Nil + + /** If this is not None, the output location where all + * classes should go. + */ + private var singleOutDir: Option[AbstractFile] = None + + /** Add a destination directory for sources found under srcdir. + * Both directories should exits. + */ + def add(srcDir: String, outDir: String): Unit = + add(checkDir(AbstractFile.getDirectory(srcDir), srcDir), + checkDir(AbstractFile.getDirectory(outDir), outDir)) + + /** Check that dir is exists and is a directory. */ + private def checkDir(dir: AbstractFile, name: String): AbstractFile = { + if ((dir eq null) || !dir.isDirectory) + throw new FatalError(name + " does not exist or is not a directory") + dir + } + + /** Set the single output directory. From now on, all files will + * be dumped in there, regardless of previous calls to 'add'. + */ + def setSingleOutput(outDir: String) { + val dst = AbstractFile.getDirectory(outDir) + checkDir(dst, outDir) + + singleOutDir = Some(dst) + } + + def add(src: AbstractFile, dst: AbstractFile) { +// singleOutDir = None + outputDirs ::= (src, dst) + } + + /** Return the list of source-destination directory pairs. */ + def outputs: List[(AbstractFile, AbstractFile)] = outputDirs + + /** Return the output directory for the given file. + */ + def outputDirFor(src: AbstractFile): AbstractFile = { + def isBelow(dir: AbstractFile, f: AbstractFile) = + f.path.startsWith(dir.path) + + singleOutDir match { + case Some(d) => d + case None => + (outputs find Function.tupled(isBelow)) match { + case Some((_, d)) => d + case _ => + throw new FatalError("Could not find an output directory for " + + src.path + " in " + outputs) + } + } + } + } + // The Setting companion object holds all the factory methods object Setting { def bool(name: String, descr: String) = @@ -242,6 +321,9 @@ object Settings new PhasesSetting(name, descr) def defines() = new DefinesSetting() + + def output(outputDirs: OutputDirs, default: String) = + new OutputSetting(outputDirs, default) } /** A base class for settings of all types. @@ -415,6 +497,17 @@ object Settings withHelpSyntax(name + " <" + arg + ">") } + /** Set the output directory. */ + class OutputSetting private[Settings]( + outputDirs: OutputDirs, + default: String) + extends StringSetting("-d", "directory", "Specify where to place generated class files", default) { + override def value_=(str: String) { + super.value_=(str) + outputDirs.setSingleOutput(str) + } + } + /** A setting that accumulates all strings supplied to it */ class MultiStringSetting private[Settings]( val name: String, @@ -588,7 +681,7 @@ trait ScalacSettings 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).withAbbreviation("-cp") - val outdir = StringSetting ("-d", "directory", "Specify where to place generated class files", ".") + val outdir = OutputSetting (outputDirs, ".") val dependenciesFile = StringSetting ("-dependencyfile", "file", "Specify the file in which dependencies are tracked", ".scala_dependencies") 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.encodingString) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 1c0dae7ab8..f12e5abe45 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -137,7 +137,7 @@ abstract class GenJVM extends SubComponent { addScalaAttr(if (isTopLevelModule(sym)) sym.sourceModule else sym); addInnerClasses(jclass) - val outfile = getFile(jclass, ".class") + val outfile = getFile(sym.sourceFile, jclass, ".class") val outstream = new DataOutputStream(outfile.output) jclass.writeTo(outstream) outstream.close() @@ -304,7 +304,7 @@ abstract class GenJVM extends SubComponent { jcode.emitRETURN() // write the bean information class file. - val outfile = getFile(beanInfoClass, ".class") + val outfile = getFile(c.symbol.sourceFile, beanInfoClass, ".class") val outstream = new DataOutputStream(outfile.output) beanInfoClass.writeTo(outstream) outstream.close() @@ -1742,8 +1742,8 @@ abstract class GenJVM extends SubComponent { res } - def getFile(cls: JClass, suffix: String): AbstractFile = { - var dir: AbstractFile = outputDir + def getFile(sourceFile: AbstractFile, cls: JClass, suffix: String): AbstractFile = { + var dir: AbstractFile = settings.outputDirs.outputDirFor(sourceFile) val pathParts = cls.getName().split("[./]").toList for (part <- pathParts.init) { dir = dir.subdirectoryNamed(part) |