From 11c194da920cd6a4196ddfbb875c0d1faa47fcff Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Wed, 24 Jan 2018 22:05:33 -0800 Subject: Migrate `scalajslib` over to a `T.worker` setup similar to `scalalib` --- scalajslib/src/mill/scalajslib/Lib.scala | 62 ------------------ .../src/mill/scalajslib/ScalaJSLinkerBridge.scala | 62 +++++++++++++++++- scalajslib/src/mill/scalajslib/ScalaJSModule.scala | 74 ++++++++++++++-------- 3 files changed, 109 insertions(+), 89 deletions(-) delete mode 100644 scalajslib/src/mill/scalajslib/Lib.scala (limited to 'scalajslib/src') diff --git a/scalajslib/src/mill/scalajslib/Lib.scala b/scalajslib/src/mill/scalajslib/Lib.scala deleted file mode 100644 index 6a85cf0c..00000000 --- a/scalajslib/src/mill/scalajslib/Lib.scala +++ /dev/null @@ -1,62 +0,0 @@ -package mill -package scalajslib - -import java.io.File -import java.net.URLClassLoader - -import ammonite.ops.{Path, mkdir, rm, _} -import mill.eval.PathRef -import mill.scalalib.Dep -import mill.util.{Ctx, Loose} - -import scala.collection.breakOut -import scala.language.reflectiveCalls - -private object LinkerBridge { - @volatile var scalaInstanceCache = Option.empty[(Long, ScalaJSLinkerBridge)] -} - -object Lib { - - def scalaJSLinkerIvyDep(scalaJSVersion: String): Dep = - Dep("com.lihaoyi", s"mill-jsbridge_${scalaJSVersion.replace('.', '_')}", "0.1-SNAPSHOT") - - def scalaJSLinkerBridge(classPath: Loose.Agg[Path]): ScalaJSLinkerBridge = { - val classloaderSig = classPath.map(p => p.toString().hashCode + p.mtime.toMillis).sum - LinkerBridge.scalaInstanceCache match { - case Some((`classloaderSig`, linker)) => linker - case _ => - val cl = new URLClassLoader(classPath.map(_.toIO.toURI.toURL).toArray) - val bridge = cl.loadClass("mill.scalajslib.bridge.ScalaJSLinkerBridge") - .getDeclaredConstructor().newInstance().asInstanceOf[ { - def link(sources: Array[File], libraries: Array[File], dest: File, main: String, fullOpt: Boolean): Unit - }] - val linker: ScalaJSLinkerBridge = (sources: Seq[File], - libraries: Seq[File], - dest: File, - main: Option[String], - mode: OptimizeMode) => - bridge.link(sources.toArray, libraries.toArray, dest, main.orNull, mode == FullOpt) - LinkerBridge.scalaInstanceCache = Some((classloaderSig, linker)) - linker - } - } - - def link(main: Option[String], - inputPaths: Seq[Path], - libraries: Loose.Agg[Path], - linker: ScalaJSLinkerBridge, - mode: OptimizeMode) - (implicit ctx: Ctx.DestCtx): PathRef = { - val outputPath = ctx.dest.copy(segments = ctx.dest.segments.init :+ (ctx.dest.segments.last + ".js")) - rm(outputPath) - if (inputPaths.nonEmpty) { - mkdir(outputPath / up) - val inputFiles: Vector[File] = inputPaths.map(ls).flatMap(_.filter(_.ext == "sjsir")).map(_.toIO)(breakOut) - val inputLibraries: Vector[File] = libraries.filter(_.ext == "jar").map(_.toIO).toVector - linker.link(inputFiles, inputLibraries, outputPath.toIO, main, mode) - } - PathRef(outputPath) - } - -} diff --git a/scalajslib/src/mill/scalajslib/ScalaJSLinkerBridge.scala b/scalajslib/src/mill/scalajslib/ScalaJSLinkerBridge.scala index 448cc16a..ae282152 100644 --- a/scalajslib/src/mill/scalajslib/ScalaJSLinkerBridge.scala +++ b/scalajslib/src/mill/scalajslib/ScalaJSLinkerBridge.scala @@ -1,12 +1,72 @@ package mill.scalajslib import java.io.File +import java.net.URLClassLoader + +import ammonite.ops.Path +import mill.{Agg, T} sealed trait OptimizeMode object FastOpt extends OptimizeMode object FullOpt extends OptimizeMode +class ScalaJSLinkerWorker { + var scalaInstanceCache = Option.empty[(Long, ScalaJSLinkerBridge)] + def link(toolsClasspath: Agg[Path], + sources: Agg[Path], + libraries: Agg[Path], + dest: File, + main: Option[String], + fullOpt: Boolean): Unit = { + + val classloaderSig = { + toolsClasspath.map(p => p.toString().hashCode + p.mtime.toMillis).sum + } + + val bridge = scalaInstanceCache match{ + case Some((sig, bridge)) if sig == classloaderSig => bridge + case _ => + val outerClassLoader = getClass.getClassLoader + val cl = new URLClassLoader(toolsClasspath.map(_.toIO.toURI.toURL).toArray){ + override def findClass(name: String) = { + if (name.startsWith("mill.scalajslib.ScalaJSLinkerBridge")){ + outerClassLoader.loadClass(name) + }else{ + super.findClass(name) + } + } + } + val bridge = cl + .loadClass("mill.scalajslib.bridge.ScalaJSLinkerBridge") + .getDeclaredConstructor() + .newInstance() + .asInstanceOf[ScalaJSLinkerBridge] + scalaInstanceCache = Some((classloaderSig, bridge)) + bridge + } + bridge.link( + sources.items.map(_.toIO).toArray, + libraries.items.map(_.toIO).toArray, + dest, + main.orNull, + fullOpt + ) + } + +} + trait ScalaJSLinkerBridge { - def link(sources: Seq[File], libraries: Seq[File], dest: File, main: Option[String], mode: OptimizeMode): Unit + def link(sources: Array[File], + libraries: Array[File], + dest: File, + main: String, + fullOpt: Boolean): Unit } + +object ScalaJSLinkerBridge extends mill.define.BaseModule(ammonite.ops.pwd){ + + def scalaJSLinkerBridge = T.worker{ + new ScalaJSLinkerWorker() + } +} \ No newline at end of file diff --git a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala index 5c964fd6..0286d573 100644 --- a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala +++ b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala @@ -3,13 +3,17 @@ package scalajslib import java.io.File -import ammonite.ops.Path +import mill.scalalib.DepSyntax +import ammonite.ops.{Path, ls, mkdir, rm} +import coursier.maven.MavenRepository +import mill.eval.PathRef import mill.eval.Result.Success -import mill.scalajslib.Lib._ import mill.scalalib.Lib.resolveDependencies -import mill.scalalib.{Dep, ScalaModule, PublishModule, TestModule} +import mill.scalalib.{Dep, PublishModule, ScalaModule, TestModule} import mill.util.Loose +import scala.collection.breakOut + trait ScalaJSModule extends scalalib.ScalaModule { outer => def scalaJSVersion: T[String] @@ -27,37 +31,55 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => def scalaJSBridgeVersion = T{ scalaJSVersion().split('.').dropRight(1).mkString(".") } - def scalaJSLinkerClasspath: T[Loose.Agg[PathRef]] = T{ + def sjsLinkerBridgeClasspath = T { val jsBridgeKey = "MILL_SCALAJS_BRIDGE_" + scalaJSBridgeVersion().replace('.', '_') val jsBridgePath = sys.props(jsBridgeKey) - if (jsBridgePath != null) { - Success( - Loose.Agg.from( - jsBridgePath.split(File.pathSeparator).map(f => PathRef(Path(f), quick = true)) - ) - ) - } - else { - val dep = scalaJSLinkerIvyDep(scalaJSBridgeVersion()) - resolveDependencies( - repositories, - scalaVersion(), - scalaBinaryVersion(), - Seq(dep) - ) - } + if (jsBridgePath != null) Success( + PathRef(Path(jsBridgePath), quick = true) + ) else resolveDependencies( + Seq(MavenRepository("https://repo1.maven.org/maven2")), + "2.12.4", + "2.12", + Seq(Dep( + "com.lihaoyi", + s"mill-jsbridge_${scalaJSBridgeVersion().replace('.', '_')}", + "0.1-SNAPSHOT" + )) + ).map(_.find(_.path.toString.contains("mill-jsbridge")).get) } - def fastOpt = T{ - val linker = scalaJSLinkerBridge(scalaJSLinkerClasspath().map(_.path)) - link(mainClass(), Seq(compile().classes.path), compileDepClasspath().map(_.path), linker, FastOpt) + + def scalaJSLinkerClasspath: T[Loose.Agg[PathRef]] = T{ + resolveDependencies( + repositories, + "2.12.4", + "2.12", + Seq(ivy"org.scala-js::scalajs-tools:${scalaJSVersion()}") + ) } - def fullOpt = T{ - val linker = scalaJSLinkerBridge(scalaJSLinkerClasspath().map(_.path)) - link(mainClass(), Seq(compile().classes.path), compileDepClasspath().map(_.path), linker, FullOpt) + def genericOpt(mode: OptimizeMode) = T.task{ + val outputPath = T.ctx().dest / "out.js" + + mkdir(T.ctx().dest) + rm(outputPath) + val inputFiles = Agg.from(ls(compile().classes.path).filter(_.ext == "sjsir")) + val inputLibraries = compileDepClasspath().map(_.path).filter(_.ext == "jar") + mill.scalajslib.ScalaJSLinkerBridge.scalaJSLinkerBridge().link( + (Agg(sjsLinkerBridgeClasspath()) ++ scalaJSLinkerClasspath()).map(_.path), + inputFiles, + inputLibraries, + outputPath.toIO, + mainClass(), + mode == FullOpt + ) + PathRef(outputPath) } + def fastOpt = T{ genericOpt(FastOpt)() } + + def fullOpt = T{ genericOpt(FullOpt)() } + override def scalacPluginIvyDeps = T{ Loose.Agg(Dep.Point("org.scala-js", "scalajs-compiler", scalaJSVersion())) } override def ivyDeps = T{ Loose.Agg(Dep("org.scala-js", "scalajs-library", scalaJSVersion())) } -- cgit v1.2.3