From 90adc4b54ed7564139185fdc79f7c05c986dc2fc Mon Sep 17 00:00:00 2001 From: Tim Nieradzik Date: Tue, 25 Feb 2020 17:06:24 +0000 Subject: [PATCH] BuildTarget: Expose build targets' source paths --- src/main/scala/seed/cli/BuildTarget.scala | 44 ++++++++++++++++++- .../scala/seed/process/ProcessHelper.scala | 16 +++++++ .../generation/BloopIntegrationSpec.scala | 35 +++++++++++---- .../generation/util/TestProcessHelper.scala | 1 + test/custom-class-target-shared/build.toml | 22 ++++++++++ .../demo/Main.scala | 3 ++ .../utils/GenerateSources.scala | 16 +++++++ 7 files changed, 127 insertions(+), 10 deletions(-) create mode 100644 test/custom-class-target-shared/build.toml create mode 100644 test/custom-class-target-shared/demo/Main.scala create mode 100644 test/custom-class-target-shared/utils/GenerateSources.scala diff --git a/src/main/scala/seed/cli/BuildTarget.scala b/src/main/scala/seed/cli/BuildTarget.scala index 79b5e1c..e2aae59 100644 --- a/src/main/scala/seed/cli/BuildTarget.scala +++ b/src/main/scala/seed/cli/BuildTarget.scala @@ -28,7 +28,7 @@ object BuildTarget { case _ => List() }.distinct - val inheritedTargets = modules + val flattenedDeps = modules .flatMap { case util.Target.Parsed(module, Some(Left(platform))) => BuildConfig.collectModuleDepsBase(build, module.module, platform) @@ -36,7 +36,34 @@ object BuildTarget { case util.Target.Parsed(module, None) => module.name +: BuildConfig.collectModuleDeps(build, module.module) } - .flatMap(m => build(m).module.target.keys.toList.map(m -> _)) + + // Determine direct parents of build targets + type BuildTarget = (String, String) // module, target name + type ParentModule = String + val parentModules: Map[BuildTarget, List[ParentModule]] = + flattenedDeps + .flatMap { parent => + BuildConfig + .allTargets(build, parent) + .flatMap { + case (m, t) => BuildConfig.platformModule(build(m).module, t) + } + .flatMap(_.moduleDeps) + .flatMap( + module => + build(module).module.target.keys.toList + .map(target => (module, target) -> parent) + ) + } + .groupBy(_._1) + .mapValues(_.map(_._2)) + + val inheritedTargets: List[BuildTarget] = flattenedDeps + .flatMap( + module => + build(module).module.target.keys.toList + .map(target => (module, target)) + ) .distinct if (targets.nonEmpty) @@ -58,6 +85,16 @@ object BuildTarget { val modulePath = build(m).path val target = build(m).module.target(t) + val moduleSourcePaths = parentModules((m, t)).flatMap { module => + val targets = BuildConfig.allTargets(build, module) + targets + .flatMap { + case (m, t) => BuildConfig.platformModule(build(m).module, t) + } + .flatMap(_.sources) + .map(_.toAbsolutePath.toString) + } + target.`class` match { case Some(c) => val bloopName = @@ -68,6 +105,7 @@ object BuildTarget { customLog, customLog.info(_), Some(modulePath.toAbsolutePath.toString), + moduleSourcePaths, Some(buildPath.toAbsolutePath.toString) )(args: _*) @@ -83,6 +121,7 @@ object BuildTarget { ProcessHelper.runShell( modulePath, cmd, + moduleSourcePaths, buildPath.toAbsolutePath.toString, customLog, customLog.info(_) @@ -96,6 +135,7 @@ object BuildTarget { val process = ProcessHelper.runShell( modulePath, cmd, + moduleSourcePaths, buildPath.toAbsolutePath.toString, customLog, customLog.info(_) diff --git a/src/main/scala/seed/process/ProcessHelper.scala b/src/main/scala/seed/process/ProcessHelper.scala index db599ef..ec5cdd8 100644 --- a/src/main/scala/seed/process/ProcessHelper.scala +++ b/src/main/scala/seed/process/ProcessHelper.scala @@ -1,5 +1,6 @@ package seed.process +import java.io.File import java.nio.ByteBuffer import java.nio.file.Path @@ -65,6 +66,7 @@ object ProcessHelper { cwd: Path, cmd: List[String], modulePath: Option[String] = None, + moduleSourcePaths: List[String] = List(), buildPath: Option[String] = None, log: Log, onStdOut: String => Unit, @@ -84,6 +86,16 @@ object ProcessHelper { log.debug(s"Module path: ${Ansi.italic(mp)}", detail = true) } + pb.environment() + .put( + "MODULE_SOURCE_PATHS", + moduleSourcePaths.mkString(File.pathSeparatorChar.toString) + ) + log.debug( + s"Module source paths: ${moduleSourcePaths.map(Ansi.italic).mkString(", ")}", + detail = true + ) + buildPath.foreach { bp => pb.environment().put("BUILD_PATH", bp) log.debug(s"Build path: ${Ansi.italic(bp)}", detail = true) @@ -125,6 +137,7 @@ object ProcessHelper { log: Log, onStdOut: String => Unit, modulePath: Option[String] = None, + moduleSourcePaths: List[String] = List(), buildPath: Option[String] = None, verbose: Boolean = true )(args: String*): Process = @@ -132,6 +145,7 @@ object ProcessHelper { cwd, List("bloop") ++ args, modulePath, + moduleSourcePaths, buildPath, log, output => onStdOut(output), @@ -141,6 +155,7 @@ object ProcessHelper { def runShell( cwd: Path, command: String, + moduleSourcePaths: List[String] = List(), buildPath: String, log: Log, onStdOut: String => Unit @@ -149,6 +164,7 @@ object ProcessHelper { cwd, List("/bin/sh", "-c", command), None, + moduleSourcePaths, Some(buildPath), log, onStdOut diff --git a/src/test/scala/seed/generation/BloopIntegrationSpec.scala b/src/test/scala/seed/generation/BloopIntegrationSpec.scala index bb9ab54..b2c5e20 100644 --- a/src/test/scala/seed/generation/BloopIntegrationSpec.scala +++ b/src/test/scala/seed/generation/BloopIntegrationSpec.scala @@ -281,8 +281,8 @@ object BloopIntegrationSpec extends TestSuite[Unit] { def buildCustomTarget( name: String, expectFailure: Boolean = false - ): Future[List[String]] = { - val path = Paths.get(s"test/$name") + ): Future[Either[List[String], List[String]]] = { + val path = Paths.get("test", name) val config = BuildConfig.load(path, Log.urgent).get import config._ @@ -317,7 +317,7 @@ object BloopIntegrationSpec extends TestSuite[Unit] { if (expectFailure) RTS.unsafeRunToFuture(uio).failed.map { _ => assert(lines.nonEmpty) - lines.toList + Left(lines.toList) } else { RTS.unsafeRunSync(uio) @@ -327,20 +327,38 @@ object BloopIntegrationSpec extends TestSuite[Unit] { TestProcessHelper .runBloop(buildPath)("run", "demo") .map { x => - assertEquals(x.split("\n").count(_ == "42"), 1) Files.delete(generatedFile) assertEquals(lines.toList, List()) - List() + Right(x.split("\n").toList) } } } testAsync("Build project with custom class target") { _ => - buildCustomTarget("custom-class-target").map(_ => ()) + buildCustomTarget("custom-class-target").map( + lines => assertEquals(lines.right.get.count(_ == "42"), 1) + ) + } + + testAsync( + "Build project with custom class target (shared by multiple modules)" + ) { _ => + buildCustomTarget("custom-class-target-shared").map( + lines => + assertEquals( + lines.right.get.map(_.split("test/").last), + List( + "custom-class-target-shared/template1", + "custom-class-target-shared/template2" + ) + ) + ) } testAsync("Build project with custom command target") { _ => - buildCustomTarget("custom-command-target").map { _ => + buildCustomTarget("custom-command-target").map { lines => + assertEquals(lines.right.get.count(_ == "42"), 1) + val path = tempPath .resolve("custom-command-target") .resolve(".bloop") @@ -368,7 +386,8 @@ object BloopIntegrationSpec extends TestSuite[Unit] { log => // Must indicate correct position assert( - log.exists(_.contains("[2:41]: not found: value invalidIdentifier")) + log.left.get + .exists(_.contains("[2:41]: not found: value invalidIdentifier")) ) ) } diff --git a/src/test/scala/seed/generation/util/TestProcessHelper.scala b/src/test/scala/seed/generation/util/TestProcessHelper.scala index 63e81fd..7616993 100644 --- a/src/test/scala/seed/generation/util/TestProcessHelper.scala +++ b/src/test/scala/seed/generation/util/TestProcessHelper.scala @@ -32,6 +32,7 @@ object TestProcessHelper { cwd, cmd, None, + List(), None, Log.urgent, out => sb.append(out + "\n") diff --git a/test/custom-class-target-shared/build.toml b/test/custom-class-target-shared/build.toml new file mode 100644 index 0000000..8a6d25f --- /dev/null +++ b/test/custom-class-target-shared/build.toml @@ -0,0 +1,22 @@ +[project] +scalaVersion = "2.13.0" + +[module.utils.jvm] +sources = ["utils"] + +[module.utils.target.gen-sources] +class = ["utils:jvm", "GenerateSources"] +await = true + +# `template1` and `template2` share the code generator (`utils`) +[module.template1.jvm] +moduleDeps = ["utils"] +sources = ["template1"] + +[module.template2.jvm] +moduleDeps = ["utils"] +sources = ["template2"] + +[module.demo.jvm] +moduleDeps = ["template1", "template2"] +sources = ["demo"] diff --git a/test/custom-class-target-shared/demo/Main.scala b/test/custom-class-target-shared/demo/Main.scala new file mode 100644 index 0000000..d725fc0 --- /dev/null +++ b/test/custom-class-target-shared/demo/Main.scala @@ -0,0 +1,3 @@ +object Main { + def main(args: Array[String]): Unit = Generated.modulePaths.foreach(println) +} diff --git a/test/custom-class-target-shared/utils/GenerateSources.scala b/test/custom-class-target-shared/utils/GenerateSources.scala new file mode 100644 index 0000000..eb503c6 --- /dev/null +++ b/test/custom-class-target-shared/utils/GenerateSources.scala @@ -0,0 +1,16 @@ +import java.io.File +import java.nio.file.{Files, Paths, StandardOpenOption} + +object GenerateSources { + def main(args: Array[String]): Unit = { + val modulePath = sys.env("MODULE_PATH") + val moduleSourcePaths = + sys.env("MODULE_SOURCE_PATHS").split(File.pathSeparatorChar) + val generatedPath = + Paths.get(modulePath).resolve("demo").resolve("Generated.scala") + val pathsScala = moduleSourcePaths.mkString("\"", "\", \"", "\"") + val output = s"object Generated { val modulePaths = List($pathsScala) }" + + Files.write(generatedPath, output.getBytes) + } +}