summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/src/main/scala/mill/Main.scala2
-rw-r--r--core/src/main/scala/mill/define/Cacher.scala11
-rw-r--r--core/src/main/scala/mill/define/Task.scala34
-rw-r--r--core/src/main/scala/mill/eval/Evaluator.scala3
-rw-r--r--core/src/test/scala/mill/JavaCompileJarTests.scala6
-rw-r--r--scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala152
6 files changed, 138 insertions, 70 deletions
diff --git a/core/src/main/scala/mill/Main.scala b/core/src/main/scala/mill/Main.scala
index f4042ae8..c4df0ee5 100644
--- a/core/src/main/scala/mill/Main.scala
+++ b/core/src/main/scala/mill/Main.scala
@@ -12,6 +12,7 @@ import ammonite.main.Scripts.pathScoptRead
import ammonite.repl.Repl
object Main {
+
def apply[T: Discovered](args: Seq[String], obj: T, watch: Path => Unit) = {
val Seq(selectorString, rest @_*) = args
@@ -131,6 +132,7 @@ class Main(config: Main.Config){
case Res.Failure(msg) =>
printError(msg)
false
+
case Res.Exception(ex, s) =>
printError(
Repl.showException(ex, fansi.Color.Red, fansi.Attr.Reset, fansi.Color.Green)
diff --git a/core/src/main/scala/mill/define/Cacher.scala b/core/src/main/scala/mill/define/Cacher.scala
index 224704ce..09200203 100644
--- a/core/src/main/scala/mill/define/Cacher.scala
+++ b/core/src/main/scala/mill/define/Cacher.scala
@@ -4,12 +4,12 @@ import scala.collection.mutable
import scala.reflect.macros.blackbox.Context
-trait Cacher[C[_], V[_]]{
- private[this] val cacherLazyMap = mutable.Map.empty[sourcecode.Enclosing, V[_]]
- def wrapCached[T](in: C[T], enclosing: String): V[T]
+trait Cacher[C[_]]{
+ private[this] val cacherLazyMap = mutable.Map.empty[sourcecode.Enclosing, C[_]]
+ def wrapCached[T](in: C[T], enclosing: String): C[T]
protected[this] def cachedTarget[T](t: => C[T])
- (implicit c: sourcecode.Enclosing): V[T] = synchronized{
- cacherLazyMap.getOrElseUpdate(c, wrapCached(t, c.value)).asInstanceOf[V[T]]
+ (implicit c: sourcecode.Enclosing): C[T] = synchronized{
+ cacherLazyMap.getOrElseUpdate(c, wrapCached(t, c.value)).asInstanceOf[C[T]]
}
}
object Cacher{
@@ -17,6 +17,7 @@ object Cacher{
c.Expr[M[T]](wrapCached(c)(t.tree))
}
def wrapCached(c: Context)(t: c.Tree) = {
+
import c.universe._
val owner = c.internal.enclosingOwner
val ownerIsCacherClass =
diff --git a/core/src/main/scala/mill/define/Task.scala b/core/src/main/scala/mill/define/Task.scala
index 0e2591c6..70f93d35 100644
--- a/core/src/main/scala/mill/define/Task.scala
+++ b/core/src/main/scala/mill/define/Task.scala
@@ -24,6 +24,8 @@ abstract class Task[+T] extends Task.Ops[T] with Applyable[T]{
* anyway?
*/
def sideHash: Int = 0
+
+ def flushDest: Boolean = true
}
trait Target[+T] extends Task[T]
@@ -31,7 +33,7 @@ object Target extends Applicative.Applyer[Task, Task, Args]{
implicit def apply[T](t: T): Target[T] = macro targetImpl[T]
- def apply[T](t: Task[T]): Target[T] = macro Cacher.impl0[Task, T]
+ def apply[T](t: Task[T]): Target[T] = macro targetTaskImpl[T]
def command[T](t: T): Command[T] = macro commandImpl[T]
@@ -42,6 +44,16 @@ object Target extends Applicative.Applyer[Task, Task, Args]{
def task[T](t: T): Task[T] = macro Applicative.impl[Task, T, Args]
def task[T](t: Task[T]): Task[T] = t
+ def persistent[T](t: T): Target[T] = macro persistentImpl[T]
+ def persistentImpl[T: c.WeakTypeTag](c: Context)(t: c.Expr[T]): c.Expr[Persistent[T]] = {
+ import c.universe._
+
+ c.Expr[Persistent[T]](
+ mill.define.Cacher.wrapCached(c)(
+ q"new ${weakTypeOf[Persistent[T]]}(${Applicative.impl[Task, T, Args](c)(t).tree})"
+ )
+ )
+ }
def commandImpl[T: c.WeakTypeTag](c: Context)(t: c.Expr[T]): c.Expr[Command[T]] = {
import c.universe._
@@ -50,10 +62,19 @@ object Target extends Applicative.Applyer[Task, Task, Args]{
)
}
+ def targetTaskImpl[T: c.WeakTypeTag](c: Context)(t: c.Expr[Task[T]]): c.Expr[Target[T]] = {
+ import c.universe._
+ c.Expr[Target[T]](
+ mill.define.Cacher.wrapCached(c)(
+ q"new ${weakTypeOf[TargetImpl[T]]}($t, _root_.sourcecode.Enclosing())"
+ )
+ )
+ }
def targetImpl[T: c.WeakTypeTag](c: Context)(t: c.Expr[T]): c.Expr[Target[T]] = {
+ import c.universe._
c.Expr[Target[T]](
mill.define.Cacher.wrapCached(c)(
- Applicative.impl[Task, T, Args](c)(t).tree
+ q"new ${weakTypeOf[TargetImpl[T]]}(${Applicative.impl[Task, T, Args](c)(t).tree}, _root_.sourcecode.Enclosing())"
)
)
}
@@ -93,6 +114,11 @@ class Command[+T](t: Task[T]) extends Task[T] {
val inputs = Seq(t)
def evaluate(args: Args) = args[T](0)
}
+class Persistent[+T](t: Task[T]) extends Target[T] {
+ val inputs = Seq(t)
+ def evaluate(args: Args) = args[T](0)
+ override def flushDest = false
+}
object Source{
implicit def apply(p: ammonite.ops.Path) = new Source(p)
}
@@ -107,8 +133,8 @@ object Task {
- trait Module extends mill.define.Cacher[Task, Target]{
- def wrapCached[T](t: Task[T], enclosing: String): Target[T] = new TargetImpl(t, enclosing)
+ trait Module extends mill.define.Cacher[Target]{
+ def wrapCached[T](t: Target[T], enclosing: String): Target[T] = t
}
class Task0[T](t: T) extends Task[T]{
lazy val t0 = t
diff --git a/core/src/main/scala/mill/eval/Evaluator.scala b/core/src/main/scala/mill/eval/Evaluator.scala
index 22861847..ef81515c 100644
--- a/core/src/main/scala/mill/eval/Evaluator.scala
+++ b/core/src/main/scala/mill/eval/Evaluator.scala
@@ -77,6 +77,7 @@ class Evaluator(workspacePath: Path,
if (labeled.nonEmpty){
println(fansi.Color.Blue("Running " + labeled.map(_.segments.mkString(".")).mkString(", ")))
}
+ if (terminal.flushDest) targetDestPath.foreach(rm)
val (newResults, newEvaluated, terminalResult) = evaluateGroup(group, results, targetDestPath)
metadataPath.foreach(
@@ -95,7 +96,7 @@ class Evaluator(workspacePath: Path,
results: collection.Map[Task[_], Any],
targetDestPath: Option[Path]) = {
- targetDestPath.foreach(rm)
+
var terminalResult: upickle.Js.Value = null
val newEvaluated = mutable.Buffer.empty[Task[_]]
val newResults = mutable.LinkedHashMap.empty[Task[_], Any]
diff --git a/core/src/test/scala/mill/JavaCompileJarTests.scala b/core/src/test/scala/mill/JavaCompileJarTests.scala
index 3e470b9d..8050ef6a 100644
--- a/core/src/test/scala/mill/JavaCompileJarTests.scala
+++ b/core/src/test/scala/mill/JavaCompileJarTests.scala
@@ -16,11 +16,8 @@ object JavaCompileJarTests extends TestSuite{
import ammonite.ops._
%("javac", sources.map(_.path.toString()), "-d", dest)(wd = dest)
PathRef(dest)
-//
}
-
-
val tests = Tests{
'javac {
val workspacePath = pwd / 'target / 'workspace / 'javac
@@ -48,10 +45,10 @@ object JavaCompileJarTests extends TestSuite{
%%('java, "-cp", classFiles().path, mainClsName)
}
}
+
import Build._
val mapping = Discovered.mapping(Build)
-
def eval[T](t: Task[T]): (T, Int) = {
val evaluator = new Evaluator(workspacePath, mapping)
val evaluated = evaluator.evaluate(OSet(t))
@@ -163,7 +160,6 @@ object JavaCompileJarTests extends TestSuite{
runOutput3.out.string == "New Cls!\n",
evalCount3 == 1
)
-
}
}
}
diff --git a/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala b/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala
index 80929088..e1b3c130 100644
--- a/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala
+++ b/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala
@@ -2,88 +2,130 @@ package mill
package scalaplugin
import java.io.File
+import java.util.Optional
import ammonite.ops._
import coursier.{Cache, Fetch, MavenRepository, Repository, Resolution}
import mill.define.Task
import mill.define.Task.Module
-import mill.discover.{Discovered, Mirror}
import mill.eval.{Evaluator, PathRef}
-import mill.modules.Jvm.{createJar, createAssembly}
+import mill.modules.Jvm.{createAssembly, createJar}
import mill.util.OSet
-import sbt.internal.inc.{FreshCompilerCache, ScalaInstance, ZincUtil}
+import sbt.internal.inc._
import sbt.internal.util.{ConsoleOut, MainAppender}
-import sbt.util.LogExchange
-import xsbti.api.{ClassLike, DependencyContext}
-import xsbti.compile.DependencyChanges
+import sbt.util.{InterfaceUtil, LogExchange}
+import xsbti.compile.{CompilerCache => _, FileAnalysisStore => _, ScalaInstance => _, _}
+
object ScalaModule{
+ case class MockedLookup(am: File => Optional[CompileAnalysis]) extends PerClasspathEntryLookup {
+ override def analysis(classpathEntry: File): Optional[CompileAnalysis] =
+ am(classpathEntry)
+
+ override def definesClass(classpathEntry: File): DefinesClass =
+ Locate.definesClass(classpathEntry)
+ }
+
+ val compilerCache = new CompilerCache(10)
def compileScala(scalaVersion: String,
- sources: PathRef,
- compileClasspath: Seq[PathRef],
+ sources: Path,
+ compileClasspath: Seq[Path],
outputPath: Path): PathRef = {
val binaryScalaVersion = scalaVersion.split('.').dropRight(1).mkString(".")
def grepJar(s: String) = {
compileClasspath
- .find(_.path.toString.endsWith(s))
+ .find(_.toString.endsWith(s))
.getOrElse(throw new Exception("Cannot find " + s))
- .path
.toIO
}
+ val scalaInstance = new ScalaInstance(
+ version = scalaVersion,
+ loader = getClass.getClassLoader,
+ libraryJar = grepJar(s"scala-library-$scalaVersion.jar"),
+ compilerJar = grepJar(s"scala-compiler-$scalaVersion.jar"),
+ allJars = compileClasspath.toArray.map(_.toIO),
+ explicitActual = None
+ )
val scalac = ZincUtil.scalaCompiler(
- new ScalaInstance(
- version = scalaVersion,
- loader = getClass.getClassLoader,
- libraryJar = grepJar(s"scala-library-$scalaVersion.jar"),
- compilerJar = grepJar(s"scala-compiler-$scalaVersion.jar"),
- allJars = compileClasspath.toArray.map(_.path.toIO),
- explicitActual = None
- ),
+ scalaInstance,
grepJar(s"compiler-bridge_$binaryScalaVersion-1.0.3.jar")
)
mkdir(outputPath)
+ val ic = new sbt.internal.inc.IncrementalCompilerImpl()
+
+ val logger = {
+ val console = ConsoleOut.systemOut
+ val consoleAppender = MainAppender.defaultScreen(console)
+ val l = LogExchange.logger("Hello")
+ LogExchange.unbindLoggerAppenders("Hello")
+ LogExchange.bindLoggerAppenders("Hello", (consoleAppender -> sbt.util.Level.Warn) :: Nil)
+ l
+ }
+ val compiler = new IncrementalCompilerImpl
+
+
+ val cs = compiler.compilers(scalaInstance, ClasspathOptionsUtil.boot, None, scalac)
- scalac.apply(
- sources = ls.rec(sources.path).filter(_.isFile).map(_.toIO).toArray,
- changes = new DependencyChanges {
- def isEmpty = true
- def modifiedBinaries() = Array[File]()
- def modifiedClasses() = Array[String]()
- },
- classpath = compileClasspath.map(_.path.toIO).toArray,
- singleOutput = outputPath.toIO,
- options = Array(),
- callback = new xsbti.AnalysisCallback {
- def startSource(source: File) = ()
- def apiPhaseCompleted() = ()
- def enabled() = true
- def binaryDependency(onBinaryEntry: File, onBinaryClassName: String, fromClassName: String, fromSourceFile: File, context: DependencyContext) = ()
- def generatedNonLocalClass(source: File, classFile: File, binaryClassName: String, srcClassName: String) = ()
- def problem(what: String, pos: xsbti.Position, msg: String, severity: xsbti.Severity, reported: Boolean) = ()
- def dependencyPhaseCompleted() = ()
- def classDependency(onClassName: String, sourceClassName: String, context: DependencyContext) = ()
- def generatedLocalClass(source: File, classFile: File) = ()
- def api(sourceFile: File, classApi: ClassLike) = ()
-
- def mainClass(sourceFile: File, className: String) = ()
- def usedName(className: String, name: String, useScopes: java.util.EnumSet[xsbti.UseScope]) = ()
- },
- maximumErrors = 10,
- cache = new FreshCompilerCache(),
- log = {
- val console = ConsoleOut.systemOut
- val consoleAppender = MainAppender.defaultScreen(console)
- val l = LogExchange.logger("Hello")
- LogExchange.unbindLoggerAppenders("Hello")
- LogExchange.bindLoggerAppenders("Hello", (consoleAppender -> sbt.util.Level.Warn) :: Nil)
- l
+ val lookup = MockedLookup(Function.const(Optional.empty[CompileAnalysis]))
+ val reporter = new ManagedLoggedReporter(10, logger)
+ val extra = Array(InterfaceUtil.t2(("key", "value")))
+
+ var lastCompiledUnits: Set[String] = Set.empty
+ val progress = new CompileProgress {
+ override def advance(current: Int, total: Int): Boolean = true
+
+ override def startUnit(phase: String, unitPath: String): Unit = {
+ println(unitPath)
+ lastCompiledUnits += unitPath
}
+ }
+
+ println("Running Compile")
+ println(outputPath/'zinc)
+ println(exists(outputPath/'zinc))
+ val store = FileAnalysisStore.binary((outputPath/'zinc).toIO)
+ val newResult = ic.compile(
+ ic.inputs(
+ classpath = compileClasspath.map(_.toIO).toArray,
+ sources = ls.rec(sources).filter(_.isFile).map(_.toIO).toArray,
+ classesDirectory = (outputPath / 'classes).toIO,
+ scalacOptions = Array(),
+ javacOptions = Array(),
+ maxErrors = 10,
+ sourcePositionMappers = Array(),
+ order = CompileOrder.Mixed,
+ compilers = cs,
+ setup = ic.setup(
+ lookup,
+ skip = false,
+ (outputPath/'zinc_cache).toIO,
+ compilerCache,
+ IncOptions.of(),
+ reporter,
+ Some(progress),
+ extra
+ ),
+ pr = {
+ val prev = store.get()
+ println(prev)
+ PreviousResult.of(prev.map(_.getAnalysis), prev.map(_.getMiniSetup))
+ }
+ ),
+ logger = logger
)
- PathRef(outputPath)
+
+ store.set(
+ AnalysisContents.create(
+ newResult.analysis(),
+ newResult.setup()
+ )
+ )
+
+ PathRef(outputPath/'classes)
}
def resolveDependencies(repositories: Seq[Repository],
@@ -193,8 +235,8 @@ trait ScalaModule extends Module{
def sources = T.source{ basePath / 'src }
def resources = T.source{ basePath / 'resources }
- def compile = T{
- compileScala(scalaVersion(), sources(), compileDepClasspath(), T.ctx().dest)
+ def compile = T.persistent{
+ compileScala(scalaVersion(), sources().path, compileDepClasspath().map(_.path), T.ctx().dest)
}
def assembly = T{
val dest = T.ctx().dest