aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--stage1/Stage1.scala24
-rw-r--r--stage1/Stage1Lib.scala39
-rw-r--r--stage1/paths.scala1
-rw-r--r--stage1/resolver.scala16
-rw-r--r--stage2/BasicBuild.scala37
-rw-r--r--stage2/BuildDependency.scala2
-rw-r--r--stage2/GitDependency.scala2
-rw-r--r--stage2/Lib.scala26
8 files changed, 70 insertions, 77 deletions
diff --git a/stage1/Stage1.scala b/stage1/Stage1.scala
index 32da3ed..be933d2 100644
--- a/stage1/Stage1.scala
+++ b/stage1/Stage1.scala
@@ -68,17 +68,21 @@ object Stage1{
val classLoaderCache = new ClassLoaderCache(logger)
- val stage2SourcesChanged = sourceFiles.exists(newerThan(_, changeIndicator))
- logger.stage1("before conditionally running zinc to recompile CBT")
- if( stage2SourcesChanged ) {
- val scalaXml = JavaDependency("org.scala-lang.modules","scala-xml_"+constants.scalaMajorVersion,constants.scalaXmlVersion)
- logger.stage1("cbt.lib has changed. Recompiling.")
- zinc( true, sourceFiles, stage2Target, nailgunTarget +: stage1Target +: Dependencies(deps, scalaXml).classpath, classLoaderCache, Seq("-deprecation") )( zincVersion = "0.3.9", scalaVersion = constants.scalaVersion )
- }
+ val stage2SourcesChanged = lib.needsUpdate(sourceFiles, stage2StatusFile)
+ logger.stage1("Compiling stage2 if necessary")
+ val scalaXml = JavaDependency("org.scala-lang.modules","scala-xml_"+constants.scalaMajorVersion,constants.scalaXmlVersion)
+ compile(
+ stage2SourcesChanged,
+ sourceFiles, stage2Target, stage2StatusFile,
+ nailgunTarget +: stage1Target +: Dependencies(deps, scalaXml).classpath,
+ Seq("-deprecation"), classLoaderCache,
+ zincVersion = "0.3.9", scalaVersion = constants.scalaVersion
+ )
+
logger.stage1(s"[$now] calling CbtDependency.classLoader")
- val cl = classLoaderCache.transient.get(
- (stage2Target +: deps.classpath).string,
+ val cl = /*classLoaderCache.transient.get(
+ (stage2Target +: deps.classpath).string,*/
cbt.URLClassLoader(
ClassPath(Seq(stage2Target)),
classLoaderCache.persistent.get(
@@ -86,7 +90,7 @@ object Stage1{
cbt.URLClassLoader( deps.classpath, classLoader )
)
)
- )
+ //)
logger.stage1(s"[$now] Run Stage2")
val exitCode = (
diff --git a/stage1/Stage1Lib.scala b/stage1/Stage1Lib.scala
index 69b828b..e4fe15e 100644
--- a/stage1/Stage1Lib.scala
+++ b/stage1/Stage1Lib.scala
@@ -6,6 +6,7 @@ import java.io._
import java.lang.reflect.InvocationTargetException
import java.net._
import java.nio.file._
+import java.nio.file.attribute.FileTime
import javax.tools._
import java.security._
import java.util._
@@ -111,14 +112,22 @@ class Stage1Lib( val logger: Logger ) extends BaseLib{
}
}
- def zinc(
+ def needsUpdate( sourceFiles: Seq[File], statusFile: File ) = {
+ val lastCompile = statusFile.lastModified
+ sourceFiles.filter(_.lastModified > lastCompile).nonEmpty
+ }
+
+ def compile(
needsRecompile: Boolean,
files: Seq[File],
compileTarget: File,
+ statusFile: File,
classpath: ClassPath,
+ scalacOptions: Seq[String] = Seq(),
classLoaderCache: ClassLoaderCache,
- extraArgs: Seq[String] = Seq()
- )( zincVersion: String, scalaVersion: String ): Unit = {
+ zincVersion: String,
+ scalaVersion: String
+ ): File = {
val cp = classpath.string
if(classpath.files.isEmpty)
@@ -126,9 +135,6 @@ class Stage1Lib( val logger: Logger ) extends BaseLib{
if(files.isEmpty)
throw new Exception("Trying to compile no files. ClassPath: " ++ cp)
-
- // only run zinc if files changed, for performance reasons
- // FIXME: this is broken, need invalidate on changes in dependencies as well
if( needsRecompile ){
val zinc = JavaDependency("com.typesafe.zinc","zinc", zincVersion)
val zincDeps = zinc.transitiveDependencies
@@ -151,6 +157,8 @@ class Stage1Lib( val logger: Logger ) extends BaseLib{
val scalaReflect = JavaDependency("org.scala-lang","scala-reflect",scalaVersion).jar
val scalaCompiler = JavaDependency("org.scala-lang","scala-compiler",scalaVersion).jar
+ val start = System.currentTimeMillis
+
val code = redirectOutToErr{
lib.runMain(
"com.typesafe.zinc.Main",
@@ -162,22 +170,21 @@ class Stage1Lib( val logger: Logger ) extends BaseLib{
"-scala-extra", scalaReflect.toString,
"-cp", cp,
"-d", compileTarget.toString
- ) ++ extraArgs.map("-S"++_) ++ files.map(_.toString),
+ ) ++ scalacOptions.map("-S"++_) ++ files.map(_.toString),
zinc.classLoader(classLoaderCache)
)
}
- if(code != ExitCode.Success){
- // Ensure we trigger recompilation next time. This is currently required because we
- // don't record the time of the last successful build elsewhere. But hopefully that will
- // change soon.
- val now = System.currentTimeMillis()
- files.foreach(_.setLastModified(now))
-
- // Tell the caller that things went wrong.
- System.exit(code.integer)
+ if(code == ExitCode.Success){
+ // write version and when last compilation started so we can trigger
+ // recompile if cbt version changed or newer source files are seen
+ Files.write(statusFile.toPath, "".getBytes)//cbtVersion.getBytes)
+ Files.setLastModifiedTime(statusFile.toPath, FileTime.fromMillis(start) )
+ } else {
+ System.exit(code.integer) // FIXME: let's find a better solution for error handling. Maybe a monad after all.
}
}
+ compileTarget
}
def redirectOutToErr[T](code: => T): T = {
val oldOut = System.out
diff --git a/stage1/paths.scala b/stage1/paths.scala
index e8e3cc5..f27e538 100644
--- a/stage1/paths.scala
+++ b/stage1/paths.scala
@@ -11,6 +11,7 @@ object paths{
private val target = Option(System.getenv("TARGET")).get.stripSuffix("/")
val stage1Target: File = stage1 ++ ("/" ++ target)
val stage2Target: File = stage2 ++ ("/" ++ target)
+ val stage2StatusFile: File = stage2Target ++ ".last-success"
val nailgunTarget: File = nailgun ++ ("/" ++ target)
val sonatypeLogin: File = cbtHome ++ "/sonatype.login"
}
diff --git a/stage1/resolver.scala b/stage1/resolver.scala
index b8e6544..1dd4d6c 100644
--- a/stage1/resolver.scala
+++ b/stage1/resolver.scala
@@ -28,7 +28,7 @@ abstract class Dependency{
implicit def logger: Logger
protected def lib = new Stage1Lib(logger)
- def updated: Boolean
+ def needsUpdate: Boolean
//def cacheClassLoader: Boolean = false
private[cbt] def targetClasspath: ClassPath
def exportedClasspath: ClassPath
@@ -174,7 +174,7 @@ abstract class Dependency{
def dependencyTree: String = dependencyTreeRecursion()
private def dependencyTreeRecursion(indent: Int = 0): String = (
( " " * indent )
- ++ (if(updated) lib.red(show) else show)
+ ++ (if(needsUpdate) lib.red(show) else show)
++ dependencies.map(
"\n" ++ _.dependencyTreeRecursion(indent + 1)
).mkString
@@ -187,7 +187,7 @@ class ScalaLibraryDependency (version: String)(implicit logger: Logger) extends
class ScalaReflectDependency (version: String)(implicit logger: Logger) extends JavaDependency("org.scala-lang","scala-reflect",version)
case class ScalaDependencies(version: String)(implicit val logger: Logger) extends Dependency{ sd =>
- final val updated = false
+ override final val needsUpdate = false
override def canBeCached = true
def targetClasspath = ClassPath(Seq())
def exportedClasspath = ClassPath(Seq())
@@ -200,23 +200,23 @@ case class ScalaDependencies(version: String)(implicit val logger: Logger) exten
}
case class BinaryDependency( path: File, dependencies: Seq[Dependency] )(implicit val logger: Logger) extends Dependency{
- def updated = false
def exportedClasspath = ClassPath(Seq(path))
def exportedJars = Seq[File](path)
+ override def needsUpdate = false
def targetClasspath = exportedClasspath
}
/** Allows to easily assemble a bunch of dependencies */
case class Dependencies( _dependencies: Dependency* )(implicit val logger: Logger) extends Dependency{
override def dependencies = _dependencies.to
- def updated = dependencies.exists(_.updated)
+ def needsUpdate = dependencies.exists(_.needsUpdate)
def exportedClasspath = ClassPath(Seq())
def exportedJars = Seq()
def targetClasspath = ClassPath(Seq())
}
case class Stage1Dependency()(implicit val logger: Logger) extends Dependency{
- def updated = false // FIXME: think this through, might allow simplifications and/or optimizations
+ def needsUpdate = false // FIXME: think this through, might allow simplifications and/or optimizations
override def canBeCached = false
/*
private object classLoaderRecursionCache extends Cache[ClassLoader]
@@ -245,7 +245,7 @@ case class CbtDependency()(implicit val logger: Logger) extends Dependency{
"org.scala-lang.modules","scala-xml","1.0.5", scalaVersion = constants.scalaMajorVersion
)
)
- def updated = false // FIXME: think this through, might allow simplifications and/or optimizations
+ def needsUpdate = false // FIXME: think this through, might allow simplifications and/or optimizations
def targetClasspath = exportedClasspath
}
@@ -260,7 +260,7 @@ case class JavaDependency(
groupId: String, artifactId: String, version: String, classifier: Classifier = Classifier.none
)(implicit val logger: Logger) extends ArtifactInfo{
- def updated = false
+ override def needsUpdate = false
override def canBeCached = true
private val groupPath = groupId.split("\\.").mkString("/")
diff --git a/stage2/BasicBuild.scala b/stage2/BasicBuild.scala
index 28360aa..27de538 100644
--- a/stage2/BasicBuild.scala
+++ b/stage2/BasicBuild.scala
@@ -48,6 +48,12 @@ class Build(val context: Context) extends Dependency with TriggerLoop{
def apiTarget: File = scalaTarget ++ "/api"
/** directory where the class files should be put (in package directories) */
def compileTarget: File = scalaTarget ++ "/classes"
+ /**
+ File which cbt uses to determine if it needs to trigger an incremental re-compile.
+ Last modified date is the time when the last successful compilation started.
+ Contents is the cbt version git hash.
+ */
+ def compileStatusFile: File = compileTarget ++ ".last-success"
/** Source directories and files. Defaults to .scala and .java files in src/ and top-level. */
def sources: Seq[File] = Seq(defaultSourceDirectory) ++ projectDirectory.listFiles.toVector.filter(sourceFileFilter)
@@ -118,33 +124,20 @@ class Build(val context: Context) extends Dependency with TriggerLoop{
/** scalac options used for zinc and scaladoc */
def scalacOptions: Seq[String] = Seq( "-feature", "-deprecation", "-unchecked" )
- val updated: Boolean = {
- val existingClassFiles = lib.listFilesRecursive(compileTarget)
- val sourcesChanged = existingClassFiles.nonEmpty && {
- val oldestClassFile = existingClassFiles.sortBy(_.lastModified).head
- val oldestClassFileAge = oldestClassFile.lastModified
- val changedSourceFiles = sourceFiles.filter(_.lastModified > oldestClassFileAge)
- if(changedSourceFiles.nonEmpty){
- /*
- println(changedSourceFiles)
- println(changedSourceFiles.map(_.lastModified))
- println(changedSourceFiles.map(_.lastModified > oldestClassFileAge))
- println(oldestClassFile)
- println(oldestClassFileAge)
- println("-"*80)
- */
- }
- changedSourceFiles.nonEmpty
- }
- sourcesChanged || transitiveDependencies.map(_.updated).fold(false)(_ || _)
+ private object needsUpdateCache extends Cache[Boolean]
+ def needsUpdate: Boolean = {
+ needsUpdateCache(
+ lib.needsUpdate( sourceFiles, compileStatusFile )
+ || transitiveDependencies.exists(_.needsUpdate)
+ )
}
private object compileCache extends Cache[File]
def compile: File = compileCache{
lib.compile(
- updated,
- sourceFiles, compileTarget, dependencyClasspath, scalacOptions,
- zincVersion = zincVersion, scalaVersion = scalaVersion, context.classLoaderCache
+ needsUpdate,
+ sourceFiles, compileTarget, compileStatusFile, dependencyClasspath, scalacOptions,
+ context.classLoaderCache, zincVersion = zincVersion, scalaVersion = scalaVersion
)
}
diff --git a/stage2/BuildDependency.scala b/stage2/BuildDependency.scala
index 84a0100..e3a01c7 100644
--- a/stage2/BuildDependency.scala
+++ b/stage2/BuildDependency.scala
@@ -25,7 +25,7 @@ case class BuildDependency(context: Context) extends TriggerLoop{
def exportedJars = Seq()
def dependencies = Seq(build)
def triggerLoopFiles = root.triggerLoopFiles
- final val updated = build.updated
+ override final val needsUpdate = build.needsUpdate
def targetClasspath = ClassPath(Seq())
}
/*
diff --git a/stage2/GitDependency.scala b/stage2/GitDependency.scala
index 993825e..59de98a 100644
--- a/stage2/GitDependency.scala
+++ b/stage2/GitDependency.scala
@@ -45,5 +45,5 @@ case class GitDependency(
def exportedClasspath = ClassPath(Seq())
def exportedJars = Seq()
private[cbt] def targetClasspath = exportedClasspath
- def updated: Boolean = false
+ def needsUpdate: Boolean = false
}
diff --git a/stage2/Lib.scala b/stage2/Lib.scala
index d917e8b..fbbe870 100644
--- a/stage2/Lib.scala
+++ b/stage2/Lib.scala
@@ -53,18 +53,6 @@ final class Lib(logger: Logger) extends Stage1Lib(logger) with Scaffold{
}
}
- def compile(
- updated: Boolean,
- sourceFiles: Seq[File], compileTarget: File, dependenyClasspath: ClassPath,
- compileArgs: Seq[String], zincVersion: String, scalaVersion: String, classLoaderCache: ClassLoaderCache
- ): File = {
- if(sourceFiles.nonEmpty)
- lib.zinc(
- updated, sourceFiles, compileTarget, dependenyClasspath, classLoaderCache, compileArgs
- )( zincVersion = zincVersion, scalaVersion = scalaVersion )
- compileTarget
- }
-
def srcJar(sources: Seq[File], artifactId: String, version: String, jarTarget: File): File = {
val file = jarTarget ++ ("/"++artifactId++"-"++version++"-sources.jar")
lib.jarFile(file, sources)
@@ -96,14 +84,14 @@ final class Lib(logger: Logger) extends Stage1Lib(logger) with Scaffold{
"-d", apiTarget.toString
) ++ compileArgs ++ sourceFiles.map(_.toString)
logger.lib("creating docs for source files "+args.mkString(", "))
- redirectOutToErr{
- runMain(
- "scala.tools.nsc.ScalaDoc",
- args,
- ScalaDependencies(scalaVersion)(logger).classLoader(classLoaderCache)
- )
- }
+ redirectOutToErr{
+ runMain(
+ "scala.tools.nsc.ScalaDoc",
+ args,
+ ScalaDependencies(scalaVersion)(logger).classLoader(classLoaderCache)
+ )
}
+ }
val docJar = jarTarget ++ ("/"++artifactId++"-"++version++"-javadoc.jar")
lib.jarFile(docJar, Vector(apiTarget))
docJar