summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.sbt2
-rwxr-xr-xbuild.sc32
-rw-r--r--core/src/mill/eval/Evaluator.scala3
-rw-r--r--core/src/mill/modules/Jvm.scala12
-rw-r--r--scalalib/src/mill/scalalib/ScalaModule.scala21
-rw-r--r--scalalib/src/mill/scalalib/ScalaWorkerApi.scala33
-rw-r--r--scalaworker/src/mill/scalaworker/ScalaWorker.scala37
7 files changed, 79 insertions, 61 deletions
diff --git a/build.sbt b/build.sbt
index aaa0833b..6aad1264 100644
--- a/build.sbt
+++ b/build.sbt
@@ -246,7 +246,7 @@ lazy val integration = project
"MILL_JAWN_REPO" -> testRepos("MILL_JAWN_REPO").value,
"MILL_BETTERFILES_REPO" -> testRepos("MILL_BETTERFILES_REPO").value
)
- for((k, v) <- kvs) yield s"-D$k=$v"
+ scalaWorkerProps.value ++ (for((k, v) <- kvs) yield s"-D$k=$v")
}
)
diff --git a/build.sc b/build.sc
index 2d240084..eb400956 100755
--- a/build.sc
+++ b/build.sc
@@ -99,6 +99,20 @@ class BridgeModule(crossVersion: String) extends PublishModule {
)
}
+
+object scalaworker extends MillModule{
+ def moduleDeps = Seq(core, scalalib)
+
+ def ivyDeps = Agg(
+ ivy"org.scala-sbt::zinc:1.0.5",
+ ivy"org.scala-sbt:test-interface:1.0"
+ )
+ def testArgs = Seq(
+ "-DMILL_SCALA_WORKER=" + runClasspath().map(_.path).mkString(",")
+ )
+}
+
+
object scalalib extends MillModule {
def moduleDeps = Seq(core)
@@ -106,25 +120,17 @@ object scalalib extends MillModule {
def testArgs = T{
val bridgeVersions = bridges.items.map(_._1.head.toString)
- for((version, compile) <- bridgeVersions.zip(bridgeCompiles()))
+ val bridgeArgs = for((version, compile) <- bridgeVersions.zip(bridgeCompiles()))
yield {
val underscored = version.replace('.', '_')
val key = s"MILL_COMPILER_BRIDGE_$underscored"
val value = compile.classes.path
s"-D$key=$value"
}
+ scalaworker.testArgs() ++ bridgeArgs
}
}
-object scalaworker extends MillModule{
- def moduleDeps = Seq(core, scalalib)
-
- def ivyDeps = Agg(
- ivy"org.scala-sbt::zinc:1.0.5",
- ivy"org.scala-sbt:test-interface:1.0"
- )
-}
-
object scalajslib extends MillModule {
@@ -137,7 +143,7 @@ object scalajslib extends MillModule {
"MILL_SCALAJS_BRIDGE_0_6" -> bridgeClasspath(jsbridges("0.6").runDepClasspath(), jsbridges("0.6").compile().classes),
"MILL_SCALAJS_BRIDGE_1_0" -> bridgeClasspath(jsbridges("1.0").runDepClasspath(), jsbridges("1.0").compile().classes)
)
- for((k, v) <- mapping.toSeq) yield s"-D$k=$v"
+ scalaworker.testArgs() ++ (for((k, v) <- mapping.toSeq) yield s"-D$k=$v")
}
object jsbridges extends Cross[JsBridgeModule]("0.6", "1.0")
@@ -167,7 +173,7 @@ def testRepos = T{
object integration extends MillModule{
def moduleDeps = Seq(moduledefs, scalalib, scalajslib)
def testArgs = T{
- for((k, v) <- testRepos()) yield s"-D$k=$v"
+ scalaworker.testArgs() ++ (for((k, v) <- testRepos()) yield s"-D$k=$v")
}
def forkArgs() = testArgs()
}
@@ -193,7 +199,7 @@ def assemblyBase(classpath: Agg[Path], extraArgs: String)
def devAssembly = T{
assemblyBase(
Agg.from(assemblyClasspath().flatten.map(_.path)),
- (scalalib.testArgs() ++ scalajslib.testArgs() ++ Seq(scalaworker.jar())).mkString(" ")
+ (scalalib.testArgs() ++ scalajslib.testArgs() ++ scalaworker.testArgs()).mkString(" ")
)
}
diff --git a/core/src/mill/eval/Evaluator.scala b/core/src/mill/eval/Evaluator.scala
index cf4b32cf..0e8709e0 100644
--- a/core/src/mill/eval/Evaluator.scala
+++ b/core/src/mill/eval/Evaluator.scala
@@ -44,7 +44,8 @@ class Evaluator[T](val workspacePath: Path,
case t: NamedTask[Any] =>
val segments = t.ctx.segments
val (finalTaskOverrides, enclosing) = t match{
- case t: Target[_] => rootModule.millInternal.segmentsToTargets(segments).ctx.overrides -> t.ctx.enclosing
+ case t: Target[_] =>
+ rootModule.millInternal.segmentsToTargets.get(segments).fold(0)(_.ctx.overrides) -> t.ctx.enclosing
case c: mill.define.Command[_] => 0 -> c.ctx.enclosing
case c: mill.define.Worker[_] => 0 -> c.ctx.enclosing
}
diff --git a/core/src/mill/modules/Jvm.scala b/core/src/mill/modules/Jvm.scala
index 0fa7e3e3..d9abff86 100644
--- a/core/src/mill/modules/Jvm.scala
+++ b/core/src/mill/modules/Jvm.scala
@@ -20,18 +20,6 @@ import scala.reflect.ClassTag
object Jvm {
- def gatherClassloaderJars(): Agg[Path] = {
- val allJars = new Agg.Mutable[Path]()
- var currentClassloader = Thread.currentThread().getContextClassLoader
- while(currentClassloader != null){
- currentClassloader match{
- case u: URLClassLoader => allJars.appendAll(u.getURLs.map(x => Path(x.getFile)))
- case _ =>
- }
- currentClassloader = currentClassloader.getParent
- }
- allJars
- }
def interactiveSubprocess(mainClass: String,
classPath: Agg[Path],
diff --git a/scalalib/src/mill/scalalib/ScalaModule.scala b/scalalib/src/mill/scalalib/ScalaModule.scala
index 77ebc417..848e0318 100644
--- a/scalalib/src/mill/scalalib/ScalaModule.scala
+++ b/scalalib/src/mill/scalalib/ScalaModule.scala
@@ -295,12 +295,11 @@ trait TestModule extends ScalaModule with TaskModule {
def forkWorkingDir = ammonite.ops.pwd
def test(args: String*) = T.command{
- mkdir(T.ctx().dest)
val outputPath = T.ctx().dest/"out.json"
Jvm.subprocess(
- mainClass = "mill.scalalib.TestRunner",
- classPath = Jvm.gatherClassloaderJars(),
+ mainClass = "mill.scalaworker.ScalaWorker",
+ classPath = mill.scalalib.ScalaWorkerApi.scalaWorkerClasspath(),
jvmArgs = forkArgs(),
envArgs = forkEnv(),
mainArgs = Seq(
@@ -323,17 +322,11 @@ trait TestModule extends ScalaModule with TaskModule {
mkdir(T.ctx().dest)
val outputPath = T.ctx().dest/"out.json"
- Jvm.runLocal(
- mainClass = "mill.scalalib.TestRunner",
- classPath = Jvm.gatherClassloaderJars(),
- mainArgs = Seq(
- testFramework(),
- runClasspath().map(_.path).mkString(" "),
- Seq(compile().classes.path).mkString(" "),
- args.mkString(" "),
- outputPath.toString,
- T.ctx().log.colored.toString
- )
+ mill.scalalib.ScalaWorkerApi.scalaWorker().apply(
+ testFramework(),
+ runClasspath().map(_.path),
+ Agg(compile().classes.path),
+ args
)
val jsonOutput = upickle.json.read(outputPath.toIO)
diff --git a/scalalib/src/mill/scalalib/ScalaWorkerApi.scala b/scalalib/src/mill/scalalib/ScalaWorkerApi.scala
index a032ab32..43b82460 100644
--- a/scalalib/src/mill/scalalib/ScalaWorkerApi.scala
+++ b/scalalib/src/mill/scalalib/ScalaWorkerApi.scala
@@ -12,25 +12,24 @@ import mill.define.{Task, Worker}
import mill.eval.PathRef
import mill.scalalib.Lib.resolveDependencies
import mill.util.Loose
-
+import mill.util.JsonFormatters._
object ScalaWorkerApi extends mill.define.BaseModule(ammonite.ops.pwd){
- def scalaWorker: Worker[ScalaWorkerApi] = T.worker{
-
+ def scalaWorkerClasspath = T{
val scalaWorkerJar = sys.props("MILL_SCALA_WORKER")
- val scalaWorkerClasspath =
- if (scalaWorkerJar != null) Loose.Agg.from(scalaWorkerJar.split(',').map(Path(_)))
- else {
- val mill.eval.Result.Success(v) = resolveDependencies(
- Seq(MavenRepository("https://repo1.maven.org/maven2")),
- "2.12.4",
- "2.12",
- Seq(ivy"com.lihaoyi::mill-scalaworker:0.1-SNAPSHOT")
- )
- v.map(_.path)
- }
-
+ if (scalaWorkerJar != null) Loose.Agg.from(scalaWorkerJar.split(',').map(Path(_)))
+ else {
+ val mill.eval.Result.Success(v) = resolveDependencies(
+ Seq(MavenRepository("https://repo1.maven.org/maven2")),
+ "2.12.4",
+ "2.12",
+ Seq(ivy"com.lihaoyi::mill-scalaworker:0.1-SNAPSHOT")
+ )
+ v.map(_.path)
+ }
+ }
+ def scalaWorker: Worker[ScalaWorkerApi] = T.worker{
val cl = new java.net.URLClassLoader(
- scalaWorkerClasspath.map(_.toNIO.toUri.toURL).toArray,
+ scalaWorkerClasspath().map(_.toNIO.toUri.toURL).toArray,
getClass.getClassLoader
)
val cls = cl.loadClass("mill.scalaworker.ScalaWorker")
@@ -56,5 +55,5 @@ trait ScalaWorkerApi {
entireClasspath: Agg[Path],
testClassfilePath: Agg[Path],
args: Seq[String])
- (implicit ctx: mill.util.Ctx): (String, Seq[Result])
+ (implicit ctx: mill.util.Ctx.LogCtx): (String, Seq[Result])
}
diff --git a/scalaworker/src/mill/scalaworker/ScalaWorker.scala b/scalaworker/src/mill/scalaworker/ScalaWorker.scala
index df92cd0f..6c6cb504 100644
--- a/scalaworker/src/mill/scalaworker/ScalaWorker.scala
+++ b/scalaworker/src/mill/scalaworker/ScalaWorker.scala
@@ -7,15 +7,16 @@ import java.util.Optional
import java.util.zip.ZipInputStream
import ammonite.ops.{Path, exists, ls, mkdir}
+import ammonite.util.Colors
import mill.Agg
import mill.define.Worker
import mill.eval.PathRef
import mill.modules.Jvm
-import mill.scalalib.CompilationResult
+import mill.scalalib.{CompilationResult, TestRunner}
import xsbti.compile.{CompilerCache => _, FileAnalysisStore => _, ScalaInstance => _, _}
import mill.scalalib.Lib.grepJar
import mill.scalalib.TestRunner.Result
-import mill.util.Ctx
+import mill.util.{Ctx, PrintLogger}
import sbt.internal.inc._
import sbt.internal.util.{ConsoleOut, MainAppender}
import sbt.testing._
@@ -31,7 +32,37 @@ case class MockedLookup(am: File => Optional[CompileAnalysis]) extends PerClassp
Locate.definesClass(classpathEntry)
}
+object ScalaWorker{
+
+ def main(args: Array[String]): Unit = {
+ try{
+ val result = new ScalaWorker(null).apply(
+ frameworkName = args(0),
+ entireClasspath = Agg.from(args(1).split(" ").map(Path(_))),
+ testClassfilePath = Agg.from(args(2).split(" ").map(Path(_))),
+ args = args(3) match{ case "" => Nil case x => x.split(" ").toList }
+ )(new PrintLogger(
+ args(5) == "true",
+ if(args(5) == "true") Colors.Default
+ else Colors.BlackWhite,
+ System.out,
+ System.err,
+ System.err
+ ))
+ val outputPath = args(4)
+ ammonite.ops.write(Path(outputPath), upickle.default.write(result))
+ }catch{case e: Throwable =>
+ println(e)
+ e.printStackTrace()
+ }
+ // Tests are over, kill the JVM whether or not anyone's threads are still running
+ // Always return 0, even if tests fail. The caller can pick up the detailed test
+ // results from the outputPath
+ System.exit(0)
+ }
+
+}
class ScalaWorker(ctx0: mill.util.Ctx) extends mill.scalalib.ScalaWorkerApi{
@volatile var scalaClassloaderCache = Option.empty[(Long, ClassLoader)]
@volatile var scalaInstanceCache = Option.empty[(Long, ScalaInstance)]
@@ -167,7 +198,7 @@ class ScalaWorker(ctx0: mill.util.Ctx) extends mill.scalalib.ScalaWorkerApi{
entireClasspath: Agg[Path],
testClassfilePath: Agg[Path],
args: Seq[String])
- (implicit ctx: mill.util.Ctx): (String, Seq[Result]) = {
+ (implicit ctx: mill.util.Ctx.LogCtx): (String, Seq[Result]) = {
Jvm.inprocess(entireClasspath, classLoaderOverrideSbtTesting = true, cl => {
val framework = cl.loadClass(frameworkName)