diff options
Diffstat (limited to 'scalajslib/src/ScalaJSModule.scala')
-rw-r--r-- | scalajslib/src/ScalaJSModule.scala | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/scalajslib/src/ScalaJSModule.scala b/scalajslib/src/ScalaJSModule.scala new file mode 100644 index 00000000..137e8ee2 --- /dev/null +++ b/scalajslib/src/ScalaJSModule.scala @@ -0,0 +1,201 @@ +package mill +package scalajslib + +import coursier.Cache +import coursier.maven.MavenRepository +import mill.eval.{PathRef, Result} +import mill.api.Result.Success +import mill.scalalib.Lib.resolveDependencies +import mill.scalalib.{DepSyntax, Lib, TestModule, TestRunner} +import mill.util.Ctx +import mill.api.Loose +import mill.scalajslib.api._ +trait ScalaJSModule extends scalalib.ScalaModule { outer => + + def scalaJSVersion: T[String] + + trait Tests extends TestScalaJSModule { + override def zincWorker = outer.zincWorker + override def scalaOrganization = outer.scalaOrganization() + override def scalaVersion = outer.scalaVersion() + override def scalaJSVersion = outer.scalaJSVersion() + override def moduleDeps = Seq(outer) + } + + def scalaJSBinaryVersion = T { mill.scalalib.api.Util.scalaBinaryVersion(scalaJSVersion()) } + + def scalaJSWorkerVersion = T{ scalaJSVersion().split('.').dropRight(1).mkString(".") } + + def scalaJSWorkerClasspath = T { + val workerKey = "MILL_SCALAJS_WORKER_" + scalaJSWorkerVersion().replace('.', '_') + mill.modules.Util.millProjectModule( + workerKey, + s"mill-scalajslib-worker-${scalaJSWorkerVersion()}", + repositories, + resolveFilter = _.toString.contains("mill-scalajslib-worker") + ) + } + + def scalaJSLinkerClasspath: T[Loose.Agg[PathRef]] = T{ + val commonDeps = Seq( + ivy"org.scala-js::scalajs-tools:${scalaJSVersion()}", + ivy"org.scala-js::scalajs-sbt-test-adapter:${scalaJSVersion()}" + ) + val envDep = scalaJSBinaryVersion() match { + case v if v.startsWith("0.6") => ivy"org.scala-js::scalajs-js-envs:${scalaJSVersion()}" + case v if v.startsWith("1.0") => ivy"org.scala-js::scalajs-env-nodejs:${scalaJSVersion()}" + } + resolveDependencies( + repositories, + Lib.depToDependency(_, "2.12.4", ""), + commonDeps :+ envDep + ) + } + + def toolsClasspath = T { scalaJSWorkerClasspath() ++ scalaJSLinkerClasspath() } + + def fastOpt = T { + link( + ScalaJSWorkerApi.scalaJSWorker(), + toolsClasspath(), + runClasspath(), + finalMainClassOpt().toOption, + FastOpt, + moduleKind() + ) + } + + def fullOpt = T { + link( + ScalaJSWorkerApi.scalaJSWorker(), + toolsClasspath(), + runClasspath(), + finalMainClassOpt().toOption, + FullOpt, + moduleKind() + ) + } + + override def runLocal(args: String*) = T.command { run(args:_*) } + + override def run(args: String*) = T.command { + finalMainClassOpt() match{ + case Left(err) => Result.Failure(err) + case Right(_) => + ScalaJSWorkerApi.scalaJSWorker().run( + toolsClasspath().map(_.path), + nodeJSConfig(), + fastOpt().path.toIO + ) + Result.Success(()) + } + + } + + override def runMainLocal(mainClass: String, args: String*) = T.command[Unit] { + mill.api.Result.Failure("runMain is not supported in Scala.js") + } + + override def runMain(mainClass: String, args: String*) = T.command[Unit] { + mill.api.Result.Failure("runMain is not supported in Scala.js") + } + + def link(worker: ScalaJSWorker, + toolsClasspath: Agg[PathRef], + runClasspath: Agg[PathRef], + mainClass: Option[String], + mode: OptimizeMode, + moduleKind: ModuleKind)(implicit ctx: Ctx): Result[PathRef] = { + val outputPath = ctx.dest / "out.js" + + os.makeDir.all(ctx.dest) + os.remove.all(outputPath) + + val classpath = runClasspath.map(_.path) + val sjsirFiles = classpath + .filter(path => os.exists(path) && os.isDir(path)) + .flatMap(os.walk(_)) + .filter(_.ext == "sjsir") + val libraries = classpath.filter(_.ext == "jar") + worker.link( + toolsClasspath.map(_.path), + sjsirFiles, + libraries, + outputPath.toIO, + mainClass, + mode == FullOpt, + moduleKind + ).map(PathRef(_)) + } + + override def scalacPluginIvyDeps = T{ + super.scalacPluginIvyDeps() ++ + Seq(ivy"org.scala-js:::scalajs-compiler:${scalaJSVersion()}") + } + override def scalaLibraryIvyDeps = T{ + Seq(ivy"org.scala-js::scalajs-library:${scalaJSVersion()}") + } + + // publish artifact with name "mill_sjs0.6.4_2.12" instead of "mill_sjs0.6_2.12" + def crossFullScalaJSVersion: T[Boolean] = false + def artifactScalaJSVersion: T[String] = T { + if (crossFullScalaJSVersion()) scalaJSVersion() + else scalaJSBinaryVersion() + } + + override def artifactSuffix: T[String] = s"${platformSuffix()}_${artifactScalaVersion()}" + + override def platformSuffix = s"_sjs${artifactScalaJSVersion()}" + + def nodeJSConfig = T { NodeJSConfig() } + + def moduleKind: T[ModuleKind] = T { ModuleKind.NoModule } +} + +trait TestScalaJSModule extends ScalaJSModule with TestModule { + def scalaJSTestDeps = T { + resolveDeps(T.task { + Loose.Agg( + ivy"org.scala-js::scalajs-library:${scalaJSVersion()}", + ivy"org.scala-js::scalajs-test-interface:${scalaJSVersion()}" + ) + }) + } + + def fastOptTest = T { + link( + ScalaJSWorkerApi.scalaJSWorker(), + toolsClasspath(), + scalaJSTestDeps() ++ runClasspath(), + None, + FastOpt, + moduleKind() + ) + } + + override def testLocal(args: String*) = T.command { test(args:_*) } + + override def test(args: String*) = T.command { + val (close, framework) = mill.scalajslib.ScalaJSWorkerApi.scalaJSWorker().getFramework( + toolsClasspath().map(_.path), + nodeJSConfig(), + testFrameworks().head, + fastOptTest().path.toIO + ) + + val (doneMsg, results) = TestRunner.runTests( + _ => Seq(framework), + runClasspath().map(_.path), + Agg(compile().classes.path), + args + ) + val res = TestModule.handleResults(doneMsg, results) + // Hack to try and let the Node.js subprocess finish streaming it's stdout + // to the JVM. Without this, the stdout can still be streaming when `close()` + // is called, and some of the output is dropped onto the floor. + Thread.sleep(100) + close() + res + } + +} |