mirror of https://github.com/sbt/sbt.git
commit
7e5b9c521e
|
|
@ -27,7 +27,7 @@ import sbt.io._
|
|||
import sbt.io.syntax._
|
||||
import sbt.util.{ Level, Logger, Show }
|
||||
import xsbti.compile.CompilerCache
|
||||
import xsbti.{ AppMain, AppProvider, ComponentProvider, ScalaProvider }
|
||||
import xsbti.{ AppMain, AppProvider, ComponentProvider, Launcher, ScalaProvider }
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import scala.concurrent.ExecutionContext
|
||||
|
|
@ -44,6 +44,14 @@ final class xMain extends xsbti.AppMain {
|
|||
val instance = clazz.getField("MODULE$").get(null)
|
||||
val runMethod = clazz.getMethod("run", classOf[xsbti.AppConfiguration])
|
||||
try {
|
||||
new Thread("sbt-load-global-instance") {
|
||||
setDaemon(true)
|
||||
override def run(): Unit = {
|
||||
// This preloads the scala.tools.nsc.Global as a performance optimization"
|
||||
loader.loadClass("sbt.internal.parser.SbtParser$").getField("MODULE$").get(null)
|
||||
()
|
||||
}
|
||||
}.start()
|
||||
runMethod.invoke(instance, modifiedConfiguration).asInstanceOf[xsbti.MainResult]
|
||||
} catch {
|
||||
case e: InvocationTargetException =>
|
||||
|
|
@ -62,11 +70,19 @@ final class xMain extends xsbti.AppMain {
|
|||
*/
|
||||
private class ModifiedConfiguration(val configuration: xsbti.AppConfiguration)
|
||||
extends xsbti.AppConfiguration {
|
||||
private[this] val initLoader = configuration.provider.loader
|
||||
private[this] val scalaLoader = configuration.provider.scalaProvider.loader
|
||||
private[this] val metaLoader: ClassLoader = SbtMetaBuildClassLoader(scalaLoader, initLoader)
|
||||
private[this] val metaLoader: ClassLoader = SbtMetaBuildClassLoader(configuration.provider)
|
||||
|
||||
private class ModifiedAppProvider(val appProvider: AppProvider) extends AppProvider {
|
||||
override def scalaProvider(): ScalaProvider = appProvider.scalaProvider
|
||||
override def scalaProvider(): ScalaProvider = new ScalaProvider {
|
||||
val delegate = configuration.provider.scalaProvider
|
||||
override def launcher(): Launcher = delegate.launcher
|
||||
override def version(): String = delegate.version
|
||||
override def loader(): ClassLoader = metaLoader.getParent
|
||||
override def jars(): Array[File] = delegate.jars
|
||||
override def libraryJar(): File = delegate.libraryJar
|
||||
override def compilerJar(): File = delegate.compilerJar
|
||||
override def app(id: xsbti.ApplicationID): AppProvider = delegate.app(id)
|
||||
}
|
||||
override def id(): xsbti.ApplicationID = appProvider.id()
|
||||
override def loader(): ClassLoader = metaLoader
|
||||
@deprecated("Implements deprecated api", "1.3.0")
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@ import sbt.internal.util.Attributed
|
|||
import sbt.internal.util.Attributed.data
|
||||
import sbt.io.IO
|
||||
import sbt.librarymanagement.Configurations.{ Runtime, Test }
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import xsbti.AppProvider
|
||||
|
||||
private[sbt] object ClassLoaders {
|
||||
private[this] val interfaceLoader = classOf[sbt.testing.Framework].getClassLoader
|
||||
|
|
@ -202,36 +201,15 @@ private[sbt] object ClassLoaders {
|
|||
}
|
||||
|
||||
private[sbt] object SbtMetaBuildClassLoader {
|
||||
private[this] implicit class Ops(val c: ClassLoader) {
|
||||
def urls: Array[URL] = c match {
|
||||
case u: URLClassLoader => u.getURLs
|
||||
case cl =>
|
||||
throw new IllegalStateException(s"sbt was launched with a non URLClassLoader: $cl")
|
||||
}
|
||||
}
|
||||
def apply(scalaProviderLoader: ClassLoader, fullLoader: ClassLoader): ClassLoader = {
|
||||
val libFilter: URL => Boolean = _.getFile.endsWith("scala-library.jar")
|
||||
def bootLoader(loader: ClassLoader): ClassLoader = {
|
||||
@tailrec def getAllParents(
|
||||
classLoader: ClassLoader,
|
||||
parents: List[ClassLoader]
|
||||
): List[ClassLoader] = classLoader.getParent match {
|
||||
case null => parents
|
||||
case cl => getAllParents(cl, classLoader :: parents)
|
||||
}
|
||||
@tailrec def getLoader(remaining: List[ClassLoader]): ClassLoader = remaining match {
|
||||
case head :: (next: URLClassLoader) :: _ if next.getURLs.exists(libFilter) => head
|
||||
case head :: Nil => head
|
||||
case _ :: tail => getLoader(tail)
|
||||
}
|
||||
getLoader(getAllParents(loader, Nil))
|
||||
}
|
||||
def apply(appProvider: AppProvider): ClassLoader = {
|
||||
val interfaceFilter: URL => Boolean = _.getFile.endsWith("test-interface-1.0.jar")
|
||||
val (interfaceURL, rest) = fullLoader.urls.partition(interfaceFilter)
|
||||
val interfaceLoader = new URLClassLoader(interfaceURL, bootLoader(scalaProviderLoader)) {
|
||||
def urls(jars: Array[File]): Array[URL] = jars.map(_.toURI.toURL)
|
||||
val (interfaceURL, rest) = urls(appProvider.mainClasspath).partition(interfaceFilter)
|
||||
val scalaProvider = appProvider.scalaProvider
|
||||
val interfaceLoader = new URLClassLoader(interfaceURL, scalaProvider.launcher.topLoader) {
|
||||
override def toString: String = s"SbtTestInterfaceClassLoader(${getURLs.head})"
|
||||
}
|
||||
val updatedLibraryLoader = new URLClassLoader(scalaProviderLoader.urls, interfaceLoader) {
|
||||
val updatedLibraryLoader = new URLClassLoader(urls(scalaProvider.jars), interfaceLoader) {
|
||||
override def toString: String = s"ScalaClassLoader(jars = {${getURLs.mkString(", ")}}"
|
||||
}
|
||||
new URLClassLoader(rest, updatedLibraryLoader) {
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ private[sbt] object SbtParser {
|
|||
private[sbt] final val globalReporter = new UniqueParserReporter
|
||||
private[sbt] var scalacGlobalInitReporter: Option[ConsoleReporter] = None
|
||||
|
||||
private[sbt] final lazy val defaultGlobalForParser = {
|
||||
private[sbt] final val defaultGlobalForParser = {
|
||||
val options = "-cp" :: s"$defaultClasspath" :: "-Yrangepos" :: Nil
|
||||
val reportError = (msg: String) => System.err.println(msg)
|
||||
val command = new CompilerCommand(options, reportError)
|
||||
|
|
|
|||
Loading…
Reference in New Issue