Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 2f4be49cf6
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 134 lines (115 sloc) 5.285 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
/* sbt -- Simple Build Tool
* Copyright 2010 Mark Harrah
*/
package sbt

import xsbti.{Logger => _,_}
import compiler._
import inc._
import java.io.File

object Compiler
{
val DefaultMaxErrors = 100

def allProblems(inc: Incomplete): Seq[Problem] =
allProblems(inc :: Nil)
def allProblems(incs: Seq[Incomplete]): Seq[Problem] =
problems(Incomplete.allExceptions(incs).toSeq)
def problems(es: Seq[Throwable]): Seq[Problem] =
es flatMap {
case cf: xsbti.CompileFailed => cf.problems
case _ => Nil
}

final case class Inputs(compilers: Compilers, config: Options, incSetup: IncSetup)
final case class Options(classpath: Seq[File], sources: Seq[File], classesDirectory: File, options: Seq[String], javacOptions: Seq[String], maxErrors: Int, order: CompileOrder.Value)
final case class IncSetup(analysisMap: Map[File, Analysis], cacheDirectory: File)
final case class Compilers(scalac: AnalyzingCompiler, javac: JavaCompiler)

def inputs(classpath: Seq[File], sources: Seq[File], outputDirectory: File, options: Seq[String], javacOptions: Seq[String], maxErrors: Int, order: CompileOrder.Value)(implicit compilers: Compilers, log: Logger): Inputs =
{
import Path._
val classesDirectory = outputDirectory / "classes"
val cacheDirectory = outputDirectory / "cache"
val augClasspath = classesDirectory.asFile +: classpath
inputs(augClasspath, sources, classesDirectory, options, javacOptions, Map.empty, cacheDirectory, maxErrors, order)
}
def inputs(classpath: Seq[File], sources: Seq[File], classesDirectory: File, options: Seq[String], javacOptions: Seq[String], analysisMap: Map[File, Analysis], cacheDirectory: File, maxErrors: Int, order: CompileOrder.Value)(implicit compilers: Compilers, log: Logger): Inputs =
new Inputs(
compilers,
new Options(classpath, sources, classesDirectory, options, javacOptions, maxErrors, order),
new IncSetup(analysisMap, cacheDirectory)
)

def compilers(cpOptions: ClasspathOptions)(implicit app: AppConfiguration, log: Logger): Compilers =
{
val scalaProvider = app.provider.scalaProvider
compilers(ScalaInstance(scalaProvider.version, scalaProvider.launcher), cpOptions)
}

def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions)(implicit app: AppConfiguration, log: Logger): Compilers =
compilers(instance, cpOptions, None)

def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions, javaHome: Option[File])(implicit app: AppConfiguration, log: Logger): Compilers =
{
val javac = directOrFork(instance, cpOptions, javaHome)
compilers(instance, cpOptions, javac)
}
def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions, javac: (Seq[String], Logger) => Int)(implicit app: AppConfiguration, log: Logger): Compilers =
{
val javaCompiler = JavaCompiler.fork(cpOptions, instance)(javac)
compilers(instance, cpOptions, javaCompiler)
}
def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions, javac: JavaCompiler)(implicit app: AppConfiguration, log: Logger): Compilers =
{
val scalac = scalaCompiler(instance, cpOptions)
new Compilers(scalac, javac)
}
def scalaCompiler(instance: ScalaInstance, cpOptions: ClasspathOptions)(implicit app: AppConfiguration, log: Logger): AnalyzingCompiler =
{
val launcher = app.provider.scalaProvider.launcher
val componentManager = new ComponentManager(launcher.globalLock, app.provider.components, log)
new AnalyzingCompiler(instance, componentManager, 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]): (Seq[String], Logger) => Int =
{
import Path._
val exec = javaHome match { case None => "javac"; case Some(jh) => (jh / "bin" / "javac").absolutePath }
(args: Seq[String], log: Logger) => {
log.debug("Forking javac: " + exec + " " + args.mkString(" "))
val javacLogger = new JavacLogger(log)
var exitCode = -1
try {
exitCode = Process(exec, args) ! javacLogger
} finally {
javacLogger.flush(exitCode)
}
exitCode
}
}

def apply(in: Inputs, log: Logger): Analysis =
{
import in.compilers._
import in.config._
import in.incSetup._

val agg = new AggressiveCompile(cacheDirectory)
agg(scalac, javac, sources, classpath, classesDirectory, options, javacOptions, analysisMap, maxErrors, order)(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()
  }
}
Something went wrong with that request. Please try again.