From 7e44da8a8b97f2a2e5d2de489369d5075a6e1ea7 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Sat, 3 Feb 2018 23:21:01 -0800 Subject: flexiblize T.sources and use it widely, which lets us fix --watch --- core/src/mill/define/Task.scala | 63 +++++++++++++++------- core/src/mill/main/MainRunner.scala | 1 + core/src/mill/main/RunScript.scala | 3 +- core/test/resources/examples/javac/build.sc | 8 +-- core/test/src/mill/eval/JavaCompileJarTests.scala | 10 ++-- docs/tasks.md | 34 ++++++++---- .../src/mill/scalajslib/HelloJSWorldTests.scala | 4 +- scalalib/src/mill/scalalib/MiscModule.scala | 33 +++++------- scalalib/src/mill/scalalib/ScalaModule.scala | 4 +- 9 files changed, 96 insertions(+), 64 deletions(-) diff --git a/core/src/mill/define/Task.scala b/core/src/mill/define/Task.scala index a94d9703..230089bf 100644 --- a/core/src/mill/define/Task.scala +++ b/core/src/mill/define/Task.scala @@ -126,32 +126,47 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul ) } - def source(value: Result[ammonite.ops.Path]) - (implicit r: R[PathRef], - w: W[PathRef], - ctx: mill.define.Ctx): Input[PathRef] = macro sourceImpl - - def sourceImpl(c: Context) - (value: c.Expr[Result[ammonite.ops.Path]]) - (r: c.Expr[R[PathRef]], - w: c.Expr[W[PathRef]], - ctx: c.Expr[mill.define.Ctx]): c.Expr[Input[PathRef]] = { + def sources(values: Result[ammonite.ops.Path]*) + (implicit ctx: mill.define.Ctx): Sources = macro sourcesImpl1 + + def sourcesImpl1(c: Context) + (values: c.Expr[Result[ammonite.ops.Path]]*) + (ctx: c.Expr[mill.define.Ctx]): c.Expr[Sources] = { import c.universe._ - val wrapped: c.Expr[Result[PathRef]] = reify(value.splice match{ - case Result.Success(p) => Result.Success(PathRef(p)) - case x: Result.Failing => x - }) - mill.moduledefs.Cacher.impl0[Input[PathRef]](c)( + val wrapped = + for (value <- values.toList) + yield Applicative.impl0[Task, PathRef, mill.util.Ctx](c)( + reify(value.splice.map(PathRef(_))).tree + ).tree + + mill.moduledefs.Cacher.impl0[Sources](c)( reify( - new Input[PathRef]( - Applicative.impl0[Task, PathRef, mill.util.Ctx](c)(wrapped.tree).splice, - ctx.splice, - RW(w.splice.write, r.splice.read), + new Sources( + Task.sequence(c.Expr[List[Task[PathRef]]](q"scala.List(..$wrapped)").splice), + ctx.splice ) ) ) } + def sources(values: Result[Seq[PathRef]]) + (implicit ctx: mill.define.Ctx): Sources = macro sourcesImpl2 + + def sourcesImpl2(c: Context) + (values: c.Expr[Result[Seq[PathRef]]]) + (ctx: c.Expr[mill.define.Ctx]): c.Expr[Sources] = { + import c.universe._ + + + mill.moduledefs.Cacher.impl0[Sources](c)( + reify( + new Sources( + Applicative.impl0[Task, Seq[PathRef], mill.util.Ctx](c)(values.tree).splice, + ctx.splice + ) + ) + ) + } def input[T](value: Result[T]) (implicit r: R[T], w: W[T], @@ -305,7 +320,15 @@ class Input[T](t: Task[T], val readWrite: RW[_]) extends NamedTaskImpl[T](ctx0, t) with Target[T]{ override def sideHash = util.Random.nextInt() } - +class Sources(t: Task[Seq[PathRef]], + ctx0: mill.define.Ctx) extends Input[Seq[PathRef]]( + t, + ctx0, + RW( + upickle.default.SeqishW[PathRef, Seq].write, + upickle.default.SeqishR[Seq, PathRef].read + ) +) object Task { class Task0[T](t: T) extends Task[T]{ diff --git a/core/src/mill/main/MainRunner.scala b/core/src/mill/main/MainRunner.scala index 06e1795f..e3820e3d 100644 --- a/core/src/mill/main/MainRunner.scala +++ b/core/src/mill/main/MainRunner.scala @@ -24,6 +24,7 @@ class MainRunner(config: ammonite.main.Cli.Config, config, outprintStream, errPrintStream, stdIn, outprintStream, errPrintStream ){ + var lastEvaluator: Option[(Seq[(Path, Long)], Evaluator[Any])] = None override def runScript(scriptPath: Path, scriptArgs: List[String]) = diff --git a/core/src/mill/main/RunScript.scala b/core/src/mill/main/RunScript.scala index e5c92e3e..a05c7623 100644 --- a/core/src/mill/main/RunScript.scala +++ b/core/src/mill/main/RunScript.scala @@ -161,8 +161,9 @@ object RunScript{ val watched = evaluated.results .iterator .collect { - case (t: define.Input[_], Result.Success(p: PathRef)) => p + case (t: define.Sources, Result.Success(p: Seq[PathRef])) => p } + .flatten .toSeq val errorStr = diff --git a/core/test/resources/examples/javac/build.sc b/core/test/resources/examples/javac/build.sc index 8f250014..0783ac17 100644 --- a/core/test/resources/examples/javac/build.sc +++ b/core/test/resources/examples/javac/build.sc @@ -12,11 +12,11 @@ def resourceRootPath = millSourcePath / 'resources // | // v // resourceRoot ----> jar -def sourceRoot = T.source{ sourceRootPath } -def resourceRoot = T.source{ resourceRootPath } -def allSources = T{ ls.rec(sourceRoot().path).map(PathRef(_)) } +def sourceRoot = T.sources{ sourceRootPath } +def resourceRoot = T.sources{ resourceRootPath } +def allSources = T{ sourceRoot().flatMap(p => ls.rec(p.path)).map(PathRef(_)) } def classFiles = T{ compileAll(allSources()) } -def jar = T{ Jvm.createJar(Loose.Agg(resourceRoot().path, classFiles().path)) } +def jar = T{ Jvm.createJar(Loose.Agg(classFiles().path) ++ resourceRoot().map(_.path)) } def run(mainClsName: String) = T.command{ %%('java, "-cp", classFiles().path, mainClsName)(T.ctx().dest) diff --git a/core/test/src/mill/eval/JavaCompileJarTests.scala b/core/test/src/mill/eval/JavaCompileJarTests.scala index a67d669d..71feebda 100644 --- a/core/test/src/mill/eval/JavaCompileJarTests.scala +++ b/core/test/src/mill/eval/JavaCompileJarTests.scala @@ -35,11 +35,11 @@ object JavaCompileJarTests extends TestSuite{ // | // v // resourceRoot ----> jar - def sourceRoot = T.source{ sourceRootPath } - def resourceRoot = T.source{ resourceRootPath } - def allSources = T{ ls.rec(sourceRoot().path).map(PathRef(_)) } + def sourceRoot = T.sources{ sourceRootPath } + def resourceRoot = T.sources{ resourceRootPath } + def allSources = T{ sourceRoot().flatMap(p => ls.rec(p.path)).map(PathRef(_)) } def classFiles = T{ compileAll(allSources()) } - def jar = T{ Jvm.createJar(Loose.Agg(resourceRoot().path, classFiles().path)) } + def jar = T{ Jvm.createJar(Loose.Agg(classFiles().path) ++ resourceRoot().map(_.path)) } def run(mainClsName: String) = T.command{ %%('java, "-cp", classFiles().path, mainClsName) @@ -108,12 +108,12 @@ object JavaCompileJarTests extends TestSuite{ val jarContents = %%('jar, "-tf", evaluator.outPath/'jar/'dest/"out.jar")(evaluator.outPath).out.string val expectedJarContents = """META-INF/MANIFEST.MF - |hello.txt |test/Bar.class |test/BarThree.class |test/BarTwo.class |test/Foo.class |test/FooTwo.class + |hello.txt |""".stripMargin assert(jarContents == expectedJarContents) diff --git a/docs/tasks.md b/docs/tasks.md index ef9270bb..73695bb8 100644 --- a/docs/tasks.md +++ b/docs/tasks.md @@ -7,14 +7,16 @@ The following is a simple self-contained example using Mill to compile Java: ```scala import ammonite.ops._, mill._ -def sourceRootPath = pwd / 'src -def resourceRootPath = pwd / 'resources +// sourceRoot -> allSources -> classFiles +// | +// v +// resourceRoot ----> jar -def sourceRoot = T.source{ sourceRootPath } +def sourceRoot = T.sources{ pwd / 'src } -def resourceRoot = T.source{ resourceRootPath } +def resourceRoot = T.sources{ pwd / 'resources } -def allSources = T{ ls.rec(sourceRoot().path).map(PathRef(_)) } +def allSources = T{ sourceRoot().flatMap(p => ls.rec(p.path)).map(PathRef(_)) } def classFiles = T{ mkdir(T.ctx().dest) @@ -23,7 +25,7 @@ def classFiles = T{ PathRef(T.ctx().dest) } -def jar = T{ mill.modules.Jvm.createJar(Agg(resourceRoot().path, classFiles().path)) } +def jar = T{ Jvm.createJar(Loose.Agg(classFiles().path) ++ resourceRoot().map(_.path)) } def run(mainClsName: String) = T.command{ %%('java, "-cp", classFiles().path, mainClsName) @@ -116,13 +118,23 @@ within a `Module` body ```scala def sourceRootPath = pwd / 'src -def sourceRoot = T.source{ sourceRootPath } +def sourceRoots = T.sources{ sourceRootPath } ``` -`Source`s are defined using `T.source{ ... }`, taking an `ammonite.ops.Path` as -an input. A `Source` is a subclass of `Target[PathRef]`: this means that it's -build signature/`hashCode` depends not just on the path it refers to (e.g. -`foo/bar/baz`) but also the MD5 hash of the filesystem tree under that path. +`Source`s are defined using `T.source{ ... }`, taking one-or-more +`ammonite.ops.Path`s as arguments. A `Source` is a subclass of +`Target[Seq[PathRef]]`: this means that it's build signature/`hashCode` depends +not just on the path it refers to (e.g. `foo/bar/baz`) but also the MD5 hash of +the filesystem tree under that path. + +`T.source` also has an overload which takes `Seq[PathRef]`, to let you +override-and-extend source lists the same way you would any other `T{...}` +definition: + +```scala +def additionalSources = T.sources{ pwd / 'additionalSources } +def sourceRoots = T.sources{ super.sourceRoots() ++ additionalSources() } +``` ### Commands diff --git a/scalajslib/test/src/mill/scalajslib/HelloJSWorldTests.scala b/scalajslib/test/src/mill/scalajslib/HelloJSWorldTests.scala index 12102666..4043feff 100644 --- a/scalajslib/test/src/mill/scalajslib/HelloJSWorldTests.scala +++ b/scalajslib/test/src/mill/scalajslib/HelloJSWorldTests.scala @@ -36,7 +36,7 @@ object HelloJSWorldTests extends TestSuite { class BuildModuleUtest(scalaVersion0: String, sjsVersion0: String) extends BuildModule(scalaVersion0: String, sjsVersion0: String) { object test extends super.Tests { - override def sources = T.input{ Agg(PathRef(millSourcePath / 'src / 'utest)) } + override def sources = T.sources{ millSourcePath / 'src / 'utest } def testFramework: T[String] = "utest.runner.Framework" override def ivyDeps = Agg( ivy"com.lihaoyi:utest_sjs${scalaJSBinaryVersion()}_${Lib.scalaBinaryVersion(scalaVersion())}:0.6.3" @@ -48,7 +48,7 @@ object HelloJSWorldTests extends TestSuite { class BuildModuleScalaTest(scalaVersion0: String, sjsVersion0: String) extends BuildModule(scalaVersion0: String, sjsVersion0: String) { object test extends super.Tests { - override def sources = T.input{ Agg(PathRef(millSourcePath / 'src / 'scalatest)) } + override def sources = T.sources{ millSourcePath / 'src / 'scalatest } def testFramework: T[String] = "org.scalatest.tools.Framework" override def ivyDeps = Agg( ivy"org.scalatest:scalatest_sjs${scalaJSBinaryVersion()}_${Lib.scalaBinaryVersion(scalaVersion())}:3.0.4" diff --git a/scalalib/src/mill/scalalib/MiscModule.scala b/scalalib/src/mill/scalalib/MiscModule.scala index e4d8a8b0..8576e788 100644 --- a/scalalib/src/mill/scalalib/MiscModule.scala +++ b/scalalib/src/mill/scalalib/MiscModule.scala @@ -37,14 +37,13 @@ trait CrossModuleBase extends mill.Module{ } trait CrossScalaModule extends ScalaModule with CrossModuleBase{ outer => - override def sources = T.input{ + override def sources = T.sources{ super.sources() ++ CrossModuleBase.scalaVersionPaths(crossScalaVersion, s => millSourcePath / s"src-$s" ) - } trait Tests extends super.Tests { - override def sources = T.input{ + override def sources = T.sources{ super.sources() ++ CrossModuleBase.scalaVersionPaths(crossScalaVersion, s => millSourcePath / s"src-$s" ) } @@ -52,28 +51,24 @@ trait CrossScalaModule extends ScalaModule with CrossModuleBase{ outer => } trait SbtModule extends ScalaModule { outer => - override def sources = T.input{ - Agg( - PathRef(millSourcePath / 'src / 'main / 'scala), - PathRef(millSourcePath / 'src / 'main / 'java) - ) - } - override def resources = T.input{ Agg(PathRef(millSourcePath / 'src / 'main / 'resources)) } + override def sources = T.sources( + millSourcePath / 'src / 'main / 'scala, + millSourcePath / 'src / 'main / 'java + ) + override def resources = T.sources{ millSourcePath / 'src / 'main / 'resources } trait Tests extends super.Tests { override def millSourcePath = outer.millSourcePath - override def sources = T.input{ - Agg( - PathRef(millSourcePath / 'src / 'test / 'scala), - PathRef(millSourcePath / 'src / 'test / 'java) - ) - } - override def resources = T.input{ Agg(PathRef(millSourcePath / 'src / 'test / 'resources)) } + override def sources = T.sources( + millSourcePath / 'src / 'test / 'scala, + millSourcePath / 'src / 'test / 'java + ) + override def resources = T.sources{ millSourcePath / 'src / 'test / 'resources } } } trait CrossSbtModule extends SbtModule with CrossModuleBase{ outer => - override def sources = T.input{ + override def sources = T.sources{ super.sources() ++ CrossModuleBase.scalaVersionPaths( crossScalaVersion, @@ -83,7 +78,7 @@ trait CrossSbtModule extends SbtModule with CrossModuleBase{ outer => } trait Tests extends super.Tests { override def millSourcePath = outer.millSourcePath - override def sources = T.input{ + override def sources = T.sources{ super.sources() ++ CrossModuleBase.scalaVersionPaths( crossScalaVersion, diff --git a/scalalib/src/mill/scalalib/ScalaModule.scala b/scalalib/src/mill/scalalib/ScalaModule.scala index 92068487..03e27596 100644 --- a/scalalib/src/mill/scalalib/ScalaModule.scala +++ b/scalalib/src/mill/scalalib/ScalaModule.scala @@ -126,8 +126,8 @@ trait ScalaModule extends mill.Module with TaskModule { outer => def prependShellScript: T[String] = T{ "" } - def sources = T.input{ Agg(PathRef(millSourcePath / 'src)) } - def resources = T.input{ Agg(PathRef(millSourcePath / 'resources)) } + def sources = T.sources{ millSourcePath / 'src } + def resources = T.sources{ millSourcePath / 'resources } def generatedSources = T { Agg.empty[PathRef] } def allSources = T{ sources() ++ generatedSources() } -- cgit v1.2.3