2010-06-27 15:18:35 +02:00
|
|
|
/* sbt -- Simple Build Tool
|
|
|
|
|
* Copyright 2010 Mark Harrah
|
|
|
|
|
*/
|
|
|
|
|
package sbt
|
2010-07-17 18:07:41 +02:00
|
|
|
package build
|
2010-06-27 15:18:35 +02:00
|
|
|
|
|
|
|
|
import inc._
|
|
|
|
|
|
|
|
|
|
import java.io.File
|
2010-07-15 01:24:50 +02:00
|
|
|
import compile.{AnalyzingCompiler, CompilerArguments, JavaCompiler}
|
|
|
|
|
import classpath.ClasspathUtilities
|
|
|
|
|
import classfile.Analyze
|
2010-06-27 15:18:35 +02:00
|
|
|
import xsbti.api.Source
|
|
|
|
|
import xsbti.AnalysisCallback
|
|
|
|
|
import CompileSetup._
|
|
|
|
|
import sbinary.DefaultProtocol.{ immutableMapFormat, immutableSetFormat, StringFormat }
|
|
|
|
|
|
2010-07-15 01:24:50 +02:00
|
|
|
final class CompileConfiguration(val sources: Seq[File], val classpath: Seq[File], val javaSrcBases: Seq[File],
|
|
|
|
|
val previousAnalysis: Analysis, val previousSetup: Option[CompileSetup], val currentSetup: CompileSetup, val getAnalysis: File => Option[Analysis],
|
|
|
|
|
val maxErrors: Int, val compiler: AnalyzingCompiler, val javac: JavaCompiler)
|
2010-06-27 15:18:35 +02:00
|
|
|
|
|
|
|
|
class AggressiveCompile(cacheDirectory: File)
|
|
|
|
|
{
|
2010-09-18 03:38:40 +02:00
|
|
|
def apply(compiler: AnalyzingCompiler, javac: JavaCompiler, sources: Seq[File], classpath: Seq[File], outputDirectory: File, javaSrcBases: Seq[File] = Nil, options: Seq[String] = Nil, javacOptions: Seq[String] = Nil, analysisMap: Map[File, Analysis] = Map.empty, maxErrors: Int = 100)(implicit log: Logger): Analysis =
|
2010-06-27 15:18:35 +02:00
|
|
|
{
|
2010-07-15 01:24:50 +02:00
|
|
|
val setup = new CompileSetup(outputDirectory, new CompileOptions(options, javacOptions), compiler.scalaInstance.actualVersion, CompileOrder.Mixed)
|
2010-09-18 03:38:40 +02:00
|
|
|
compile1(sources, classpath, javaSrcBases, setup, store, analysisMap, compiler, javac, maxErrors)
|
2010-06-27 15:18:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def withBootclasspath(args: CompilerArguments, classpath: Seq[File]): Seq[File] =
|
2010-09-18 03:38:40 +02:00
|
|
|
args.bootClasspath ++ args.finishClasspath(classpath)
|
2010-06-27 15:18:35 +02:00
|
|
|
|
2010-07-15 01:24:50 +02:00
|
|
|
def compile1(sources: Seq[File], classpath: Seq[File], javaSrcBases: Seq[File], setup: CompileSetup, store: AnalysisStore, analysis: Map[File, Analysis], compiler: AnalyzingCompiler, javac: JavaCompiler, maxErrors: Int)(implicit log: Logger): Analysis =
|
2010-06-27 15:18:35 +02:00
|
|
|
{
|
2010-07-02 12:57:03 +02:00
|
|
|
val (previousAnalysis, previousSetup) = extract(store.get())
|
2010-07-15 01:24:50 +02:00
|
|
|
val config = new CompileConfiguration(sources, classpath, javaSrcBases, previousAnalysis, previousSetup, setup, analysis.get _, maxErrors, compiler, javac)
|
|
|
|
|
val result = compile2(config)
|
2010-06-27 15:18:35 +02:00
|
|
|
store.set(result, setup)
|
|
|
|
|
result
|
|
|
|
|
}
|
2010-07-15 01:24:50 +02:00
|
|
|
def compile2(config: CompileConfiguration)(implicit log: Logger, equiv: Equiv[CompileSetup]): Analysis =
|
2010-06-27 15:18:35 +02:00
|
|
|
{
|
|
|
|
|
import config._
|
|
|
|
|
import currentSetup._
|
|
|
|
|
val getAPI = (f: File) => {
|
|
|
|
|
val extApis = getAnalysis(f) match { case Some(a) => a.apis.external; case None => Map.empty[String, Source] }
|
|
|
|
|
extApis.get _
|
|
|
|
|
}
|
2010-09-18 03:38:40 +02:00
|
|
|
val apiOption= (api: Either[Boolean, Source]) => api.right.toOption
|
2010-06-27 15:18:35 +02:00
|
|
|
val cArgs = new CompilerArguments(compiler.scalaInstance, compiler.cp)
|
2010-09-18 03:38:40 +02:00
|
|
|
val searchClasspath = withBootclasspath(cArgs, classpath)
|
|
|
|
|
val entry = Locate.entry(searchClasspath)
|
2010-07-15 01:24:50 +02:00
|
|
|
|
2010-06-27 15:18:35 +02:00
|
|
|
val compile0 = (include: Set[File], callback: AnalysisCallback) => {
|
2010-07-02 12:57:03 +02:00
|
|
|
IO.createDirectory(outputDirectory)
|
2010-07-15 01:24:50 +02:00
|
|
|
val incSrc = sources.filter(include)
|
|
|
|
|
val arguments = cArgs(incSrc, classpath, outputDirectory, options.options)
|
2010-06-27 15:18:35 +02:00
|
|
|
compiler.compile(arguments, callback, maxErrors, log)
|
2010-07-15 01:24:50 +02:00
|
|
|
val javaSrcs = incSrc.filter(javaOnly)
|
|
|
|
|
if(!javaSrcs.isEmpty)
|
|
|
|
|
{
|
|
|
|
|
import Path._
|
|
|
|
|
val loader = ClasspathUtilities.toLoader(classpath, compiler.scalaInstance.loader)
|
|
|
|
|
// TODO: Analyze needs to generate API from Java class files
|
|
|
|
|
Analyze(outputDirectory, javaSrcs, javaSrcBases, log)(callback, loader) {
|
|
|
|
|
javac(javaSrcs, classpath, outputDirectory, options.javacOptions)
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-06-27 15:18:35 +02:00
|
|
|
}
|
2010-07-15 01:24:50 +02:00
|
|
|
|
2010-06-27 15:18:35 +02:00
|
|
|
val sourcesSet = sources.toSet
|
2010-07-02 12:57:03 +02:00
|
|
|
val analysis = previousSetup match {
|
|
|
|
|
case Some(previous) if equiv.equiv(previous, currentSetup) => previousAnalysis
|
|
|
|
|
case _ => Incremental.prune(sourcesSet, previousAnalysis)
|
|
|
|
|
}
|
2010-09-18 03:38:40 +02:00
|
|
|
IncrementalCompile(sourcesSet, entry, compile0, analysis, getAnalysis, outputDirectory)
|
2010-06-27 15:18:35 +02:00
|
|
|
}
|
2010-07-02 12:57:03 +02:00
|
|
|
private def extract(previous: Option[(Analysis, CompileSetup)]): (Analysis, Option[CompileSetup]) =
|
|
|
|
|
previous match
|
|
|
|
|
{
|
|
|
|
|
case Some((an, setup)) => (an, Some(setup))
|
|
|
|
|
case None => (Analysis.Empty, None)
|
|
|
|
|
}
|
2010-07-15 01:24:50 +02:00
|
|
|
def javaOnly(f: File) = f.getName.endsWith(".java")
|
2010-06-27 15:18:35 +02:00
|
|
|
|
|
|
|
|
import AnalysisFormats._
|
2010-09-22 04:29:18 +02:00
|
|
|
val store = AnalysisStore.sync(AnalysisStore.cached(FileBasedStore(cacheDirectory)))
|
2010-06-27 15:18:35 +02:00
|
|
|
}
|