summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorIulian Dragos <jaguarul@gmail.com>2009-05-18 17:36:50 +0000
committerIulian Dragos <jaguarul@gmail.com>2009-05-18 17:36:50 +0000
commit3de51d6b76e87aad67a5f0b5177650cb78178b08 (patch)
tree205e8aa24c1b192c70cb56267317fd03e723ae2b /src/compiler
parente789f9ac8f55e9ac97834b7261d281388562c53d (diff)
downloadscala-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).
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala4
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala95
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala8
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)