summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbuild.sc13
-rw-r--r--core/src/main/scala/mill/define/Applicative.scala6
-rw-r--r--core/src/main/scala/mill/define/Task.scala5
-rw-r--r--core/src/test/scala/mill/define/ApplicativeTests.scala3
-rw-r--r--scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala80
-rw-r--r--scalaplugin/src/test/scala/mill/scalaplugin/AcyclicTests.scala2
-rw-r--r--scalaplugin/src/test/scala/mill/scalaplugin/HelloWorldTests.scala4
7 files changed, 70 insertions, 43 deletions
diff --git a/build.sc b/build.sc
index 5d581364..f58c160e 100755
--- a/build.sc
+++ b/build.sc
@@ -82,16 +82,13 @@ object ScalaPlugin extends MillModule {
override def projectDeps = Seq(Core)
def basePath = pwd / 'scalaplugin
- override def compile = T.persistent[mill.eval.PathRef]{
- super.compile()
- }
override def testArgs = T{
val mapping = Map(
- "MILL_COMPILER_BRIDGE_2_10_6" -> bridges("2.10.6").compile().path,
- "MILL_COMPILER_BRIDGE_2_11_8" -> bridges("2.11.8").compile().path,
- "MILL_COMPILER_BRIDGE_2_11_11" -> bridges("2.11.11").compile().path,
- "MILL_COMPILER_BRIDGE_2_12_3" -> bridges("2.12.3").compile().path,
- "MILL_COMPILER_BRIDGE_2_12_4" -> bridges("2.12.4").compile().path,
+ "MILL_COMPILER_BRIDGE_2_10_6" -> bridges("2.10.6").compile().classes.path,
+ "MILL_COMPILER_BRIDGE_2_11_8" -> bridges("2.11.8").compile().classes.path,
+ "MILL_COMPILER_BRIDGE_2_11_11" -> bridges("2.11.11").compile().classes.path,
+ "MILL_COMPILER_BRIDGE_2_12_3" -> bridges("2.12.3").compile().classes.path,
+ "MILL_COMPILER_BRIDGE_2_12_4" -> bridges("2.12.4").compile().classes.path,
)
for((k, v) <- mapping.toSeq) yield s"-D$k=$v"
}
diff --git a/core/src/main/scala/mill/define/Applicative.scala b/core/src/main/scala/mill/define/Applicative.scala
index f8193742..38a98015 100644
--- a/core/src/main/scala/mill/define/Applicative.scala
+++ b/core/src/main/scala/mill/define/Applicative.scala
@@ -37,8 +37,8 @@ object Applicative {
(cb: (A, B, C, D, E, Ctx) => Z[R]) = mapCtx(zip(a, b, c, d, e)){case ((a, b, c, d, e), x) => cb(a, b, c, d, e, x)}
def zipMap[A, B, C, D, E, F, R](a: T[A], b: T[B], c: T[C], d: T[D], e: T[E], f: T[F])
(cb: (A, B, C, D, E, F, Ctx) => Z[R]) = mapCtx(zip(a, b, c, d, e, f)){case ((a, b, c, d, e, f), x) => cb(a, b, c, d, e, f, x)}
- def zipMap[A, B, C, D, E, F, G, R](a: T[A], b: T[B], c: T[C], d: T[D], e: T[E], f: T[F], g: T[G])
- (cb: (A, B, C, D, E, F, G, Ctx) => Z[R]) = mapCtx(zip(a, b, c, d, e, f, g)){case ((a, b, c, d, e, f, g), x) => cb(a, b, c, d, e, f, g, x)}
+ def zipMap[A, B, C, D, E, F, G, H, R](a: T[A], b: T[B], c: T[C], d: T[D], e: T[E], f: T[F], g: T[G], h: T[H])
+ (cb: (A, B, C, D, E, F, G, H, Ctx) => Z[R]) = mapCtx(zip(a, b, c, d, e, f, g, h)){case ((a, b, c, d, e, f, g, h), x) => cb(a, b, c, d, e, f, g, h, x)}
def zip(): T[Unit]
def zip[A](a: T[A]): T[Tuple1[A]]
def zip[A, B](a: T[A], b: T[B]): T[(A, B)]
@@ -46,7 +46,7 @@ object Applicative {
def zip[A, B, C, D](a: T[A], b: T[B], c: T[C], d: T[D]): T[(A, B, C, D)]
def zip[A, B, C, D, E](a: T[A], b: T[B], c: T[C], d: T[D], e: T[E]): T[(A, B, C, D, E)]
def zip[A, B, C, D, E, F](a: T[A], b: T[B], c: T[C], d: T[D], e: T[E], f: T[F]): T[(A, B, C, D, E, F)]
- def zip[A, B, C, D, E, F, G](a: T[A], b: T[B], c: T[C], d: T[D], e: T[E], f: T[F], g: T[G]): T[(A, B, C, D, E, F, G)]
+ def zip[A, B, C, D, E, F, G, H](a: T[A], b: T[B], c: T[C], d: T[D], e: T[E], f: T[F], g: T[G], h: T[H]): T[(A, B, C, D, E, F, G, H)]
}
def impl[M[_], T: c.WeakTypeTag, Ctx: c.WeakTypeTag](c: Context)
diff --git a/core/src/main/scala/mill/define/Task.scala b/core/src/main/scala/mill/define/Task.scala
index 451cc1d4..8b811bdc 100644
--- a/core/src/main/scala/mill/define/Task.scala
+++ b/core/src/main/scala/mill/define/Task.scala
@@ -112,6 +112,11 @@ object Target extends Applicative.Applyer[Task, Task, Result, Ctx]{
val inputs = Seq(a, b, c, d, e, f, g)
def evaluate(args: Ctx) = (args[A](0), args[B](1), args[C](2), args[D](3), args[E](4), args[F](5), args[G](6))
}
+
+ def zip[A, B, C, D, E, F, G, H](a: Task[A], b: Task[B], c: Task[C], d: Task[D], e: Task[E], f: Task[F], g: Task[G], h: Task[H]) = new Task[(A, B, C, D, E, F, G, H)]{
+ val inputs = Seq(a, b, c, d, e, f, g, h)
+ def evaluate(args: Ctx) = (args[A](0), args[B](1), args[C](2), args[D](3), args[E](4), args[F](5), args[G](6), args[H](7))
+ }
}
class TargetImpl[+T](t: Task[T], enclosing: String) extends Target[T] {
val inputs = Seq(t)
diff --git a/core/src/test/scala/mill/define/ApplicativeTests.scala b/core/src/test/scala/mill/define/ApplicativeTests.scala
index 7e325184..14b566b3 100644
--- a/core/src/test/scala/mill/define/ApplicativeTests.scala
+++ b/core/src/test/scala/mill/define/ApplicativeTests.scala
@@ -38,6 +38,9 @@ object ApplicativeTests extends TestSuite {
def zip[A, B, C, D, E, F, G](a: O[A], b: O[B], c: O[C], d: O[D], e: O[E], f: O[F], g: O[G]) = {
for(a <- a; b <- b; c <- c; d <- d; e <- e; f <- f; g <- g) yield (a, b, c, d, e, f, g)
}
+ def zip[A, B, C, D, E, F, G, H](a: O[A], b: O[B], c: O[C], d: O[D], e: O[E], f: O[F], g: O[G], h: O[H]) = {
+ for(a <- a; b <- b; c <- c; d <- d; e <- e; f <- f; g <- g; h <- h) yield (a, b, c, d, e, f, g, h)
+ }
}
class Counter{
var value = 0
diff --git a/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala b/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala
index 0686f131..4de2f416 100644
--- a/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala
+++ b/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala
@@ -1,10 +1,9 @@
package mill
package scalaplugin
-import java.io.{File, PrintStream, PrintWriter, Writer}
+import java.io.File
import java.net.URLClassLoader
import java.util.Optional
-import java.util.concurrent.Callable
import ammonite.ops._
import coursier.{Cache, Fetch, MavenRepository, Repository, Resolution}
@@ -18,11 +17,13 @@ import sbt.internal.inc._
import sbt.internal.util.{ConsoleOut, MainAppender}
import sbt.util.{InterfaceUtil, LogExchange}
import xsbti.compile.{CompilerCache => _, FileAnalysisStore => _, ScalaInstance => _, _}
-import mill.util.JsonFormatters._
-import sbt.librarymanagement.DependencyResolution
-import xsbti.GlobalLock
+object CompilationResult {
+ implicit val jsonFormatter: upickle.default.ReadWriter[CompilationResult] = upickle.default.macroRW
+}
+// analysisFile is represented by Path, so we won't break caches after file changes
+case class CompilationResult(analysisFile: Path, classes: PathRef)
object ScalaModule{
case class MockedLookup(am: File => Optional[CompileAnalysis]) extends PerClasspathEntryLookup {
@@ -41,8 +42,9 @@ object ScalaModule{
compilerClasspath: Seq[Path],
compilerBridge: Seq[Path],
scalacOptions: Seq[String],
- javacOptions: Seq[String])
- (implicit ctx: Ctx): PathRef = {
+ javacOptions: Seq[String],
+ upstreamCompileOutput: Seq[CompilationResult])
+ (implicit ctx: Ctx): CompilationResult = {
val compileClasspathFiles = compileClasspath.map(_.toIO).toArray
def grepJar(classPath: Seq[Path], s: String) = {
@@ -89,17 +91,32 @@ object ScalaModule{
l
}
- val lookup = MockedLookup(Function.const(Optional.empty[CompileAnalysis]))
+ def analysisMap(f: File): Optional[CompileAnalysis] = {
+ if (f.isFile) {
+ Optional.empty[CompileAnalysis]
+ } else {
+ upstreamCompileOutput.collectFirst {
+ case CompilationResult(zincPath, classFiles) if classFiles.path.toNIO == f.toPath =>
+ FileAnalysisStore.binary(zincPath.toIO).get().map[CompileAnalysis](_.getAnalysis)
+ }.getOrElse(Optional.empty[CompileAnalysis])
+ }
+ }
+
+ val lookup = MockedLookup(analysisMap)
+
+ val zincFile = ctx.dest / 'zinc
+ val classesDir = ctx.dest / 'classes
- val zincFile = (ctx.dest/'zinc).toIO
- val store = FileAnalysisStore.binary(zincFile)
- val classesDir = (ctx.dest / 'classes).toIO
+ val zincIOFile = zincFile.toIO
+ val classesIODir = classesDir.toIO
+
+ val store = FileAnalysisStore.binary(zincIOFile)
val newResult = ic.compile(
ic.inputs(
- classpath = classesDir +: compileClasspathFiles,
+ classpath = classesIODir +: compileClasspathFiles,
sources = sources.flatMap(ls.rec).filter(x => x.isFile && x.ext == "scala").map(_.toIO).toArray,
- classesDirectory = classesDir,
+ classesDirectory = classesIODir,
scalacOptions = scalacOptions.toArray,
javacOptions = javacOptions.toArray,
maxErrors = 10,
@@ -114,7 +131,7 @@ object ScalaModule{
setup = ic.setup(
lookup,
skip = false,
- zincFile,
+ zincIOFile,
new FreshCompilerCache,
IncOptions.of(),
new ManagedLoggedReporter(10, logger),
@@ -136,7 +153,7 @@ object ScalaModule{
)
)
- PathRef(ctx.dest/'classes)
+ CompilationResult(zincFile, PathRef(classesDir))
}
def resolveDependencies(repositories: Seq[Repository],
@@ -194,8 +211,8 @@ trait TestScalaModule extends ScalaModule with TaskModule {
jvmOptions = forkArgs(),
options = Seq(
testFramework(),
- (runDepClasspath().map(_.path) :+ compile().path).mkString(" "),
- Seq(compile().path).mkString(" "),
+ (runDepClasspath().map(_.path) :+ compile().classes.path).mkString(" "),
+ Seq(compile().classes.path).mkString(" "),
args.mkString(" "),
outputPath.toString
),
@@ -209,8 +226,8 @@ trait TestScalaModule extends ScalaModule with TaskModule {
def test(args: String*) = T.command{
TestRunner(
testFramework(),
- runDepClasspath().map(_.path) :+ compile().path,
- Seq(compile().path),
+ runDepClasspath().map(_.path) :+ compile().classes.path,
+ Seq(compile().classes.path),
args
) match{
case Some(errMsg) => Result.Failure(errMsg)
@@ -248,7 +265,7 @@ trait ScalaModule extends Module with TaskModule{ outer =>
def upstreamRunClasspath = T{
Task.traverse(
for (p <- projectDeps)
- yield T.task(p.runDepClasspath() ++ Seq(p.compile()))
+ yield T.task(p.runDepClasspath() ++ Seq(p.compile().classes))
)
}
@@ -258,7 +275,8 @@ trait ScalaModule extends Module with TaskModule{ outer =>
def upstreamCompileDepSources = T{
Task.traverse(projectDeps.map(_.externalCompileDepSources))
}
- def upstreamCompileOutputClasspath = T{
+
+ def upstreamCompileOutput = T{
Task.traverse(projectDeps.map(_.compile))
}
@@ -288,7 +306,7 @@ trait ScalaModule extends Module with TaskModule{ outer =>
* might be less than the runtime classpath
*/
def compileDepClasspath: T[Seq[PathRef]] = T{
- upstreamCompileOutputClasspath() ++
+ upstreamCompileOutput().map(_.classes) ++
depClasspath() ++
externalCompileDepClasspath()
}
@@ -327,7 +345,7 @@ trait ScalaModule extends Module with TaskModule{ outer =>
def sources = T.source{ basePath / 'src }
def resources = T.source{ basePath / 'resources }
def allSources = T{ Seq(sources()) }
- def compile = T.persistent{
+ def compile: T[CompilationResult] = T.persistent{
compileScala(
scalaVersion(),
allSources().map(_.path),
@@ -335,35 +353,37 @@ trait ScalaModule extends Module with TaskModule{ outer =>
scalaCompilerClasspath().map(_.path),
compilerBridgeClasspath().map(_.path),
scalacOptions(),
- javacOptions()
+ javacOptions(),
+ upstreamCompileOutput()
)
}
def assembly = T{
createAssembly(
(runDepClasspath().filter(_.path.ext != "pom") ++
- Seq(resources(), compile())).map(_.path).filter(exists),
+ Seq(resources(), compile().classes)).map(_.path).filter(exists),
prependShellScript = prependShellScript()
)
}
- def classpath = T{ Seq(resources(), compile()) }
+ def classpath = T{ Seq(resources(), compile().classes) }
+
def jar = T{
- createJar(Seq(resources(), compile()).map(_.path).filter(exists), mainClass())
+ createJar(Seq(resources(), compile().classes).map(_.path).filter(exists), mainClass())
}
def run() = T.command{
val main = mainClass().getOrElse(throw new RuntimeException("No mainClass provided!"))
- subprocess(main, runDepClasspath().map(_.path) :+ compile().path)
+ subprocess(main, runDepClasspath().map(_.path) :+ compile().classes.path)
}
def runMain(mainClass: String) = T.command{
- subprocess(mainClass, runDepClasspath().map(_.path) :+ compile().path)
+ subprocess(mainClass, runDepClasspath().map(_.path) :+ compile().classes.path)
}
def console() = T.command{
subprocess(
mainClass = "scala.tools.nsc.MainGenericRunner",
- classPath = externalCompileDepClasspath().map(_.path) :+ compile().path,
+ classPath = externalCompileDepClasspath().map(_.path) :+ compile().classes.path,
options = Seq("-usejavacp")
)
}
diff --git a/scalaplugin/src/test/scala/mill/scalaplugin/AcyclicTests.scala b/scalaplugin/src/test/scala/mill/scalaplugin/AcyclicTests.scala
index 856e9508..7c10cb6b 100644
--- a/scalaplugin/src/test/scala/mill/scalaplugin/AcyclicTests.scala
+++ b/scalaplugin/src/test/scala/mill/scalaplugin/AcyclicTests.scala
@@ -63,7 +63,7 @@ object AcyclicTests extends TestSuite{
// We can compile
val Right((pathRef, evalCount)) = eval(AcyclicBuild.acyclic(scalaVersion).compile)
- val outputPath = pathRef.path
+ val outputPath = pathRef.classes.path
val outputFiles = ls.rec(outputPath)
assert(
evalCount > 0,
diff --git a/scalaplugin/src/test/scala/mill/scalaplugin/HelloWorldTests.scala b/scalaplugin/src/test/scala/mill/scalaplugin/HelloWorldTests.scala
index 916dd7ca..7f672f12 100644
--- a/scalaplugin/src/test/scala/mill/scalaplugin/HelloWorldTests.scala
+++ b/scalaplugin/src/test/scala/mill/scalaplugin/HelloWorldTests.scala
@@ -95,11 +95,13 @@ object HelloWorldTests extends TestSuite {
val Right((result, evalCount)) =
eval(HelloWorld.compile, helloWorldMapping)
- val outPath = result.path
+ val outPath = result.classes.path
+ val analysisFile = result.analysisFile
val outputFiles = ls.rec(outPath)
val expectedClassfiles = compileClassfiles(outputPath / 'compile / 'classes)
assert(
outPath == outputPath / 'compile / 'classes,
+ exists(analysisFile),
outputFiles.nonEmpty,
outputFiles.forall(expectedClassfiles.contains),
evalCount > 0