summaryrefslogtreecommitdiff
path: root/scalaplugin
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2017-12-05 07:47:18 -0800
committerLi Haoyi <haoyi.sg@gmail.com>2017-12-05 22:21:29 -0800
commit7cd79bd7579bfdef0e3e13672ea90df904f6ab12 (patch)
tree39527061df795c17011d9f1eb5b5e73d4467ad83 /scalaplugin
parentb1df0b98612957b98aacabd5dbe38c98e748c660 (diff)
parent395a856d91b318957963ab24011862653452a101 (diff)
downloadmill-7cd79bd7579bfdef0e3e13672ea90df904f6ab12.tar.gz
mill-7cd79bd7579bfdef0e3e13672ea90df904f6ab12.tar.bz2
mill-7cd79bd7579bfdef0e3e13672ea90df904f6ab12.zip
merge cross-bridge into master
Diffstat (limited to 'scalaplugin')
-rw-r--r--scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala4
-rw-r--r--scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala93
-rw-r--r--scalaplugin/src/main/scala/mill/scalaplugin/TestRunner.scala21
-rw-r--r--scalaplugin/src/test/scala/mill/scalaplugin/AcyclicTests.scala50
-rw-r--r--scalaplugin/src/test/scala/mill/scalaplugin/HelloWorldTests.scala2
-rw-r--r--scalaplugin/src/test/scala/mill/scalaplugin/TestEvaluator.scala7
6 files changed, 95 insertions, 82 deletions
diff --git a/scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala b/scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala
index 87a42d04..4ccb71cd 100644
--- a/scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala
+++ b/scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala
@@ -4,7 +4,7 @@ import ammonite.ops._
import mill.discover.Mirror.Segment
import mill.discover.{Discovered, Mirror}
import mill.eval.{Evaluator, PathRef}
-import mill.util.OSet
+import mill.util.{OSet, PrintLogger}
object GenIdea {
@@ -22,7 +22,7 @@ object GenIdea {
val discovered = implicitly[Discovered[T]]
val mapping = Discovered.mapping(obj)(discovered)
val workspacePath = pwd / 'out
- val evaluator = new Evaluator(workspacePath, mapping, _ => ())
+ val evaluator = new Evaluator(workspacePath, mapping, new PrintLogger(true))
val modules = Mirror
.traverse(obj, discovered.mirror){ (h, p) =>
diff --git a/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala b/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala
index c9cf4a49..001f5844 100644
--- a/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala
+++ b/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala
@@ -1,9 +1,10 @@
package mill
package scalaplugin
-import java.io.File
+import java.io.{File, PrintStream, PrintWriter, Writer}
import java.net.URLClassLoader
import java.util.Optional
+import java.util.concurrent.Callable
import ammonite.ops._
import coursier.{Cache, Fetch, MavenRepository, Repository, Resolution}
@@ -12,11 +13,14 @@ import mill.define.Task.{Module, TaskModule}
import mill.eval.{PathRef, Result}
import mill.modules.Jvm
import mill.modules.Jvm.{createAssembly, createJar, subprocess}
+import mill.util.Ctx
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
@@ -29,17 +33,17 @@ object ScalaModule{
Locate.definesClass(classpathEntry)
}
- val compilerCache = new CompilerCache(2)
+ var scalaInstanceCache = Option.empty[(Long, ScalaInstance)]
def compileScala(scalaVersion: String,
- sources: Path,
+ sources: Seq[Path],
compileClasspath: Seq[Path],
compilerClasspath: Seq[Path],
compilerBridge: Seq[Path],
scalacOptions: Seq[String],
- javacOptions: Seq[String],
- outputPath: Path): PathRef = {
+ javacOptions: Seq[String])
+ (implicit ctx: Ctx): PathRef = {
val compileClasspathFiles = compileClasspath.map(_.toIO).toArray
- val binaryScalaVersion = scalaVersion.split('.').dropRight(1).mkString(".")
+
def grepJar(classPath: Seq[Path], s: String) = {
classPath
.find(_.toString.endsWith(s))
@@ -47,37 +51,44 @@ object ScalaModule{
.toIO
}
- val outerClassLoader = getClass.getClassLoader
+
val compilerJars = compilerClasspath.toArray.map(_.toIO)
- val compilerBridgeJar = grepJar(compilerBridge, s"compiler-bridge_$binaryScalaVersion-1.0.5.jar")
- val zincClassLoader = new URLClassLoader(compilerJars.map(_.toURI.toURL), null){
- override def loadClass(name: String): Class[_] = {
- Option(findLoadedClass(name)) orElse
- (try Some(findClass(name)) catch {case e: ClassNotFoundException => None}) getOrElse {
- // Try to limit `outerClassLoader` to only stuff from the compiler-bridge jar
- if (name.startsWith("xsbt.")) outerClassLoader.loadClass(name)
- else super.loadClass(name)
- }
- }
- }
- val scalaInstance = new ScalaInstance(
- version = scalaVersion,
- loader = zincClassLoader,
- libraryJar = grepJar(compilerClasspath, s"scala-library-$scalaVersion.jar"),
- compilerJar = grepJar(compilerClasspath, s"scala-compiler-$scalaVersion.jar"),
- allJars = compilerJars,
- explicitActual = None
+ def binaryScalaVersion = scalaVersion.split('.').dropRight(1).mkString(".")
+ val compilerBridgeJar = new java.io.File(
+ s"bridge/${scalaVersion.replace('.', '_')}/target/scala-$binaryScalaVersion/mill-bridge_$scalaVersion-0.1-SNAPSHOT.jar"
+// s"out/bridges/$scalaVersion/compile/classes"
)
+ val classloaderSig = compilerClasspath.map(p => p.toString().hashCode + p.mtime.toMillis).sum
+ println("classloaderSig: " + classloaderSig)
+ val scalaInstance = scalaInstanceCache match{
+ case Some((k, v)) if k == classloaderSig => v
+ case _ =>
+ val scalaInstance = new ScalaInstance(
+ version = scalaVersion,
+ loader = new URLClassLoader(compilerJars.map(_.toURI.toURL), null),
+ libraryJar = grepJar(compilerClasspath, s"scala-library-$scalaVersion.jar"),
+ compilerJar = grepJar(compilerClasspath, s"scala-compiler-$scalaVersion.jar"),
+ allJars = compilerJars,
+ explicitActual = None
+ )
+ scalaInstanceCache = Some((classloaderSig, scalaInstance))
+ scalaInstance
+ }
+
+
+
val scalac = ZincUtil.scalaCompiler(scalaInstance, compilerBridgeJar)
- mkdir(outputPath)
+ mkdir(ctx.dest)
val ic = new sbt.internal.inc.IncrementalCompilerImpl()
val logger = {
- val console = ConsoleOut.systemOut
- val consoleAppender = MainAppender.defaultScreen(console)
+
+ val consoleAppender = MainAppender.defaultScreen(ConsoleOut.printStreamOut(
+ ctx.log.outputStream
+ ))
val l = LogExchange.logger("Hello")
LogExchange.unbindLoggerAppenders("Hello")
LogExchange.bindLoggerAppenders("Hello", (consoleAppender -> sbt.util.Level.Info) :: Nil)
@@ -97,13 +108,13 @@ object ScalaModule{
override def startUnit(phase: String, unitPath: String): Unit = ()
}
- val zincFile = (outputPath/'zinc).toIO
+ val zincFile = (ctx.dest/'zinc).toIO
val store = FileAnalysisStore.binary(zincFile)
- val classesDir = (outputPath / 'classes).toIO
+ val classesDir = (ctx.dest / 'classes).toIO
val newResult = ic.compile(
ic.inputs(
classpath = classesDir +: compileClasspathFiles,
- sources = ls.rec(sources).filter(_.isFile).map(_.toIO).toArray,
+ sources = sources.flatMap(ls.rec).filter(x => x.isFile && x.ext == "scala").map(_.toIO).toArray,
classesDirectory = classesDir,
scalacOptions = scalacOptions.toArray,
javacOptions = javacOptions.toArray,
@@ -115,7 +126,7 @@ object ScalaModule{
lookup,
skip = false,
zincFile,
- compilerCache,
+ new FreshCompilerCache,
IncOptions.of(),
reporter,
Some(ignoreProgress),
@@ -136,7 +147,7 @@ object ScalaModule{
)
)
- PathRef(outputPath/'classes)
+ PathRef(ctx.dest/'classes)
}
def resolveDependencies(repositories: Seq[Repository],
@@ -325,33 +336,29 @@ 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{
compileScala(
scalaVersion(),
- sources().path,
+ allSources().map(_.path),
compileDepClasspath().map(_.path),
scalaCompilerClasspath().map(_.path),
compilerBridgeClasspath().map(_.path),
scalacOptions(),
- javacOptions(),
- T.ctx().dest
+ javacOptions()
)
}
def assembly = T{
- val dest = T.ctx().dest
createAssembly(
- dest,
- (runDepClasspath().filter(_.path.ext != "pom") ++ Seq(resources(), compile())).map(_.path).filter(exists),
+ (runDepClasspath().filter(_.path.ext != "pom") ++
+ Seq(resources(), compile())).map(_.path).filter(exists),
prependShellScript = prependShellScript()
)
- PathRef(dest)
}
def classpath = T{ Seq(resources(), compile()) }
def jar = T{
- val dest = T.ctx().dest
- createJar(dest, Seq(resources(), compile()).map(_.path).filter(exists), mainClass())
- PathRef(dest)
+ createJar(Seq(resources(), compile()).map(_.path).filter(exists), mainClass())
}
def run() = T.command{
diff --git a/scalaplugin/src/main/scala/mill/scalaplugin/TestRunner.scala b/scalaplugin/src/main/scala/mill/scalaplugin/TestRunner.scala
index 03292b68..43e15974 100644
--- a/scalaplugin/src/main/scala/mill/scalaplugin/TestRunner.scala
+++ b/scalaplugin/src/main/scala/mill/scalaplugin/TestRunner.scala
@@ -6,6 +6,8 @@ import java.net.URLClassLoader
import java.util.zip.ZipInputStream
import ammonite.ops.{Path, ls, pwd}
+import mill.util.Ctx.LogCtx
+import mill.util.PrintLogger
import sbt.testing._
import scala.collection.mutable
@@ -43,14 +45,17 @@ object TestRunner {
entireClasspath = args(1).split(" ").map(Path(_)),
testClassfilePath = args(2).split(" ").map(Path(_)),
args = args(3) match{ case "" => Nil case x => x.split(" ").toList }
- )
+ )(new LogCtx {
+ def log = new PrintLogger(true)
+ })
val outputPath = args(4)
ammonite.ops.write(Path(outputPath), upickle.default.write(result))
}
def apply(frameworkName: String,
entireClasspath: Seq[Path],
testClassfilePath: Seq[Path],
- args: Seq[String]): Option[String] = {
+ args: Seq[String])
+ (implicit ctx: LogCtx): Option[String] = {
val outerClassLoader = getClass.getClassLoader
val cl = new URLClassLoader(
entireClasspath.map(_.toIO.toURI.toURL).toArray,
@@ -86,17 +91,17 @@ object TestRunner {
},
Array(
new Logger {
- def debug(msg: String) = println(msg)
+ def debug(msg: String) = ctx.log.info(msg)
- def error(msg: String) = println(msg)
+ def error(msg: String) = ctx.log.error(msg)
def ansiCodesSupported() = true
- def warn(msg: String) = println(msg)
+ def warn(msg: String) = ctx.log.info(msg)
- def trace(t: Throwable) = println(t)
+ def trace(t: Throwable) = t.printStackTrace(ctx.log.outputStream)
- def info(msg: String) = println(msg)
+ def info(msg: String) = ctx.log.info(msg)
})
)
}
@@ -107,7 +112,7 @@ object TestRunner {
val grouped = events.groupBy(x => x).mapValues(_.length).filter(_._2 != 0).toList.sorted
grouped.map{case (k, v) => k + ": " + v}.mkString(",")
}
- println(msg)
+ ctx.log.info(msg)
if (events.count(Set(Status.Error, Status.Failure)) == 0) None
else Some(msg)
}
diff --git a/scalaplugin/src/test/scala/mill/scalaplugin/AcyclicTests.scala b/scalaplugin/src/test/scala/mill/scalaplugin/AcyclicTests.scala
index 7ba8b267..856e9508 100644
--- a/scalaplugin/src/test/scala/mill/scalaplugin/AcyclicTests.scala
+++ b/scalaplugin/src/test/scala/mill/scalaplugin/AcyclicTests.scala
@@ -9,7 +9,7 @@ import utest._
import mill.util.JsonFormatters._
object AcyclicBuild{
val acyclic =
- for(crossVersion <- Cross("2.10.6", "2.11.8", "2.12.4"))
+ for(crossVersion <- Cross("2.10.6", "2.11.8", "2.12.3", "2.12.4"))
yield new ScalaModule{outer =>
def basePath = AcyclicTests.workspacePath
def organization = "com.lihaoyi"
@@ -44,12 +44,13 @@ object AcyclicTests extends TestSuite{
val packageScala = workspacePath/'src/'main/'scala/'acyclic/"package.scala"
- 'scala210 - check("2.10.6")
- 'scala211 - check("2.11.8")
- 'scala212 - check("2.12.4")
+ 'scala210 - check("2.10.6", full = false)
+ 'scala211 - check("2.11.8", full = false)
+ 'scala2123 - check("2.12.3", full = true)
+ 'scala2124 - check("2.12.4", full = false)
val allBinaryVersions = Seq("2.10", "2.11", "2.12")
- def check(scalaVersion: String) = {
+ def check(scalaVersion: String, full: Boolean) = {
// Dependencies are right; make sure every dependency is of the correct
// binary Scala version, except for the compiler-bridge which is of the
// same version as the host classpath.
@@ -74,30 +75,31 @@ object AcyclicTests extends TestSuite{
val Right((_, evalCount2)) = eval(AcyclicBuild.acyclic(scalaVersion).compile)
assert(evalCount2 == 0)
- write.append(packageScala, "\n")
+ if (full){
+ // Caches are invalidated if code is changed
+ write.append(packageScala, "\n")
+ val Right((_, evalCount3)) = eval(AcyclicBuild.acyclic(scalaVersion).compile)
+ assert(evalCount3 > 0)
- // Caches are invalidated if code is changed
- val Right((_, evalCount3)) = eval(AcyclicBuild.acyclic(scalaVersion).compile)
- assert(evalCount3 > 0)
+ // Compilation can fail on broken code, and work when fixed
+ write.append(packageScala, "\n}}")
+ val Left(Result.Exception(ex)) = eval(AcyclicBuild.acyclic(scalaVersion).compile)
+ assert(ex.isInstanceOf[sbt.internal.inc.CompileFailed])
- // Compilation can fail on broken code, and work when fixed
- write.append(packageScala, "\n}}")
- val Left(Result.Exception(ex)) = eval(AcyclicBuild.acyclic(scalaVersion).compile)
- assert(ex.isInstanceOf[sbt.internal.inc.CompileFailed])
+ write.write(packageScala, read(packageScala).dropRight(3))
+ val Right(_) = eval(AcyclicBuild.acyclic(scalaVersion).compile)
- write.write(packageScala, read(packageScala).dropRight(3))
- val Right(_) = eval(AcyclicBuild.acyclic(scalaVersion).compile)
+ // Tests compile & run
+ val Right(_) = eval(AcyclicBuild.acyclic(scalaVersion).test.forkTest())
- // Tests compile & run
- val Right(_) = eval(AcyclicBuild.acyclic(scalaVersion).test.forkTest())
+ // Tests can be broken
+ write.append(packageScala, "\n}}")
+ val Left(_) = eval(AcyclicBuild.acyclic(scalaVersion).test.forkTest())
- // Tests can be broken
- write.append(packageScala, "\n}}")
- val Left(_) = eval(AcyclicBuild.acyclic(scalaVersion).test.forkTest())
-
- // Tests can be fixed
- write.write(packageScala, read(packageScala).dropRight(3))
- val Right(_) = eval(AcyclicBuild.acyclic(scalaVersion).test.forkTest())
+ // Tests can be fixed
+ write.write(packageScala, read(packageScala).dropRight(3))
+ val Right(_) = eval(AcyclicBuild.acyclic(scalaVersion).test.forkTest())
+ }
}
}
diff --git a/scalaplugin/src/test/scala/mill/scalaplugin/HelloWorldTests.scala b/scalaplugin/src/test/scala/mill/scalaplugin/HelloWorldTests.scala
index c2f5a7b8..916dd7ca 100644
--- a/scalaplugin/src/test/scala/mill/scalaplugin/HelloWorldTests.scala
+++ b/scalaplugin/src/test/scala/mill/scalaplugin/HelloWorldTests.scala
@@ -119,7 +119,7 @@ object HelloWorldTests extends TestSuite {
val Right((_, incCompileCount)) =
eval(HelloWorld.compile, helloWorldMapping)
- assert(incCompileCount == 1)
+ assert(incCompileCount > 0, incCompileCount < freshCount)
}
'failOnError - {
write.append(mainObject, "val x: ")
diff --git a/scalaplugin/src/test/scala/mill/scalaplugin/TestEvaluator.scala b/scalaplugin/src/test/scala/mill/scalaplugin/TestEvaluator.scala
index e54480c9..242b4e8b 100644
--- a/scalaplugin/src/test/scala/mill/scalaplugin/TestEvaluator.scala
+++ b/scalaplugin/src/test/scala/mill/scalaplugin/TestEvaluator.scala
@@ -4,20 +4,19 @@ import ammonite.ops.Path
import mill.define.{Target, Task}
import mill.discover.Mirror
import mill.eval.{Evaluator, Result}
-import mill.util.OSet
+import mill.util.{DummyLogger, OSet, PrintLogger}
object TestEvaluator {
- private val noopLogger: String => Unit = _ => ()
def resolveDestPaths(workspacePath: Path)(t: Mirror.LabelledTarget[_]): (Path, Path) = {
- new Evaluator(workspacePath, Map.empty, noopLogger).resolveDestPaths(t)
+ new Evaluator(workspacePath, Map.empty, DummyLogger).resolveDestPaths(t)
}
def eval[T](
mapping: Map[Target[_], Mirror.LabelledTarget[_]],
workspacePath: Path)(t: Task[T]): Either[Result.Failing, (T, Int)] = {
- val evaluator = new Evaluator(workspacePath, mapping, noopLogger)
+ val evaluator = new Evaluator(workspacePath, mapping, new PrintLogger(true))
val evaluated = evaluator.evaluate(OSet(t))
if (evaluated.failing.keyCount == 0) {