mirror of https://github.com/sbt/sbt.git
support cross-compiling/bootstrapping
This commit is contained in:
parent
54bc694081
commit
7edcc68a92
|
|
@ -9,38 +9,26 @@ package xsbt
|
|||
* 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, log: CompileLogger) extends NotNull
|
||||
class AnalyzingCompiler(val scalaInstance: ScalaInstance, val manager: ComponentManager, val autoBootClasspath: Boolean, val compilerOnClasspath: Boolean, log: CompileLogger) extends NotNull
|
||||
{
|
||||
def apply(sources: Set[File], classpath: Set[File], outputDirectory: File, options: Seq[String], callback: AnalysisCallback, maximumErrors: Int, log: CompileLogger): Unit =
|
||||
apply(sources, classpath, outputDirectory, options, false, callback, maximumErrors, log)
|
||||
def apply(sources: Set[File], classpath: Set[File], outputDirectory: File, options: Seq[String], compilerOnClasspath: Boolean,
|
||||
callback: AnalysisCallback, maximumErrors: Int, log: CompileLogger)
|
||||
def this(scalaInstance: ScalaInstance, manager: ComponentManager, log: CompileLogger) = this(scalaInstance, manager, true, true, log)
|
||||
def apply(sources: Set[File], classpath: Set[File], outputDirectory: File, options: Seq[String], callback: AnalysisCallback, maximumErrors: Int, log: CompileLogger)
|
||||
{
|
||||
val arguments = (new CompilerArguments(scalaInstance))(sources, classpath, outputDirectory, options, compilerOnClasspath)
|
||||
val arguments = (new CompilerArguments(scalaInstance, autoBootClasspath, compilerOnClasspath))(sources, classpath, outputDirectory, options)
|
||||
call("xsbt.CompilerInterface", log)(
|
||||
classOf[Array[String]], classOf[AnalysisCallback], classOf[Int], classOf[xLogger] ) (
|
||||
arguments.toArray[String] : Array[String], callback, maximumErrors: java.lang.Integer, log )
|
||||
// this is commented out because of Scala ticket #2365
|
||||
/*
|
||||
val interface = getInterfaceClass(interface, log).newInstance.asInstanceOf[AnyRef]
|
||||
val runnable = interface.asInstanceOf[{ def run(args: Array[String], callback: AnalysisCallback, maximumErrors: Int, log: xLogger): Unit }]
|
||||
// these arguments are safe to pass across the ClassLoader boundary because the types are defined in Java
|
||||
// so they will be binary compatible across all versions of Scala
|
||||
runnable.run(arguments.toArray, callback, maximumErrors, log)*/
|
||||
}
|
||||
def doc(sources: Set[File], classpath: Set[File], outputDirectory: File, options: Seq[String], maximumErrors: Int, log: CompileLogger): Unit =
|
||||
doc(sources, classpath, outputDirectory, options, false, maximumErrors, log)
|
||||
def doc(sources: Set[File], classpath: Set[File], outputDirectory: File, options: Seq[String], compilerOnClasspath: Boolean,
|
||||
maximumErrors: Int, log: CompileLogger): Unit =
|
||||
{
|
||||
val arguments = (new CompilerArguments(scalaInstance))(sources, classpath, outputDirectory, options, compilerOnClasspath)
|
||||
val arguments = (new CompilerArguments(scalaInstance, autoBootClasspath, compilerOnClasspath))(sources, classpath, outputDirectory, options)
|
||||
call("xsbt.ScaladocInterface", log) (classOf[Array[String]], classOf[Int], classOf[xLogger]) (arguments.toArray[String] : Array[String], maximumErrors: java.lang.Integer, log)
|
||||
}
|
||||
def console(classpath: Set[File], initialCommands: String, log: CompileLogger): Unit =
|
||||
{
|
||||
val arguments = new CompilerArguments(scalaInstance)
|
||||
val classpathString = CompilerArguments.absString(arguments.finishClasspath(classpath, true))
|
||||
val bootClasspath = arguments.createBootClasspath
|
||||
val arguments = new CompilerArguments(scalaInstance, autoBootClasspath, compilerOnClasspath)
|
||||
val classpathString = CompilerArguments.absString(arguments.finishClasspath(classpath))
|
||||
val bootClasspath = if(autoBootClasspath) arguments.createBootClasspath else ""
|
||||
call("xsbt.ConsoleInterface", log) (classOf[String], classOf[String], classOf[String], classOf[xLogger]) (bootClasspath, classpathString, initialCommands, log)
|
||||
}
|
||||
def force(log: CompileLogger): Unit = getInterfaceJar(log)
|
||||
|
|
@ -66,7 +54,7 @@ class AnalyzingCompiler(val scalaInstance: ScalaInstance, val manager: Component
|
|||
log.debug("Getting " + ComponentCompiler.compilerInterfaceID + " from component compiler for Scala " + scalaInstance.version)
|
||||
componentCompiler(ComponentCompiler.compilerInterfaceID)
|
||||
}
|
||||
def newComponentCompiler(log: CompileLogger) = new ComponentCompiler(new RawCompiler(scalaInstance, log), manager)
|
||||
def newComponentCompiler(log: CompileLogger) = new ComponentCompiler(new RawCompiler(scalaInstance, true, true, log), manager)
|
||||
protected def createDualLoader(scalaLoader: ClassLoader, sbtLoader: ClassLoader): ClassLoader =
|
||||
{
|
||||
val xsbtiFilter = (name: String) => name.startsWith("xsbti.")
|
||||
|
|
|
|||
|
|
@ -8,18 +8,18 @@ package xsbt
|
|||
* order to add these jars to the boot classpath. The 'scala.home' property must be unset because Scala
|
||||
* puts jars in that directory on the bootclasspath. Because we use multiple Scala versions,
|
||||
* this would lead to compiling against the wrong library jar.*/
|
||||
class CompilerArguments(scalaInstance: ScalaInstance)
|
||||
class CompilerArguments(scalaInstance: ScalaInstance, autoBootClasspath: Boolean, compilerOnClasspath: Boolean)
|
||||
{
|
||||
def apply(sources: Set[File], classpath: Set[File], outputDirectory: File, options: Seq[String], compilerOnClasspath: Boolean): Seq[String] =
|
||||
def apply(sources: Set[File], classpath: Set[File], outputDirectory: File, options: Seq[String]): Seq[String] =
|
||||
{
|
||||
checkScalaHomeUnset()
|
||||
val bootClasspathOption = Seq("-bootclasspath", createBootClasspath)
|
||||
val cpWithCompiler = finishClasspath(classpath, compilerOnClasspath)
|
||||
val bootClasspathOption = if(autoBootClasspath) Seq("-bootclasspath", createBootClasspath) else Nil
|
||||
val cpWithCompiler = finishClasspath(classpath)
|
||||
val classpathOption = Seq("-cp", absString(cpWithCompiler) )
|
||||
val outputOption = Seq("-d", outputDirectory.getAbsolutePath)
|
||||
options ++ outputOption ++ bootClasspathOption ++ classpathOption ++ abs(sources)
|
||||
}
|
||||
def finishClasspath(classpath: Set[File], compilerOnClasspath: Boolean): Set[File] =
|
||||
def finishClasspath(classpath: Set[File]): Set[File] =
|
||||
classpath ++ (if(compilerOnClasspath) scalaInstance.compilerJar :: Nil else Nil)
|
||||
protected def abs(files: Set[File]) = files.map(_.getAbsolutePath)
|
||||
protected def checkScalaHomeUnset()
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ class ComponentCompiler(compiler: RawCompiler, manager: ComponentManager)
|
|||
val start = System.currentTimeMillis
|
||||
try
|
||||
{
|
||||
compiler(Set() ++ sourceFiles, Set() ++ xsbtiJars ++ sourceJars, outputDirectory, "-nowarn" :: Nil, true)
|
||||
compiler(Set() ++ sourceFiles, Set() ++ xsbtiJars ++ sourceJars, outputDirectory, "-nowarn" :: Nil)
|
||||
manager.log.info(" Compilation completed in " + (System.currentTimeMillis - start) / 1000.0 + " s")
|
||||
}
|
||||
catch { case e: xsbti.CompileFailed => throw new CompileFailed(e.arguments, "Error compiling sbt component '" + id + "'") }
|
||||
|
|
|
|||
|
|
@ -3,30 +3,29 @@ package xsbt
|
|||
import java.io.File
|
||||
|
||||
/** A basic interface to the compiler. It is called in the same virtual machine, but no dependency analysis is done. This
|
||||
* is used, for example, to compile the interface/plugin code.*/
|
||||
class RawCompiler(val scalaInstance: ScalaInstance, log: CompileLogger)
|
||||
* is used, for example, to compile the interface/plugin code.
|
||||
* If `explicitClasspath` is true, the bootclasspath and classpath are not augmented. If it is false,
|
||||
* the scala-library.jar from `scalaInstance` is put on bootclasspath and the scala-compiler jar goes on the classpath.*/
|
||||
class RawCompiler(val scalaInstance: ScalaInstance, autoBootClasspath: Boolean, compilerOnClasspath: Boolean, log: CompileLogger)
|
||||
{
|
||||
def apply(sources: Set[File], classpath: Set[File], outputDirectory: File, options: Seq[String]): Unit =
|
||||
apply(sources, classpath, outputDirectory, options, false)
|
||||
def apply(sources: Set[File], classpath: Set[File], outputDirectory: File, options: Seq[String], compilerOnClasspath: Boolean)
|
||||
def apply(sources: Set[File], classpath: Set[File], outputDirectory: File, options: Seq[String])
|
||||
{
|
||||
// reflection is required for binary compatibility
|
||||
// The following imports ensure there is a compile error if the identifiers change,
|
||||
// The following import ensures there is a compile error if the identifiers change,
|
||||
// but should not be otherwise directly referenced
|
||||
import scala.tools.nsc.Main
|
||||
import scala.tools.nsc.Main.{process => _}
|
||||
|
||||
val arguments = (new CompilerArguments(scalaInstance))(sources, classpath, outputDirectory, options, compilerOnClasspath)
|
||||
val arguments = compilerArguments(sources, classpath, outputDirectory, options)
|
||||
log.debug("Plain interface to Scala compiler " + scalaInstance.actualVersion + " with arguments: " + arguments.mkString("\n\t", "\n\t", ""))
|
||||
val mainClass = Class.forName("scala.tools.nsc.Main", true, scalaInstance.loader)
|
||||
val process = mainClass.getMethod("process", classOf[Array[String]])
|
||||
process.invoke(null, toJavaArray(arguments))
|
||||
checkForFailure(mainClass, arguments.toArray)
|
||||
}
|
||||
def compilerArguments = new CompilerArguments(scalaInstance, autoBootClasspath, compilerOnClasspath)
|
||||
protected def checkForFailure(mainClass: Class[_], args: Array[String])
|
||||
{
|
||||
val reporter = mainClass.getMethod("reporter").invoke(null)
|
||||
// this is commented out because of Scala ticket #2365
|
||||
//val failed = reporter.asInstanceOf[{ def hasErrors: Boolean }].hasErrors
|
||||
val failed = reporter.getClass.getMethod("hasErrors").invoke(reporter).asInstanceOf[Boolean]
|
||||
if(failed) throw new CompileFailed(args, "Plain compile failed")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ package xsbt
|
|||
* for the compiler itself.
|
||||
* The 'version' field is the version used to obtain the Scala classes. This is typically the version for the maven repository.
|
||||
* The 'actualVersion' field should be used to uniquely identify the compiler. It is obtained from the compiler.properties file.*/
|
||||
final class ScalaInstance(val version: String, val loader: ClassLoader, val libraryJar: File, val compilerJar: File) extends NotNull
|
||||
final class ScalaInstance(val version: String, val loader: ClassLoader, val libraryJar: File, val compilerJar: File, val extraJars: Seq[File]) extends NotNull
|
||||
{
|
||||
require(version.indexOf(' ') < 0, "Version cannot contain spaces (was '" + version + "')")
|
||||
def jars = libraryJar :: compilerJar :: Nil
|
||||
def jars = libraryJar :: compilerJar :: extraJars.toList
|
||||
/** Gets the version of Scala in the compiler.properties file from the loader. This version may be different than that given by 'version'*/
|
||||
lazy val actualVersion = ScalaInstance.actualVersion(loader)(" version " + version)
|
||||
override def toString = "Scala instance{version label " + version + ", actual version " + actualVersion + ", library jar: " + libraryJar + ", compiler jar: " + compilerJar + "}"
|
||||
|
|
@ -22,20 +22,20 @@ object ScalaInstance
|
|||
def apply(version: String, launcher: xsbti.Launcher): ScalaInstance =
|
||||
apply(version, launcher.getScala(version))
|
||||
def apply(version: String, provider: xsbti.ScalaProvider): ScalaInstance =
|
||||
new ScalaInstance(version, provider.loader, provider.libraryJar, provider.compilerJar)
|
||||
new ScalaInstance(version, provider.loader, provider.libraryJar, provider.compilerJar, Nil)
|
||||
|
||||
def apply(scalaHome: File, launcher: xsbti.Launcher): ScalaInstance =
|
||||
apply(libraryJar(scalaHome), compilerJar(scalaHome), launcher)
|
||||
def apply(version: String, scalaHome: File, launcher: xsbti.Launcher): ScalaInstance =
|
||||
apply(version, libraryJar(scalaHome), compilerJar(scalaHome), launcher)
|
||||
def apply(libraryJar: File, compilerJar: File, launcher: xsbti.Launcher): ScalaInstance =
|
||||
def apply(libraryJar: File, compilerJar: File, launcher: xsbti.Launcher, extraJars: File*): ScalaInstance =
|
||||
{
|
||||
val loader = scalaLoader(launcher, libraryJar, compilerJar)
|
||||
val loader = scalaLoader(launcher, libraryJar :: compilerJar :: extraJars.toList)
|
||||
val version = actualVersion(loader)(" (library jar " + libraryJar.getAbsolutePath + ")")
|
||||
new ScalaInstance(version, loader, libraryJar, compilerJar)
|
||||
new ScalaInstance(version, loader, libraryJar, compilerJar, extraJars)
|
||||
}
|
||||
def apply(version: String, libraryJar: File, compilerJar: File, launcher: xsbti.Launcher): ScalaInstance =
|
||||
new ScalaInstance(version, scalaLoader(launcher, libraryJar, compilerJar), libraryJar, compilerJar)
|
||||
def apply(version: String, libraryJar: File, compilerJar: File, launcher: xsbti.Launcher, extraJars: File*): ScalaInstance =
|
||||
new ScalaInstance(version, scalaLoader(launcher, libraryJar :: compilerJar :: extraJars.toList), libraryJar, compilerJar, extraJars)
|
||||
|
||||
private def compilerJar(scalaHome: File) = scalaJar(scalaHome, "scala-compiler.jar")
|
||||
private def libraryJar(scalaHome: File) = scalaJar(scalaHome, "scala-library.jar")
|
||||
|
|
@ -50,7 +50,7 @@ object ScalaInstance
|
|||
}
|
||||
|
||||
import java.net.{URL, URLClassLoader}
|
||||
private def scalaLoader(launcher: xsbti.Launcher, jars: File*): ClassLoader =
|
||||
private def scalaLoader(launcher: xsbti.Launcher, jars: Seq[File]): ClassLoader =
|
||||
new URLClassLoader(jars.map(_.toURI.toURL).toArray[URL], launcher.topLoader)
|
||||
}
|
||||
class InvalidScalaInstance(message: String, cause: Throwable) extends RuntimeException(message, cause)
|
||||
|
|
@ -19,6 +19,7 @@ object Analyzer
|
|||
final class Analyzer(val global: Global, val callback: AnalysisCallback) extends NotNull
|
||||
{
|
||||
import global._
|
||||
import Compat.{linkedClass, nameString}
|
||||
|
||||
def newPhase(prev: Phase): Phase = new AnalyzerPhase(prev)
|
||||
private class AnalyzerPhase(prev: Phase) extends Phase(prev)
|
||||
|
|
@ -67,9 +68,9 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends
|
|||
{
|
||||
val isModule = sym.isModuleClass
|
||||
for(superclass <- superclasses.filter(sym.isSubClass))
|
||||
callback.foundSubclass(sourceFile, NameString(sym), NameString(superclass), isModule)
|
||||
callback.foundSubclass(sourceFile, nameString(sym), nameString(superclass), isModule)
|
||||
if(isModule && hasMainMethod(sym))
|
||||
callback.foundApplication(sourceFile, NameString(sym))
|
||||
callback.foundApplication(sourceFile, nameString(sym))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -85,7 +86,7 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends
|
|||
}
|
||||
if(sym.isModuleClass && !sym.isImplClass)
|
||||
{
|
||||
if(isTopLevelModule(sym) && sym.linkedClassOfModule == NoSymbol)
|
||||
if(isTopLevelModule(sym) && linkedClass(sym) == NoSymbol)
|
||||
addGenerated(false)
|
||||
addGenerated(true)
|
||||
}
|
||||
|
|
@ -118,7 +119,7 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends
|
|||
finder.findClass(name) orElse {
|
||||
if(isTopLevelModule(sym))
|
||||
{
|
||||
val linked = sym.linkedClassOfModule
|
||||
val linked = linkedClass(sym)
|
||||
if(linked == NoSymbol)
|
||||
None
|
||||
else
|
||||
|
|
@ -133,7 +134,7 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends
|
|||
private def moduleSuffix(sym: Symbol) =
|
||||
if (sym.hasFlag(Flags.MODULE) && !sym.isMethod && !sym.isImplClass && !sym.hasFlag(Flags.JAVA)) "$" else "";
|
||||
private def flatname(s: Symbol, separator: Char) =
|
||||
atPhase(currentRun.flattenPhase.next) { NameString(s, separator) }
|
||||
atPhase(currentRun.flattenPhase.next) { nameString(s, separator) }
|
||||
|
||||
private def isTopLevelModule(sym: Symbol): Boolean =
|
||||
atPhase (currentRun.picklerPhase.next) {
|
||||
|
|
@ -204,19 +205,24 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends
|
|||
if(entry eq null) None else Some(entry.classFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
private object NameString
|
||||
{
|
||||
def apply(s: Global#Symbol): String = s.fullNameString
|
||||
def apply(s: Global#Symbol, sep: Char): String = s.fullNameString(sep)
|
||||
|
||||
/** After 2.8.0.Beta1, fullNameString was renamed fullName.*/
|
||||
private implicit def symName(sym: Global#Symbol): WithString = new WithString(sym)
|
||||
private final class WithString(s: Global#Symbol)
|
||||
private object Compat
|
||||
{
|
||||
def fullNameString = s.fullName; def fullName = sourceCompatibilityOnly
|
||||
def fullNameString(sep: Char) = s.fullName(sep); def fullName(sep: Char) = sourceCompatibilityOnly
|
||||
private def sourceCompatibilityOnly = error("For source compatibility only: should not get here.")
|
||||
}
|
||||
def nameString(s: Symbol): String = s.fullNameString
|
||||
def nameString(s: Symbol, sep: Char): String = s.fullNameString(sep)
|
||||
|
||||
def linkedClass(s: Symbol): Symbol = s.linkedClassOfModule
|
||||
|
||||
/** After 2.8.0.Beta1, fullNameString was renamed fullName.
|
||||
* linkedClassOfModule was renamed companionClass. */
|
||||
private implicit def symName(sym: Symbol): WithString = new WithString(sym)
|
||||
private final class WithString(s: Symbol)
|
||||
{
|
||||
def fullNameString = s.fullName; def fullName = sourceCompatibilityOnly
|
||||
def fullNameString(sep: Char) = s.fullName(sep); def fullName(sep: Char) = sourceCompatibilityOnly
|
||||
private def sourceCompatibilityOnly = error("For source compatibility only: should not get here.")
|
||||
|
||||
def linkedClassOfModule = s.companionClass; def companionClass = sourceCompatibilityOnly
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,8 @@ class ConsoleInterface
|
|||
def run(bootClasspathString: String, classpathString: String, initialCommands: String, log: Logger)
|
||||
{
|
||||
val settings = Settings(log)
|
||||
settings.bootclasspath.value = bootClasspathString
|
||||
if(!bootClasspathString.isEmpty)
|
||||
settings.bootclasspath.value = bootClasspathString
|
||||
settings.classpath.value = classpathString
|
||||
log.info(Message("Starting scala interpreter..."))
|
||||
log.debug(Message(" Classpath: " + settings.classpath.value))
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
package xsbt
|
||||
|
||||
import xsbti.Logger
|
||||
import scala.tools.nsc.SubComponent
|
||||
import Log.debug
|
||||
|
||||
class ScaladocInterface
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
#Project properties
|
||||
#Mon Mar 22 18:24:15 EDT 2010
|
||||
project.name=Compile
|
||||
sbt.version=0.7.1
|
||||
|
|
@ -8,7 +8,7 @@ import org.specs._
|
|||
|
||||
object CompileTest extends Specification
|
||||
{
|
||||
"Analysis compiler" should {
|
||||
/*"Analysis compiler" should {
|
||||
"compile basic sources" in {
|
||||
WithCompiler( "2.7.2" )(testCompileAnalysis)
|
||||
WithCompiler( "2.7.3" )(testCompileAnalysis)
|
||||
|
|
@ -18,7 +18,16 @@ object CompileTest extends Specification
|
|||
WithCompiler( "2.8.0.Beta1" )(testCompileAnalysis)
|
||||
WithCompiler( "2.8.0-SNAPSHOT" )(testCompileAnalysis)
|
||||
}
|
||||
}*/
|
||||
|
||||
"Raw compiler" should {
|
||||
"Properly handle classpaths" in {
|
||||
testClasspath("2.7.2")
|
||||
testClasspath("2.7.7")
|
||||
testClasspath("2.8.0.Beta1")
|
||||
}
|
||||
}
|
||||
|
||||
private def testCompileAnalysis(compiler: AnalyzingCompiler, log: CompileLogger)
|
||||
{
|
||||
WithFiles( new File("Test.scala") -> "object Test" ) { sources =>
|
||||
|
|
@ -29,25 +38,69 @@ object CompileTest extends Specification
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
val UsingCompiler = "object Test { classOf[scala.tools.nsc.Global] }"
|
||||
|
||||
private def shouldFail(act: => Unit) =
|
||||
{
|
||||
val success = try { act; true } catch { case e: Exception => false }
|
||||
if(success) error("Expected exception not thrown")
|
||||
}
|
||||
private def isMissingRequirementError(t: Throwable) = t.getClass.getName == "scala.tools.nsc.MissingRequirementError"
|
||||
private def testClasspath(scalaVersion: String) =
|
||||
WithCompiler.launcher { (launch, log) =>
|
||||
def compiler(autoBoot: Boolean, compilerOnClasspath: Boolean): RawCompiler =
|
||||
new RawCompiler(ScalaInstance(scalaVersion, launch), autoBoot, compilerOnClasspath, log)
|
||||
|
||||
val callback = new xsbti.TestCallback(Array())
|
||||
|
||||
val standard = compiler(true, true)
|
||||
val noCompiler = compiler(true, false)
|
||||
val fullExplicit = compiler(false, false)
|
||||
|
||||
val fullBoot = "-bootclasspath" :: fullExplicit.compilerArguments.createBootClasspath :: Nil
|
||||
val withCompiler = Set() + noCompiler.scalaInstance.compilerJar
|
||||
|
||||
WithFiles( new File("Test.scala") -> "object Test", new File("Test2.scala") -> UsingCompiler ) { case Array(plain, useCompiler) =>
|
||||
val plainSrcs = Set[File](plain)
|
||||
val compSrcs = Set[File](useCompiler)
|
||||
FileUtilities.withTemporaryDirectory { out =>
|
||||
standard(plainSrcs, Set.empty, out, Nil) //success
|
||||
standard(compSrcs, Set.empty, out, Nil) //success
|
||||
|
||||
noCompiler(plainSrcs, Set.empty, out, Nil) //success
|
||||
shouldFail( noCompiler(compSrcs, Set.empty, out, Nil) )
|
||||
noCompiler(compSrcs, withCompiler, out, Nil) //success
|
||||
|
||||
shouldFail( fullExplicit(plainSrcs, Set.empty, out, Nil) )// failure
|
||||
shouldFail( fullExplicit(compSrcs, Set.empty, out, Nil) )// failure
|
||||
fullExplicit(plainSrcs, Set.empty, out, fullBoot) // success
|
||||
fullExplicit(compSrcs, withCompiler, out, fullBoot) // success
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
object WithCompiler
|
||||
{
|
||||
def apply[T](scalaVersion: String)(f: (AnalyzingCompiler, CompileLogger) => T): T =
|
||||
{
|
||||
System.setProperty("scala.home", "") // need to make sure scala.home is unset
|
||||
launcher { (launch, log) =>
|
||||
FileUtilities.withTemporaryDirectory { componentDirectory =>
|
||||
val manager = new ComponentManager(xsbt.boot.Locks, new boot.ComponentProvider(componentDirectory), log)
|
||||
val compiler = new AnalyzingCompiler(ScalaInstance(scalaVersion, launch), manager, log)
|
||||
compiler.newComponentCompiler(log).clearCache(ComponentCompiler.compilerInterfaceID)
|
||||
define(manager, ComponentCompiler.compilerInterfaceSrcID, getResource("CompilerInterface.scala"), getClassResource(classOf[jline.Completor]))
|
||||
define(manager, ComponentCompiler.xsbtiID, getClassResource(classOf[xsbti.AnalysisCallback]))
|
||||
f(compiler, log)
|
||||
}
|
||||
}
|
||||
}
|
||||
def launcher[T](f: (xsbti.Launcher, TestIvyLogger with CompileLogger) => T): T =
|
||||
{
|
||||
val log = new TestIvyLogger with CompileLogger
|
||||
log.setLevel(Level.Debug)
|
||||
log.bufferQuietly {
|
||||
boot.LaunchTest.withLauncher { launch =>
|
||||
FileUtilities.withTemporaryDirectory { componentDirectory =>
|
||||
val manager = new ComponentManager(xsbt.boot.Locks, new boot.ComponentProvider(componentDirectory), log)
|
||||
val compiler = new AnalyzingCompiler(ScalaInstance(scalaVersion, launch), manager, log)
|
||||
compiler.newComponentCompiler(log).clearCache(ComponentCompiler.compilerInterfaceID)
|
||||
define(manager, ComponentCompiler.compilerInterfaceSrcID, getResource("CompilerInterface.scala"), getClassResource(classOf[jline.Completor]))
|
||||
define(manager, ComponentCompiler.xsbtiID, getClassResource(classOf[xsbti.AnalysisCallback]))
|
||||
f(compiler, log)
|
||||
}
|
||||
}
|
||||
boot.LaunchTest.withLauncher { launch => f(launch, log) }
|
||||
}
|
||||
}
|
||||
def getClassResource(resource: Class[_]): File = FileUtilities.classLocationFile(resource)
|
||||
|
|
|
|||
Loading…
Reference in New Issue