mirror of https://github.com/sbt/sbt.git
Allow bytecode enhancement to update analysis
This breaks the loading/saving of the incremental compiler analysis out into separate task, thereby providing the necessary hooks for byte code enhancement tasks to enhance bytecode and update the analysis before the analysis gets stored to disk.
This commit is contained in:
parent
e2942f167b
commit
0f784ab101
|
|
@ -24,7 +24,7 @@ final class CompileConfiguration(val sources: Seq[File], val classpath: Seq[File
|
|||
val previousAnalysis: Analysis, val previousSetup: Option[CompileSetup], val currentSetup: CompileSetup, val progress: Option[CompileProgress], val getAnalysis: File => Option[Analysis], val definesClass: DefinesClass,
|
||||
val reporter: Reporter, val compiler: AnalyzingCompiler, val javac: xsbti.compile.JavaCompiler, val cache: GlobalsCache, val incOptions: IncOptions)
|
||||
|
||||
class AggressiveCompile(cacheFile: File) {
|
||||
class AggressiveCompile {
|
||||
def apply(compiler: AnalyzingCompiler,
|
||||
javac: xsbti.compile.JavaCompiler,
|
||||
sources: Seq[File], classpath: Seq[File],
|
||||
|
|
@ -33,17 +33,20 @@ class AggressiveCompile(cacheFile: File) {
|
|||
progress: Option[CompileProgress] = None,
|
||||
options: Seq[String] = Nil,
|
||||
javacOptions: Seq[String] = Nil,
|
||||
previousAnalysis: Analysis,
|
||||
previousSetup: Option[CompileSetup],
|
||||
analysisMap: File => Option[Analysis] = { _ => None },
|
||||
definesClass: DefinesClass = Locate.definesClass _,
|
||||
reporter: Reporter,
|
||||
compileOrder: CompileOrder = Mixed,
|
||||
skip: Boolean = false,
|
||||
incrementalCompilerOptions: IncOptions)(implicit log: Logger): Analysis =
|
||||
incrementalCompilerOptions: IncOptions)(implicit log: Logger): (Analysis, CompileSetup, Boolean) =
|
||||
{
|
||||
val setup = new CompileSetup(output, new CompileOptions(options, javacOptions),
|
||||
compiler.scalaInstance.actualVersion, compileOrder, incrementalCompilerOptions.nameHashing)
|
||||
compile1(sources, classpath, setup, progress, store, analysisMap, definesClass,
|
||||
val (analysis, modified) = compile1(sources, classpath, setup, progress, previousAnalysis, previousSetup, analysisMap, definesClass,
|
||||
compiler, javac, reporter, skip, cache, incrementalCompilerOptions)
|
||||
(analysis, setup, modified)
|
||||
}
|
||||
|
||||
def withBootclasspath(args: CompilerArguments, classpath: Seq[File]): Seq[File] =
|
||||
|
|
@ -52,25 +55,23 @@ class AggressiveCompile(cacheFile: File) {
|
|||
def compile1(sources: Seq[File],
|
||||
classpath: Seq[File],
|
||||
setup: CompileSetup, progress: Option[CompileProgress],
|
||||
store: AnalysisStore,
|
||||
previousAnalysis: Analysis,
|
||||
previousSetup: Option[CompileSetup],
|
||||
analysis: File => Option[Analysis],
|
||||
definesClass: DefinesClass,
|
||||
compiler: AnalyzingCompiler,
|
||||
javac: xsbti.compile.JavaCompiler,
|
||||
reporter: Reporter, skip: Boolean,
|
||||
cache: GlobalsCache,
|
||||
incrementalCompilerOptions: IncOptions)(implicit log: Logger): Analysis =
|
||||
incrementalCompilerOptions: IncOptions)(implicit log: Logger): (Analysis, Boolean) =
|
||||
{
|
||||
val (previousAnalysis, previousSetup) = extract(store.get(), incrementalCompilerOptions)
|
||||
if (skip)
|
||||
previousAnalysis
|
||||
(previousAnalysis, false)
|
||||
else {
|
||||
val config = new CompileConfiguration(sources, classpath, previousAnalysis, previousSetup, setup,
|
||||
progress, analysis, definesClass, reporter, compiler, javac, cache, incrementalCompilerOptions)
|
||||
val (modified, result) = compile2(config)
|
||||
if (modified)
|
||||
store.set(result, setup)
|
||||
result
|
||||
(result, modified)
|
||||
}
|
||||
}
|
||||
def compile2(config: CompileConfiguration)(implicit log: Logger, equiv: Equiv[CompileSetup]): (Boolean, Analysis) =
|
||||
|
|
@ -176,17 +177,11 @@ class AggressiveCompile(cacheFile: File) {
|
|||
if (!combined.isEmpty)
|
||||
log.info(combined.mkString("Compiling ", " and ", " to " + outputDirs.map(_.getAbsolutePath).mkString(",") + "..."))
|
||||
}
|
||||
private def extract(previous: Option[(Analysis, CompileSetup)], incOptions: IncOptions): (Analysis, Option[CompileSetup]) =
|
||||
previous match {
|
||||
case Some((an, setup)) => (an, Some(setup))
|
||||
case None => (Analysis.empty(nameHashing = incOptions.nameHashing), None)
|
||||
}
|
||||
def javaOnly(f: File) = f.getName.endsWith(".java")
|
||||
|
||||
private[this] def explicitBootClasspath(options: Seq[String]): Seq[File] =
|
||||
options.dropWhile(_ != CompilerArguments.BootClasspathOption).drop(1).take(1).headOption.toList.flatMap(IO.parseClasspath)
|
||||
|
||||
val store = AggressiveCompile.staticCache(cacheFile, AnalysisStore.sync(AnalysisStore.cached(FileBasedStore(cacheFile))))
|
||||
}
|
||||
object AggressiveCompile {
|
||||
import collection.mutable
|
||||
|
|
@ -200,6 +195,9 @@ object AggressiveCompile {
|
|||
b
|
||||
}
|
||||
}
|
||||
|
||||
def staticCachedStore(cacheFile: File) = staticCache(cacheFile, AnalysisStore.sync(AnalysisStore.cached(FileBasedStore(cacheFile))))
|
||||
|
||||
@deprecated("0.13.8", "Deprecated in favor of new sbt.compiler.javac package.")
|
||||
def directOrFork(instance: ScalaInstance, cpOptions: ClasspathOptions, javaHome: Option[File]): JavaTool =
|
||||
if (javaHome.isDefined)
|
||||
|
|
|
|||
|
|
@ -12,12 +12,19 @@ object IC extends IncrementalCompiler[Analysis, AnalyzingCompiler] {
|
|||
val setup = in.setup; import setup._
|
||||
val options = in.options; import options.{ options => scalacOptions, _ }
|
||||
val compilers = in.compilers; import compilers._
|
||||
val agg = new AggressiveCompile(setup.cacheFile)
|
||||
val agg = new AggressiveCompile
|
||||
val aMap = (f: File) => m2o(analysisMap(f))
|
||||
val defClass = (f: File) => { val dc = definesClass(f); (name: String) => dc.apply(name) }
|
||||
val incOptions = IncOptions.fromStringMap(incrementalCompilerOptions)
|
||||
agg(scalac, javac, sources, classpath, output, cache, m2o(progress), scalacOptions, javacOptions, aMap,
|
||||
defClass, reporter, order, skip, incOptions)(log)
|
||||
val (previousAnalysis, previousSetup) = {
|
||||
AggressiveCompile.staticCachedStore(setup.cacheFile()).get().map {
|
||||
case (a, s) => (a, Some(s))
|
||||
} getOrElse {
|
||||
(Analysis.empty(nameHashing = incOptions.nameHashing), None)
|
||||
}
|
||||
}
|
||||
agg(scalac, javac, sources, classpath, output, cache, m2o(progress), scalacOptions, javacOptions, previousAnalysis,
|
||||
previousSetup, aMap, defClass, reporter, order, skip, incOptions)(log)._1
|
||||
}
|
||||
|
||||
private[this] def m2o[S](opt: Maybe[S]): Option[S] = if (opt.isEmpty) None else Some(opt.get)
|
||||
|
|
|
|||
|
|
@ -15,9 +15,10 @@ import java.io.File
|
|||
object Compiler {
|
||||
val DefaultMaxErrors = 100
|
||||
|
||||
final case class Inputs(compilers: Compilers, config: Options, incSetup: IncSetup)
|
||||
final case class Inputs(compilers: Compilers, config: Options, incSetup: IncSetup, previousAnalysis: PreviousAnalysis)
|
||||
final case class Options(classpath: Seq[File], sources: Seq[File], classesDirectory: File, options: Seq[String], javacOptions: Seq[String], maxErrors: Int, sourcePositionMapper: Position => Position, order: CompileOrder)
|
||||
final case class IncSetup(analysisMap: File => Option[Analysis], definesClass: DefinesClass, skip: Boolean, cacheFile: File, cache: GlobalsCache, incOptions: IncOptions)
|
||||
<<<<<<< HEAD
|
||||
private[sbt] trait JavaToolWithNewInterface extends JavaTool {
|
||||
def newJavac: IncrementalCompilerJavaTools
|
||||
}
|
||||
|
|
@ -29,12 +30,20 @@ object Compiler {
|
|||
}
|
||||
}
|
||||
final case class NewCompilers(scalac: AnalyzingCompiler, javac: JavaTools)
|
||||
=======
|
||||
final case class Compilers(scalac: AnalyzingCompiler, javac: JavaTool)
|
||||
final case class PreviousAnalysis(analysis: Analysis, setup: Option[CompileSetup])
|
||||
final case class AnalysisResult(analysis: Analysis, setup: CompileSetup, modified: Boolean)
|
||||
>>>>>>> Allow bytecode enhancement to update analysis
|
||||
|
||||
def inputs(classpath: Seq[File], sources: Seq[File], classesDirectory: File, options: Seq[String], javacOptions: Seq[String], maxErrors: Int, sourcePositionMappers: Seq[Position => Option[Position]], order: CompileOrder)(implicit compilers: Compilers, incSetup: IncSetup, log: Logger): Inputs =
|
||||
def inputs(classpath: Seq[File], sources: Seq[File], classesDirectory: File, options: Seq[String],
|
||||
javacOptions: Seq[String], maxErrors: Int, sourcePositionMappers: Seq[Position => Option[Position]],
|
||||
order: CompileOrder, previousAnalysis: PreviousAnalysis)(implicit compilers: Compilers, incSetup: IncSetup, log: Logger): Inputs =
|
||||
new Inputs(
|
||||
compilers,
|
||||
new Options(classpath, sources, classesDirectory, options, javacOptions, maxErrors, foldMappers(sourcePositionMappers), order),
|
||||
incSetup
|
||||
incSetup,
|
||||
previousAnalysis
|
||||
)
|
||||
|
||||
def compilers(cpOptions: ClasspathOptions)(implicit app: AppConfiguration, log: Logger): Compilers =
|
||||
|
|
@ -79,14 +88,14 @@ object Compiler {
|
|||
val provider = ComponentCompiler.interfaceProvider(componentManager)
|
||||
new AnalyzingCompiler(instance, provider, cpOptions, log)
|
||||
}
|
||||
def apply(in: Inputs, log: Logger): Analysis =
|
||||
def apply(in: Inputs, log: Logger): AnalysisResult =
|
||||
{
|
||||
import in.compilers._
|
||||
import in.config._
|
||||
import in.incSetup._
|
||||
apply(in, log, new LoggerReporter(maxErrors, log, sourcePositionMapper))
|
||||
}
|
||||
def apply(in: Inputs, log: Logger, reporter: xsbti.Reporter): Analysis =
|
||||
def apply(in: Inputs, log: Logger, reporter: xsbti.Reporter): AnalysisResult =
|
||||
{
|
||||
import in.compilers._
|
||||
import in.config._
|
||||
|
|
@ -98,7 +107,7 @@ object Compiler {
|
|||
val javacChosen: xsbti.compile.JavaCompiler =
|
||||
in.compilers.newJavac.map(_.xsbtiCompiler).getOrElse(in.compilers.javac)
|
||||
agg(scalac, javacChosen, sources, classpath, CompileOutput(classesDirectory), cache, None, options, javacOptions,
|
||||
analysisMap, definesClass, reporter, order, skip, incOptions)(log)
|
||||
in.previousAnalysis.analysis, in.previousAnalysis.setup, analysisMap, definesClass, reporter, order, skip, incOptions)(log)
|
||||
}
|
||||
|
||||
private[sbt] def foldMappers[A](mappers: Seq[A => Option[A]]) =
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ import Configurations.{ Compile, CompilerPlugin, IntegrationTest, names, Provide
|
|||
import CrossVersion.{ binarySbtVersion, binaryScalaVersion, partialVersion }
|
||||
import complete._
|
||||
import std.TaskExtra._
|
||||
import inc.{ FileValueCache, IncOptions, Locate }
|
||||
import sbt.inc.{ Analysis, FileValueCache, IncOptions, Locate }
|
||||
import sbt.compiler.AggressiveCompile
|
||||
import testing.{ Framework, Runner, AnnotatedFingerprint, SubclassFingerprint }
|
||||
|
||||
import sys.error
|
||||
|
|
@ -246,8 +247,9 @@ object Defaults extends BuildCommon {
|
|||
|
||||
def compilersSetting = compilers := Compiler.compilers(scalaInstance.value, classpathOptions.value, javaHome.value)(appConfiguration.value, streams.value.log)
|
||||
|
||||
lazy val configTasks = docTaskSettings(doc) ++ inTask(compile)(compileInputsSettings) ++ configGlobal ++ Seq(
|
||||
compile <<= compileTask tag (Tags.Compile, Tags.CPU),
|
||||
lazy val configTasks = docTaskSettings(doc) ++ inTask(compile)(compileInputsSettings) ++ configGlobal ++ compileAnalysisSettings ++ Seq(
|
||||
compile <<= compileTask,
|
||||
compileIncremental <<= compileIncrementalTask tag (Tags.Compile, Tags.CPU),
|
||||
printWarnings <<= printWarningsTask,
|
||||
compileAnalysisFilename := {
|
||||
// Here, if the user wants cross-scala-versioning, we also append it
|
||||
|
|
@ -778,8 +780,11 @@ object Defaults extends BuildCommon {
|
|||
@deprecated("Use inTask(compile)(compileInputsSettings)", "0.13.0")
|
||||
def compileTaskSettings: Seq[Setting[_]] = inTask(compile)(compileInputsSettings)
|
||||
|
||||
def compileTask: Initialize[Task[inc.Analysis]] = Def.task { compileTaskImpl(streams.value, (compileInputs in compile).value, (compilerReporter in compile).value) }
|
||||
private[this] def compileTaskImpl(s: TaskStreams, ci: Compiler.Inputs, reporter: Option[xsbti.Reporter]): inc.Analysis =
|
||||
def compileTask: Initialize[Task[inc.Analysis]] = Def.task { saveAnalysis.value }
|
||||
def compileIncrementalTask = Def.task {
|
||||
compileIncrementalTaskImpl(streams.value, (compileInputs in compile).value, (compilerReporter in compile).value)
|
||||
}
|
||||
private[this] def compileIncrementalTaskImpl(s: TaskStreams, ci: Compiler.Inputs, reporter: Option[xsbti.Reporter]): Compiler.AnalysisResult =
|
||||
{
|
||||
lazy val x = s.text(ExportStream)
|
||||
def onArgs(cs: Compiler.Compilers) = cs.copy(scalac = cs.scalac.onArgs(exported(x, "scalac")), javac = cs.javac.onArgs(exported(x, "javac")))
|
||||
|
|
@ -803,9 +808,29 @@ object Defaults extends BuildCommon {
|
|||
def compileInputsSettings: Seq[Setting[_]] =
|
||||
Seq(compileInputs := {
|
||||
val cp = classDirectory.value +: data(dependencyClasspath.value)
|
||||
Compiler.inputs(cp, sources.value, classDirectory.value, scalacOptions.value, javacOptions.value, maxErrors.value, sourcePositionMappers.value, compileOrder.value)(compilers.value, compileIncSetup.value, streams.value.log)
|
||||
Compiler.inputs(cp, sources.value, classDirectory.value, scalacOptions.value, javacOptions.value,
|
||||
maxErrors.value, sourcePositionMappers.value, compileOrder.value, readAnalysis.value)(compilers.value, compileIncSetup.value, streams.value.log)
|
||||
},
|
||||
compilerReporter := None)
|
||||
def compileAnalysisSettings: Seq[Setting[_]] = Seq(
|
||||
readAnalysis := {
|
||||
val setup: Compiler.IncSetup = compileIncSetup.value
|
||||
val store = AggressiveCompile.staticCachedStore(setup.cacheFile)
|
||||
store.get() match {
|
||||
case Some((an, setup)) => Compiler.PreviousAnalysis(an, Some(setup))
|
||||
case None => Compiler.PreviousAnalysis(Analysis.empty(nameHashing = setup.incOptions.nameHashing), None)
|
||||
}
|
||||
},
|
||||
saveAnalysis := {
|
||||
val setup: Compiler.IncSetup = compileIncSetup.value
|
||||
val analysisResult: Compiler.AnalysisResult = compileIncremental.value
|
||||
if (analysisResult.modified) {
|
||||
val store = AggressiveCompile.staticCachedStore(setup.cacheFile)
|
||||
store.set(analysisResult.analysis, analysisResult.setup)
|
||||
}
|
||||
analysisResult.analysis
|
||||
}
|
||||
)
|
||||
|
||||
def printWarningsTask: Initialize[Task[Unit]] =
|
||||
(streams, compile, maxErrors, sourcePositionMappers) map { (s, analysis, max, spms) =>
|
||||
|
|
|
|||
|
|
@ -141,6 +141,9 @@ object Keys {
|
|||
val consoleQuick = TaskKey[Unit]("console-quick", "Starts the Scala interpreter with the project dependencies on the classpath.", ATask, console)
|
||||
val consoleProject = TaskKey[Unit]("console-project", "Starts the Scala interpreter with the sbt and the build definition on the classpath and useful imports.", AMinusTask)
|
||||
val compile = TaskKey[Analysis]("compile", "Compiles sources.", APlusTask)
|
||||
val compileIncremental = TaskKey[Compiler.AnalysisResult]("compileIncremental", "Actually runs the incremental compliation", DTask)
|
||||
val readAnalysis = TaskKey[Compiler.PreviousAnalysis]("readAnalysis", "Read the incremental compiler analysis from disk", DTask)
|
||||
val saveAnalysis = TaskKey[Analysis]("saveAnalysis", "Save the incremental compiler analysis to disk", DTask)
|
||||
val compilers = TaskKey[Compiler.Compilers]("compilers", "Defines the Scala and Java compilers to use for compilation.", DTask)
|
||||
val compileAnalysisFilename = TaskKey[String]("compileAnalysisFilename", "Defines the filename used to store the incremental compiler analysis file (inside the streams cacheDirectory).", DTask)
|
||||
val compileIncSetup = TaskKey[Compiler.IncSetup]("inc-compile-setup", "Configures aspects of incremental compilation.", DTask)
|
||||
|
|
|
|||
Loading…
Reference in New Issue