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
|
* 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
|
* 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.*/
|
* 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)
|
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)
|
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])(
|
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)
|
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*)
|
private def call(interfaceClassName: String, log: Logger)(argTypes: Class[_]*)(args: AnyRef*)
|
||||||
{
|
{
|
||||||
val interfaceClass = getInterfaceClass(interfaceClassName, log)
|
val interfaceClass = getInterfaceClass(interfaceClassName, log)
|
||||||
|
|
@ -59,20 +59,12 @@ class AnalyzingCompiler(val scalaInstance: ScalaInstance, val manager: Component
|
||||||
}
|
}
|
||||||
private[this] def loader =
|
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
|
// this goes to scalaInstance.loader for scala classes and the loader of this class for xsbti classes
|
||||||
val dual = createDualLoader(scalaInstance.loader, getClass.getClassLoader)
|
val dual = createDualLoader(scalaInstance.loader, getClass.getClassLoader)
|
||||||
new URLClassLoader(Array(interfaceJar.toURI.toURL), dual)
|
new URLClassLoader(Array(interfaceJar.toURI.toURL), dual)
|
||||||
}
|
}
|
||||||
private def getInterfaceClass(name: String, log: Logger) = Class.forName(name, true, loader)
|
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 =
|
protected def createDualLoader(scalaLoader: ClassLoader, sbtLoader: ClassLoader): ClassLoader =
|
||||||
{
|
{
|
||||||
val xsbtiFilter = (name: String) => name.startsWith("xsbti.")
|
val xsbtiFilter = (name: String) => name.startsWith("xsbti.")
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
package sbt
|
package sbt
|
||||||
package compiler
|
package compiler
|
||||||
|
|
||||||
|
import xsbti.ArtifactInfo
|
||||||
import scala.util
|
import scala.util
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import CompilerArguments.{abs, absString, BootClasspathOption}
|
import CompilerArguments.{abs, absString, BootClasspathOption}
|
||||||
|
|
@ -48,7 +49,7 @@ final class CompilerArguments(scalaInstance: ScalaInstance, cp: ClasspathOptions
|
||||||
originalBoot
|
originalBoot
|
||||||
}
|
}
|
||||||
def filterLibrary(classpath: Seq[File]) =
|
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 bootClasspathOption = if(cp.autoBoot) Seq(BootClasspathOption, createBootClasspath) else Nil
|
||||||
def bootClasspath = if(cp.autoBoot) IO.parseClasspath(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
|
* Copyright 2010 Mark Harrah
|
||||||
*/
|
*/
|
||||||
package sbt
|
package sbt
|
||||||
|
package compiler
|
||||||
|
|
||||||
import inc._
|
import inc._
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import compiler.{AnalyzingCompiler, CompilerArguments, JavaCompiler}
|
|
||||||
import classpath.ClasspathUtilities
|
import classpath.ClasspathUtilities
|
||||||
import classfile.Analyze
|
import classfile.Analyze
|
||||||
import xsbti.api.Source
|
import xsbti.api.Source
|
||||||
|
|
@ -108,7 +108,7 @@ class AggressiveCompile(cacheFile: File)
|
||||||
import AnalysisFormats._
|
import AnalysisFormats._
|
||||||
val store = AggressiveCompile.staticCache(cacheFile, AnalysisStore.sync(AnalysisStore.cached(FileBasedStore(cacheFile))))
|
val store = AggressiveCompile.staticCache(cacheFile, AnalysisStore.sync(AnalysisStore.cached(FileBasedStore(cacheFile))))
|
||||||
}
|
}
|
||||||
private object AggressiveCompile
|
object AggressiveCompile
|
||||||
{
|
{
|
||||||
import collection.mutable
|
import collection.mutable
|
||||||
import java.lang.ref.{Reference,SoftReference}
|
import java.lang.ref.{Reference,SoftReference}
|
||||||
|
|
@ -121,4 +121,53 @@ private object AggressiveCompile
|
||||||
b
|
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 compilerInterfaceID = "compiler-interface"
|
||||||
val compilerInterfaceSrcID = compilerInterfaceID + srcExtension
|
val compilerInterfaceSrcID = compilerInterfaceID + srcExtension
|
||||||
val javaVersion = System.getProperty("java.class.version")
|
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.
|
/** This class provides source components compiled with the provided RawCompiler.
|
||||||
* The compiled classes are cached using the provided component manager according
|
* 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
|
object ScalaArtifacts
|
||||||
{
|
{
|
||||||
val Organization = "org.scala-lang"
|
import xsbti.ArtifactInfo._
|
||||||
val LibraryID = "scala-library"
|
val Organization = ScalaOrganization
|
||||||
val CompilerID = "scala-compiler"
|
val LibraryID = ScalaLibraryID
|
||||||
|
val CompilerID = ScalaCompilerID
|
||||||
def libraryDependency(version: String): ModuleID = ModuleID(Organization, LibraryID, version)
|
def libraryDependency(version: String): ModuleID = ModuleID(Organization, LibraryID, version)
|
||||||
}
|
}
|
||||||
object SbtArtifacts
|
object SbtArtifacts
|
||||||
{
|
{
|
||||||
val Organization = "org.scala-sbt"
|
import xsbti.ArtifactInfo._
|
||||||
|
val Organization = SbtOrganization
|
||||||
}
|
}
|
||||||
|
|
||||||
import ScalaArtifacts._
|
import ScalaArtifacts._
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ object Compiler
|
||||||
|
|
||||||
def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions, javaHome: Option[File])(implicit app: AppConfiguration, log: Logger): Compilers =
|
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)
|
compilers(instance, cpOptions, javac)
|
||||||
}
|
}
|
||||||
def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions, javac: JavaCompiler.Fork)(implicit app: AppConfiguration, log: Logger): Compilers =
|
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 launcher = app.provider.scalaProvider.launcher
|
||||||
val componentManager = new ComponentManager(launcher.globalLock, app.provider.components, Option(launcher.ivyHome), log)
|
val componentManager = new ComponentManager(launcher.globalLock, app.provider.components, Option(launcher.ivyHome), log)
|
||||||
new AnalyzingCompiler(instance, componentManager, cpOptions, log)
|
val provider = ComponentCompiler.interfaceProvider(componentManager)
|
||||||
}
|
new AnalyzingCompiler(instance, provider, 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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def apply(in: Inputs, log: Logger): Analysis =
|
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)
|
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
|
// Persists the incremental data structures using SBinary
|
||||||
lazy val compilePersistSub = baseProject(compilePath / "persist", "Persist") dependsOn(compileIncrementalSub, apiSub) settings(sbinary)
|
lazy val compilePersistSub = baseProject(compilePath / "persist", "Persist") dependsOn(compileIncrementalSub, apiSub) settings(sbinary)
|
||||||
// sbt-side interface to compiler. Calls compiler-side interface reflectively
|
// 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 : _*)
|
logSub % "test->test", launchSub % "test->test", apiSub % "test") settings( compilerSettings : _*)
|
||||||
lazy val compilerIntegrationSub = baseProject(compilePath / "integration", "Compiler Integration") dependsOn(
|
lazy val compilerIntegrationSub = baseProject(compilePath / "integration", "Compiler Integration") dependsOn(
|
||||||
compileIncrementalSub, compilerSub, compilePersistSub, apiSub, classfileSub)
|
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 scriptedBaseSub = baseProject(scriptedPath / "base", "Scripted Framework") dependsOn(ioSub, processSub)
|
||||||
lazy val scriptedSbtSub = baseProject(scriptedPath / "sbt", "Scripted sbt") dependsOn(ioSub, logSub, processSub, scriptedBaseSub, launchInterfaceSub % "provided")
|
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.
|
// Implementation and support code for defining actions.
|
||||||
lazy val actionsSub = baseProject(mainPath / "actions", "Actions") dependsOn(
|
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)
|
interfaceSub, ioSub, ivySub, logSub, processSub, runSub, stdTaskSub, taskSub, trackingSub, testingSub)
|
||||||
|
|
||||||
lazy val commandSub = testedBaseProject(commandPath, "Command") dependsOn(interfaceSub, ioSub, launchInterfaceSub, logSub, completeSub, classpathSub)
|
lazy val commandSub = testedBaseProject(commandPath, "Command") dependsOn(interfaceSub, ioSub, launchInterfaceSub, logSub, completeSub, classpathSub)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue