summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2017-12-06 20:53:29 -0800
committerLi Haoyi <haoyi.sg@gmail.com>2017-12-06 20:54:04 -0800
commit7239d6bd64ec0d025686f5f97aaaf94b7ab43951 (patch)
treeada5a410d1ee7d658d98e3b57e4188d013109451
parent7a1b339b08a7e6b99da7d98b1856d534c207c99e (diff)
downloadmill-7239d6bd64ec0d025686f5f97aaaf94b7ab43951.tar.gz
mill-7239d6bd64ec0d025686f5f97aaaf94b7ab43951.tar.bz2
mill-7239d6bd64ec0d025686f5f97aaaf94b7ab43951.zip
Explicitly pass built compiler-bridge jar locations from the build system into Mill as JVM properties.
This makes the dependency between the compiler-bridge jar and the Mill executable explicit, allowing us to swap out the locations compiler-bridge jars (which end up in different places, depending on whether you're building with SBT or Mill) or eventually making them load from Maven Central in a "release" Mill executable Since Mill (and uTest) both do not support SBT-style test arguments, we need to use `forkTest` instead of `test` to run the Mill tests passing the compiler-jar locations as JVM props. This necessitated some fixes to make `forkTest` behave properly
-rw-r--r--build.sbt54
-rwxr-xr-xbuild.sc21
-rw-r--r--core/src/main/scala/mill/modules/Jvm.scala24
-rw-r--r--scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala21
-rw-r--r--scalaplugin/src/main/scala/mill/scalaplugin/TestRunner.scala5
5 files changed, 80 insertions, 45 deletions
diff --git a/build.sbt b/build.sbt
index 1177cf26..1dc993bf 100644
--- a/build.sbt
+++ b/build.sbt
@@ -8,19 +8,6 @@ val sharedSettings = Seq(
parallelExecution in Test := false,
test in assembly := {},
- assemblyOption in assembly := (assemblyOption in assembly).value.copy(
- prependShellScript = Some(
- // G1 Garbage Collector is awesome https://github.com/lihaoyi/Ammonite/issues/216
- Seq("#!/usr/bin/env sh", """exec java -cp "$0" mill.Main "$@" """)
- )
- ),
- assembly in Test := {
- val dest = target.value/"mill"
- IO.copyFile(assembly.value, dest)
- import sys.process._
- Seq("chmod", "+x", dest.getAbsolutePath).!
- dest
- },
libraryDependencies += "com.lihaoyi" %% "acyclic" % "0.1.7" % "provided",
scalacOptions += "-P:acyclic:force",
autoCompilerPlugins := true,
@@ -97,26 +84,39 @@ lazy val core = project
)
)
+val bridgeProps = Def.task{
+ val mapping = Map(
+ "MILL_COMPILER_BRIDGE_2_10_6" -> (packageBin in (bridge2_10_6, Compile)).value.absolutePath,
+ "MILL_COMPILER_BRIDGE_2_11_8" -> (packageBin in (bridge2_11_8, Compile)).value.absolutePath,
+ "MILL_COMPILER_BRIDGE_2_11_11" -> (packageBin in (bridge2_11_11, Compile)).value.absolutePath,
+ "MILL_COMPILER_BRIDGE_2_12_3" -> (packageBin in (bridge2_12_3, Compile)).value.absolutePath,
+ "MILL_COMPILER_BRIDGE_2_12_4" -> (packageBin in (bridge2_12_4, Compile)).value.absolutePath
+ )
+ for((k, v) <- mapping) yield s"-D$k=$v"
+}
lazy val scalaplugin = project
.dependsOn(core % "compile->compile;test->test")
.settings(
sharedSettings,
name := "mill-scalaplugin",
- (compile in Test) := {
- val a = (packageBin in (bridge2_10_6, Compile)).value
- val b = (packageBin in (bridge2_11_8, Compile)).value
-// val c = (packageBin in (bridge2_11_9, Compile)).value
-// val d = (packageBin in (bridge2_11_10, Compile)).value
- val e = (packageBin in (bridge2_11_11, Compile)).value
-// val f = (packageBin in (bridge2_12_0, Compile)).value
-// val g = (packageBin in (bridge2_12_1, Compile)).value
-// val h = (packageBin in (bridge2_12_2, Compile)).value
- val i = (packageBin in (bridge2_12_3, Compile)).value
- val j = (packageBin in (bridge2_12_4, Compile)).value
- (compile in Test).value
+ fork in Test := true,
+ baseDirectory in (Test, test) := (baseDirectory in (Test, test)).value / "..",
+ javaOptions in (Test, test) := bridgeProps.value.toSeq,
+ assemblyOption in assembly := {
+ (assemblyOption in assembly).value.copy(
+ prependShellScript = Some(
+ Seq(
+ "#!/usr/bin/env sh",
+ s"""exec java ${bridgeProps.value.mkString(" ")} -cp "$$0" mill.Main "$$@" """
+ )
+ )
+ )
},
assembly in Test := {
- (compile in Test).value
- (assembly in Test).value
+ val dest = target.value/"mill"
+ IO.copyFile(assembly.value, dest)
+ import sys.process._
+ Seq("chmod", "+x", dest.getAbsolutePath).!
+ dest
}
)
diff --git a/build.sc b/build.sc
index 7b261892..5d581364 100755
--- a/build.sc
+++ b/build.sc
@@ -5,7 +5,10 @@ import mill.scalaplugin._
trait MillModule extends ScalaModule{ outer =>
def scalaVersion = "2.12.4"
override def sources = basePath/'src/'main/'scala
+ def testArgs = T{ Seq.empty[String] }
object test extends this.Tests{
+ override def defaultCommandName() = "forkTest"
+ override def forkArgs = T{ testArgs() }
override def projectDeps =
if (this == Core.test) Seq(Core)
else Seq(outer, Core.test)
@@ -80,14 +83,20 @@ object ScalaPlugin extends MillModule {
override def projectDeps = Seq(Core)
def basePath = pwd / 'scalaplugin
override def compile = T.persistent[mill.eval.PathRef]{
- bridges("2.10.6").compile()
- bridges("2.11.8").compile()
- bridges("2.11.11").compile()
- bridges("2.12.3").compile()
- bridges("2.12.4").compile()
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,
+ )
+ for((k, v) <- mapping.toSeq) yield s"-D$k=$v"
+ }
+
override def prependShellScript =
"#!/usr/bin/env sh\n" +
- """exec java $JAVA_OPTS -cp "$0" mill.Main "$@" """
+ s"""exec java ${testArgs().mkString(" ")} $$JAVA_OPTS -cp "$$0" mill.Main "$$@" """
}
diff --git a/core/src/main/scala/mill/modules/Jvm.scala b/core/src/main/scala/mill/modules/Jvm.scala
index 43382b8d..ddc8b427 100644
--- a/core/src/main/scala/mill/modules/Jvm.scala
+++ b/core/src/main/scala/mill/modules/Jvm.scala
@@ -1,6 +1,7 @@
package mill.modules
import java.io.FileOutputStream
+import java.net.URLClassLoader
import java.nio.file.attribute.PosixFilePermission
import java.util.jar.{JarEntry, JarFile, JarOutputStream}
@@ -14,16 +15,35 @@ import scala.collection.mutable
object Jvm {
-
+ def gatherClassloaderJars(): Seq[Path] = {
+ val allJars = collection.mutable.Buffer.empty[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 subprocess(mainClass: String,
classPath: Seq[Path],
+ jvmOptions: Seq[String] = Seq.empty,
options: Seq[String] = Seq.empty,
workingDir: Path = ammonite.ops.pwd)
(implicit ctx: Ctx) = {
+
+ val commandArgs =
+ Vector("java") ++
+ jvmOptions ++
+ Vector("-cp", classPath.mkString(":"), mainClass) ++
+ options
+
val proc =
new java.lang.ProcessBuilder()
.directory(workingDir.toIO)
- .command(Vector("java", "-cp", classPath.mkString(":"), mainClass) ++ options:_*)
+ .command(commandArgs:_*)
.redirectOutput(ProcessBuilder.Redirect.PIPE)
.redirectError(ProcessBuilder.Redirect.PIPE)
.start()
diff --git a/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala b/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala
index 49d9660f..0686f131 100644
--- a/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala
+++ b/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala
@@ -34,6 +34,7 @@ object ScalaModule{
}
var scalaInstanceCache = Option.empty[(Long, ScalaInstance)]
+
def compileScala(scalaVersion: String,
sources: Seq[Path],
compileClasspath: Seq[Path],
@@ -52,11 +53,10 @@ object ScalaModule{
}
val compilerJars = compilerClasspath.toArray.map(_.toIO)
- 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 compilerBridgeKey = "MILL_COMPILER_BRIDGE_"+scalaVersion.replace('.', '_')
+ val compilerBridgePath = sys.props(compilerBridgeKey)
+ assert(compilerBridgePath != null, "Cannot find compiler bridge " + compilerBridgeKey)
+ val compilerBridgeJar = new java.io.File(compilerBridgePath)
val classloaderSig = compilerClasspath.map(p => p.toString().hashCode + p.mtime.toMillis).sum
@@ -184,14 +184,15 @@ trait TestScalaModule extends ScalaModule with TaskModule {
def testFramework: T[String]
def forkWorkingDir = ammonite.ops.pwd
+ def forkArgs = T{ Seq.empty[String] }
def forkTest(args: String*) = T.command{
val outputPath = tmp.dir()/"out.json"
+
Jvm.subprocess(
- "mill.scalaplugin.TestRunner",
- getClass.getClassLoader.asInstanceOf[URLClassLoader].getURLs.toList.map(
- u => Path(new java.io.File(u.toURI))
- ),
- Seq(
+ mainClass = "mill.scalaplugin.TestRunner",
+ classPath = Jvm.gatherClassloaderJars(),
+ jvmOptions = forkArgs(),
+ options = Seq(
testFramework(),
(runDepClasspath().map(_.path) :+ compile().path).mkString(" "),
Seq(compile().path).mkString(" "),
diff --git a/scalaplugin/src/main/scala/mill/scalaplugin/TestRunner.scala b/scalaplugin/src/main/scala/mill/scalaplugin/TestRunner.scala
index 43e15974..bc36d9c7 100644
--- a/scalaplugin/src/main/scala/mill/scalaplugin/TestRunner.scala
+++ b/scalaplugin/src/main/scala/mill/scalaplugin/TestRunner.scala
@@ -50,6 +50,11 @@ object TestRunner {
})
val outputPath = args(4)
ammonite.ops.write(Path(outputPath), upickle.default.write(result))
+
+ // 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)
}
def apply(frameworkName: String,
entireClasspath: Seq[Path],