Permalink
Browse files

reorganize compilation modules

  • Loading branch information...
1 parent b3270ba commit 6bcf71efefe2533a6757df113f0ebcec5bb07b6d @harrah harrah committed Apr 18, 2012
@@ -12,9 +12,9 @@ package compiler
* provided by scalaInstance. This class requires a ComponentManager in order to obtain the interface code to scalac and
* the analysis plugin. Because these call Scala code for a different Scala version than the one used for this class, they must
* be compiled for the version of Scala being used.*/
-class AnalyzingCompiler(val scalaInstance: ScalaInstance, val manager: ComponentManager, val cp: ClasspathOptions, log: Logger)
+class AnalyzingCompiler(val scalaInstance: ScalaInstance, val provider: CompilerInterfaceProvider, val cp: ClasspathOptions, log: Logger)
{
- def this(scalaInstance: ScalaInstance, manager: ComponentManager, log: Logger) = this(scalaInstance, manager, ClasspathOptions.auto, log)
+ def this(scalaInstance: ScalaInstance, provider: CompilerInterfaceProvider, log: Logger) = this(scalaInstance, provider, ClasspathOptions.auto, log)
def apply(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], callback: AnalysisCallback, maximumErrors: Int, log: Logger)
{
val arguments = (new CompilerArguments(scalaInstance, cp))(sources, classpath, outputDirectory, options)
@@ -48,7 +48,7 @@ class AnalyzingCompiler(val scalaInstance: ScalaInstance, val manager: Component
classOf[Array[String]], classOf[String], classOf[String], classOf[String], classOf[String], classOf[ClassLoader], classOf[Array[String]], classOf[Array[Any]], classOf[xLogger])(
options.toArray[String]: Array[String], bootClasspath, classpathString, initialCommands, cleanupCommands, loader.orNull, names.toArray[String], values.toArray[Any], log)
}
- def force(log: Logger): Unit = getInterfaceJar(log)
+ def force(log: Logger): Unit = provider(scalaInstance, log)
private def call(interfaceClassName: String, log: Logger)(argTypes: Class[_]*)(args: AnyRef*)
{
val interfaceClass = getInterfaceClass(interfaceClassName, log)
@@ -59,25 +59,17 @@ class AnalyzingCompiler(val scalaInstance: ScalaInstance, val manager: Component
}
private[this] def loader =
{
- val interfaceJar = getInterfaceJar(log)
+ val interfaceJar = provider(scalaInstance, log)
// this goes to scalaInstance.loader for scala classes and the loader of this class for xsbti classes
val dual = createDualLoader(scalaInstance.loader, getClass.getClassLoader)
new URLClassLoader(Array(interfaceJar.toURI.toURL), dual)
}
private def getInterfaceClass(name: String, log: Logger) = Class.forName(name, true, loader)
- private def getInterfaceJar(log: Logger) =
- {
- // this is the instance used to compile the interface component
- val componentCompiler = newComponentCompiler(log)
- log.debug("Getting " + ComponentCompiler.compilerInterfaceID + " from component compiler for Scala " + scalaInstance.version)
- componentCompiler(ComponentCompiler.compilerInterfaceID)
- }
- def newComponentCompiler(log: Logger) = new ComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptions.auto, log), manager)
protected def createDualLoader(scalaLoader: ClassLoader, sbtLoader: ClassLoader): ClassLoader =
{
val xsbtiFilter = (name: String) => name.startsWith("xsbti.")
val notXsbtiFilter = (name: String) => !xsbtiFilter(name)
new classpath.DualLoader(scalaLoader, notXsbtiFilter, x => true, sbtLoader, xsbtiFilter, x => false)
}
override def toString = "Analyzing compiler (Scala " + scalaInstance.actualVersion + ")"
-}
+}
@@ -4,6 +4,7 @@
package sbt
package compiler
+ import xsbti.ArtifactInfo
import scala.util
import java.io.File
import CompilerArguments.{abs, absString, BootClasspathOption}
@@ -48,7 +49,7 @@ final class CompilerArguments(scalaInstance: ScalaInstance, cp: ClasspathOptions
originalBoot
}
def filterLibrary(classpath: Seq[File]) =
- if(cp.filterLibrary) classpath.filterNot(_.getName contains ScalaArtifacts.LibraryID) else classpath
+ if(cp.filterLibrary) classpath.filterNot(_.getName contains ArtifactInfo.ScalaLibraryID) else classpath
def bootClasspathOption = if(cp.autoBoot) Seq(BootClasspathOption, createBootClasspath) else Nil
def bootClasspath = if(cp.autoBoot) IO.parseClasspath(createBootClasspath) else Nil
}
@@ -0,0 +1,15 @@
+package sbt
+package compiler
+
+ import java.io.File
+
+trait CompilerInterfaceProvider
+{
+ def apply(scalaInstance: ScalaInstance, log: Logger): File
+}
+object CompilerInterfaceProvider
+{
+ def constant(file: File): CompilerInterfaceProvider = new CompilerInterfaceProvider {
+ def apply(scalaInstance: ScalaInstance, log: Logger): File = file
+ }
+}
@@ -2,11 +2,11 @@
* Copyright 2010 Mark Harrah
*/
package sbt
+package compiler
import inc._
import java.io.File
- import compiler.{AnalyzingCompiler, CompilerArguments, JavaCompiler}
import classpath.ClasspathUtilities
import classfile.Analyze
import xsbti.api.Source
@@ -108,7 +108,7 @@ class AggressiveCompile(cacheFile: File)
import AnalysisFormats._
val store = AggressiveCompile.staticCache(cacheFile, AnalysisStore.sync(AnalysisStore.cached(FileBasedStore(cacheFile))))
}
-private object AggressiveCompile
+object AggressiveCompile
{
import collection.mutable
import java.lang.ref.{Reference,SoftReference}
@@ -121,4 +121,53 @@ private object AggressiveCompile
b
}
}
-}
+
+ def directOrFork(instance: ScalaInstance, cpOptions: ClasspathOptions, javaHome: Option[File]): JavaCompiler =
+ if(javaHome.isDefined)
+ JavaCompiler.fork(cpOptions, instance)(forkJavac(javaHome))
+ else
+ JavaCompiler.directOrFork(cpOptions, instance)(forkJavac(None))
+
+ def forkJavac(javaHome: Option[File]): JavaCompiler.Fork =
+ {
+ import Path._
+ def exec(jc: JavacContract) = javaHome match { case None => jc.name; case Some(jh) => (jh / "bin" / jc.name).absolutePath }
+ (contract: JavacContract, args: Seq[String], log: Logger) => {
+ log.debug("Forking " + contract.name + ": " + exec(contract) + " " + args.mkString(" "))
+ val javacLogger = new JavacLogger(log)
+ var exitCode = -1
+ try {
+ exitCode = Process(exec(contract), args) ! javacLogger
+ } finally {
+ javacLogger.flush(exitCode)
+ }
+ exitCode
+ }
+ }
+}
+
+private[sbt] class JavacLogger(log: Logger) extends ProcessLogger {
+ import scala.collection.mutable.ListBuffer
+ import Level.{Info, Warn, Error, Value => LogLevel}
+
+ private val msgs: ListBuffer[(LogLevel, String)] = new ListBuffer()
+
+ def info(s: => String): Unit =
+ synchronized { msgs += ((Info, s)) }
+
+ def error(s: => String): Unit =
+ synchronized { msgs += ((Error, s)) }
+
+ def buffer[T](f: => T): T = f
+
+ private def print(desiredLevel: LogLevel)(t: (LogLevel, String)) = t match {
+ case (Info, msg) => log.info(msg)
+ case (Error, msg) => log.log(desiredLevel, msg)
+ }
+
+ def flush(exitCode: Int): Unit = {
+ val level = if (exitCode == 0) Warn else Error
+ msgs foreach print(level)
+ msgs.clear()
+ }
+}
@@ -14,6 +14,17 @@ object ComponentCompiler
val compilerInterfaceID = "compiler-interface"
val compilerInterfaceSrcID = compilerInterfaceID + srcExtension
val javaVersion = System.getProperty("java.class.version")
+
+ def interfaceProvider(manager: ComponentManager): CompilerInterfaceProvider = new CompilerInterfaceProvider
+ {
+ def apply(scalaInstance: ScalaInstance, log: Logger): File =
+ {
+ // this is the instance used to compile the interface component
+ val componentCompiler = new ComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptions.auto, log), manager)
+ log.debug("Getting " + compilerInterfaceID + " from component compiler for Scala " + scalaInstance.version)
+ componentCompiler(compilerInterfaceID)
+ }
+ }
}
/** This class provides source components compiled with the provided RawCompiler.
* The compiled classes are cached using the provided component manager according
@@ -0,0 +1,9 @@
+package xsbti;
+
+public final class ArtifactInfo
+{
+ public static final String ScalaOrganization = "org.scala-lang";
+ public static final String ScalaLibraryID = "scala-library";
+ public static final String ScalaCompilerID = "scala-compiler";
+ public static final String SbtOrganization = "org.scala-sbt";
+}
View
@@ -14,14 +14,16 @@ import plugins.matcher.ExactPatternMatcher
object ScalaArtifacts
{
- val Organization = "org.scala-lang"
- val LibraryID = "scala-library"
- val CompilerID = "scala-compiler"
+ import xsbti.ArtifactInfo._
+ val Organization = ScalaOrganization
+ val LibraryID = ScalaLibraryID
+ val CompilerID = ScalaCompilerID
def libraryDependency(version: String): ModuleID = ModuleID(Organization, LibraryID, version)
}
object SbtArtifacts
{
- val Organization = "org.scala-sbt"
+ import xsbti.ArtifactInfo._
+ val Organization = SbtOrganization
}
import ScalaArtifacts._
@@ -46,7 +46,7 @@ object Compiler
def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions, javaHome: Option[File])(implicit app: AppConfiguration, log: Logger): Compilers =
{
- val javac = directOrFork(instance, cpOptions, javaHome)
+ val javac = AggressiveCompile.directOrFork(instance, cpOptions, javaHome)
compilers(instance, cpOptions, javac)
}
def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions, javac: JavaCompiler.Fork)(implicit app: AppConfiguration, log: Logger): Compilers =
@@ -63,29 +63,8 @@ object Compiler
{
val launcher = app.provider.scalaProvider.launcher
val componentManager = new ComponentManager(launcher.globalLock, app.provider.components, Option(launcher.ivyHome), log)
- new AnalyzingCompiler(instance, componentManager, cpOptions, log)
- }
- def directOrFork(instance: ScalaInstance, cpOptions: ClasspathOptions, javaHome: Option[File]): JavaCompiler =
- if(javaHome.isDefined)
- JavaCompiler.fork(cpOptions, instance)(forkJavac(javaHome))
- else
- JavaCompiler.directOrFork(cpOptions, instance)(forkJavac(None))
-
- def forkJavac(javaHome: Option[File]): JavaCompiler.Fork =
- {
- import Path._
- def exec(jc: JavacContract) = javaHome match { case None => jc.name; case Some(jh) => (jh / "bin" / jc.name).absolutePath }
- (contract: JavacContract, args: Seq[String], log: Logger) => {
- log.debug("Forking " + contract.name + ": " + exec(contract) + " " + args.mkString(" "))
- val javacLogger = new JavacLogger(log)
- var exitCode = -1
- try {
- exitCode = Process(exec(contract), args) ! javacLogger
- } finally {
- javacLogger.flush(exitCode)
- }
- exitCode
- }
+ val provider = ComponentCompiler.interfaceProvider(componentManager)
+ new AnalyzingCompiler(instance, provider, cpOptions, log)
}
def apply(in: Inputs, log: Logger): Analysis =
@@ -98,29 +77,3 @@ object Compiler
agg(scalac, javac, sources, classpath, classesDirectory, options, javacOptions, analysisMap, definesClass, maxErrors, order, skip)(log)
}
}
-
-private[sbt] class JavacLogger(log: Logger) extends ProcessLogger {
- import scala.collection.mutable.ListBuffer
- import Level.{Info, Warn, Error, Value => LogLevel}
-
- private val msgs: ListBuffer[(LogLevel, String)] = new ListBuffer()
-
- def info(s: => String): Unit =
- synchronized { msgs += ((Info, s)) }
-
- def error(s: => String): Unit =
- synchronized { msgs += ((Error, s)) }
-
- def buffer[T](f: => T): T = f
-
- private def print(desiredLevel: LogLevel)(t: (LogLevel, String)) = t match {
- case (Info, msg) => log.info(msg)
- case (Error, msg) => log.log(desiredLevel, msg)
- }
-
- def flush(exitCode: Int): Unit = {
- val level = if (exitCode == 0) Warn else Error
- msgs foreach print(level)
- msgs.clear()
- }
-}
View
@@ -102,10 +102,11 @@ object Sbt extends Build
// Persists the incremental data structures using SBinary
lazy val compilePersistSub = baseProject(compilePath / "persist", "Persist") dependsOn(compileIncrementalSub, apiSub) settings(sbinary)
// sbt-side interface to compiler. Calls compiler-side interface reflectively
- lazy val compilerSub = testedBaseProject(compilePath, "Compile") dependsOn(launchInterfaceSub, interfaceSub % "compile;test->test", ivySub, ioSub, classpathSub,
+ lazy val compilerSub = testedBaseProject(compilePath, "Compile") dependsOn(launchInterfaceSub, interfaceSub % "compile;test->test", logSub, ioSub, classpathSub,
logSub % "test->test", launchSub % "test->test", apiSub % "test") settings( compilerSettings : _*)
lazy val compilerIntegrationSub = baseProject(compilePath / "integration", "Compiler Integration") dependsOn(
compileIncrementalSub, compilerSub, compilePersistSub, apiSub, classfileSub)
+ lazy val compilerIvySub = baseProject(compilePath / "ivy", "Compiler Ivy Integration") dependsOn(ivySub, compilerSub )
lazy val scriptedBaseSub = baseProject(scriptedPath / "base", "Scripted Framework") dependsOn(ioSub, processSub)
lazy val scriptedSbtSub = baseProject(scriptedPath / "sbt", "Scripted sbt") dependsOn(ioSub, logSub, processSub, scriptedBaseSub, launchInterfaceSub % "provided")
@@ -114,7 +115,7 @@ object Sbt extends Build
// Implementation and support code for defining actions.
lazy val actionsSub = baseProject(mainPath / "actions", "Actions") dependsOn(
- classpathSub, completeSub, apiSub, compilerIntegrationSub,
+ classpathSub, completeSub, apiSub, compilerIntegrationSub, compilerIvySub,
interfaceSub, ioSub, ivySub, logSub, processSub, runSub, stdTaskSub, taskSub, trackingSub, testingSub)
lazy val commandSub = testedBaseProject(commandPath, "Command") dependsOn(interfaceSub, ioSub, launchInterfaceSub, logSub, completeSub, classpathSub)

0 comments on commit 6bcf71e

Please sign in to comment.