mirror of https://github.com/sbt/sbt.git
reorganize compilation modules
This commit is contained in:
parent
db7ec09591
commit
8594e4443d
|
|
@ -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,20 +59,12 @@ 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.")
|
||||
|
|
@ -80,4 +72,4 @@ class AnalyzingCompiler(val scalaInstance: ScalaInstance, val manager: Component
|
|||
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";
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue