Merge pull request #4675 from eatkins/startup

Startup
This commit is contained in:
eugene yokota 2019-05-13 20:10:05 -04:00 committed by GitHub
commit 7e5b9c521e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 35 deletions

View File

@ -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")

View File

@ -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) {

View File

@ -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)