From 7edcc68a92837eba710a278b8523d1e4e478eafe Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Mon, 22 Mar 2010 20:42:59 -0400 Subject: [PATCH] support cross-compiling/bootstrapping --- compile/AnalyzingCompiler.scala | 30 +++------ compile/CompilerArguments.scala | 10 +-- compile/ComponentCompiler.scala | 2 +- compile/RawCompiler.scala | 19 +++--- compile/ScalaInstance.scala | 18 +++--- compile/interface/Analyzer.scala | 42 +++++++------ compile/interface/ConsoleInterface.scala | 3 +- compile/interface/ScaladocInterface.scala | 1 - compile/project/build.properties | 4 ++ compile/src/test/scala/CompileTest.scala | 77 +++++++++++++++++++---- 10 files changed, 128 insertions(+), 78 deletions(-) create mode 100644 compile/project/build.properties diff --git a/compile/AnalyzingCompiler.scala b/compile/AnalyzingCompiler.scala index 1412de461..cfcccf75f 100644 --- a/compile/AnalyzingCompiler.scala +++ b/compile/AnalyzingCompiler.scala @@ -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.") diff --git a/compile/CompilerArguments.scala b/compile/CompilerArguments.scala index f22a5491b..65cf60a46 100644 --- a/compile/CompilerArguments.scala +++ b/compile/CompilerArguments.scala @@ -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() diff --git a/compile/ComponentCompiler.scala b/compile/ComponentCompiler.scala index d8522168b..582c2eaf2 100644 --- a/compile/ComponentCompiler.scala +++ b/compile/ComponentCompiler.scala @@ -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 + "'") } diff --git a/compile/RawCompiler.scala b/compile/RawCompiler.scala index 0e4d87f38..1febddea7 100644 --- a/compile/RawCompiler.scala +++ b/compile/RawCompiler.scala @@ -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") } diff --git a/compile/ScalaInstance.scala b/compile/ScalaInstance.scala index 31b608621..c1a69111b 100644 --- a/compile/ScalaInstance.scala +++ b/compile/ScalaInstance.scala @@ -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) \ No newline at end of file diff --git a/compile/interface/Analyzer.scala b/compile/interface/Analyzer.scala index 4f1f51ef3..d5d21d396 100644 --- a/compile/interface/Analyzer.scala +++ b/compile/interface/Analyzer.scala @@ -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 + } + + } } \ No newline at end of file diff --git a/compile/interface/ConsoleInterface.scala b/compile/interface/ConsoleInterface.scala index 51e54cedc..9091b3271 100644 --- a/compile/interface/ConsoleInterface.scala +++ b/compile/interface/ConsoleInterface.scala @@ -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)) diff --git a/compile/interface/ScaladocInterface.scala b/compile/interface/ScaladocInterface.scala index 1b5d5e0f6..9c3bb66c9 100644 --- a/compile/interface/ScaladocInterface.scala +++ b/compile/interface/ScaladocInterface.scala @@ -4,7 +4,6 @@ package xsbt import xsbti.Logger -import scala.tools.nsc.SubComponent import Log.debug class ScaladocInterface diff --git a/compile/project/build.properties b/compile/project/build.properties new file mode 100644 index 000000000..e90a50a05 --- /dev/null +++ b/compile/project/build.properties @@ -0,0 +1,4 @@ +#Project properties +#Mon Mar 22 18:24:15 EDT 2010 +project.name=Compile +sbt.version=0.7.1 diff --git a/compile/src/test/scala/CompileTest.scala b/compile/src/test/scala/CompileTest.scala index b122910aa..000272daa 100644 --- a/compile/src/test/scala/CompileTest.scala +++ b/compile/src/test/scala/CompileTest.scala @@ -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)