Skip to content

Commit

Permalink
Refactor build path logic
Browse files Browse the repository at this point in the history
Currently, if tmpfs is disabled, `BuildTarget` uses an output path
that is different from the generated Bloop project. Introduce
`PathUtil` to unify the build path logic across the entire code base
and write test cases.

Also, change the path of the linked Bloop artefacts from
`build/bloop/` to `build/`. When packaging modules, place `dist/`
under the same build path.

Further changes:
- Idea: Move `normalisePath()` to `PathUtil`
- `Cli`: Improve help
  • Loading branch information
tindzk committed Jul 15, 2019
1 parent cf69777 commit 0776771
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 81 deletions.
10 changes: 5 additions & 5 deletions src/main/scala/seed/Cli.scala
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ ${underlined("Usage:")} seed [--build=<path>] [--config=<path>] <command>
${italic("link")} Link module(s)
${italic("buildEvents")} Subscribe to build events on Seed server
${italic("update")} Check library dependencies for updates
${italic("package")} Create JAR package for given module and its dependent modules
Also sets the main class from the configuration file
${italic("package")} Create JAR package for given module and its dependencies
Also sets the main class from the build file
Specify --libs to copy all library dependencies for distribution

${bold("Parameters:")}
Expand All @@ -176,7 +176,7 @@ ${underlined("Usage:")} seed [--build=<path>] [--config=<path>] <command>
${bold("Command:")} ${underlined("build")} [--connect[=${webSocketDefaultConnection.format}]] [--watch] [--tmpfs] <modules>
${italic("--connect")} Run build command on remote Seed server
${italic("--watch")} Build upon source changes (cannot be combined with ${Ansi.italic("--connect")})
${italic("<modules>")} One or multiple space-separated modules. The syntax of a module is: ${italic("<name>")} or ${italic("<name>:<platform>")}
${italic("<modules>")} One or multiple space-separated modules. The syntax of a module is: ${italic("<name>")} or ${italic("<name>:<target>")}
${italic("Examples:")}
- app Compile all available platforms of module ${Ansi.italic("app")}
- app:js Only compile JavaScript platform of module ${Ansi.italic("app")}
Expand Down Expand Up @@ -205,8 +205,8 @@ ${underlined("Usage:")} seed [--build=<path>] [--config=<path>] <command>

${bold("Command:")} ${underlined("package")} [--tmpfs] [--libs] [--output=<path>] <module>
${italic("--tmpfs")} Read build directory in tmpfs
${italic("--libs")} Copy libraries and reference them in the JAR's class path.
${italic("--output")} Output path (default: ${Ansi.italic("dist/")})
${italic("--libs")} Copy libraries and reference them in the JAR's class path
${italic("--output")} Output path (default: ${Ansi.italic("build/dist/")})
${italic("<module>")} Module to package""")
}

Expand Down
8 changes: 3 additions & 5 deletions src/main/scala/seed/cli/BuildTarget.scala
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package seed.cli

import java.nio.file.{Path, Paths}
import java.nio.file.Path

import seed.Log
import seed.config.BuildConfig
import seed.generation.util.PathUtil
import seed.model
import seed.process.ProcessHelper

import scala.concurrent.{Await, Future}
import scala.concurrent.duration.Duration

import scala.concurrent.ExecutionContext.Implicits.global

object BuildTarget {
Expand Down Expand Up @@ -46,9 +46,7 @@ object BuildTarget {

val allTargets = (targets ++ inheritedTargets).distinct

val buildPath =
if (tmpfs) BuildConfig.tmpfsPath(projectPath, log).resolve("bloop")
else Paths.get("build")
val buildPath = PathUtil.buildPath(projectPath, tmpfs, log)

log.info(s"Build path: $buildPath")

Expand Down
14 changes: 7 additions & 7 deletions src/main/scala/seed/cli/Package.scala
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package seed.cli

import java.nio.file.{Files, Path, Paths}
import java.nio.file.{Files, Path}

import scala.collection.JavaConverters._

import seed.artefact.{ArtefactResolution, Coursier}
import seed.cli.util.Ansi
import seed.config.BuildConfig
import seed.generation.Bloop
import seed.generation.util.PathUtil
import seed.model
import seed.model.Build.JavaDep
import seed.model.Config
Expand All @@ -24,9 +23,10 @@ object Package {
packageConfig: Cli.PackageConfig
): Unit = {
val tmpfs = packageConfig.tmpfs || seedConfig.build.tmpfs
val buildPath = Bloop.getBuildPath(projectPath, tmpfs)
val buildPath = PathUtil.buildPath(projectPath, tmpfs)
val bloopBuildPath = buildPath.resolve("bloop")
val platform = JVM
val outputPath = output.getOrElse(Paths.get("dist"))
val outputPath = output.getOrElse(buildPath.resolve("dist"))

build.module.get(module) match {
case None => Log.error(s"Module ${Ansi.italic(module)} does not exist")
Expand All @@ -35,9 +35,9 @@ object Package {
List(module) ++ BuildConfig.collectJvmModuleDeps(build, resolvedModule)
).map { name =>
if (BuildConfig.isCrossBuild(build.module(name)))
buildPath.resolve(name + "-" + platform.id)
bloopBuildPath.resolve(name + "-" + platform.id)
else
buildPath.resolve(name)
bloopBuildPath.resolve(name)
}

val notFound = paths.find(p => !Files.exists(p))
Expand Down
7 changes: 0 additions & 7 deletions src/main/scala/seed/config/BuildConfig.scala
Original file line number Diff line number Diff line change
Expand Up @@ -290,11 +290,4 @@ object BuildConfig {
def collectJvmJavaDeps(build: Build, module: Module): List[JavaDep] =
module.javaDeps ++ module.jvm.map(_.javaDeps).getOrElse(List()) ++
jvmModuleDeps(module).flatMap(m => collectJvmJavaDeps(build, build.module(m)))

def tmpfsPath(projectPath: Path, log: Log = Log): Path = {
val name = projectPath.toAbsolutePath.getFileName.toString
log.info("Build path set to tmpfs")
log.warn(s"Please ensure that there is no other project with the name ${Ansi.italic(name)} that also compiles to tmpfs")
Paths.get("/tmp").resolve("build-" + name)
}
}
49 changes: 22 additions & 27 deletions src/main/scala/seed/generation/Bloop.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ package seed.generation

import java.nio.file.{Files, Path, Paths}

import seed.config.BuildConfig.{collectJsClassPath, collectJsDeps, collectJvmClassPath, collectJvmScalaDeps, collectJvmJavaDeps, collectNativeClassPath, collectNativeDeps}
import seed.artefact.{Coursier, ArtefactResolution}
import seed.config.BuildConfig.{collectJsClassPath, collectJsDeps, collectJvmClassPath, collectJvmJavaDeps, collectJvmScalaDeps, collectNativeClassPath, collectNativeDeps}
import seed.artefact.{ArtefactResolution, Coursier}
import seed.cli.util.Ansi
import seed.model.Build.{Module, Project}
import seed.model.Platform.{JVM, JavaScript, Native}
import seed.model.{Artefact, Build, Resolution}
import seed.Log
import seed.config.BuildConfig
import seed.generation.util.PathUtil

object Bloop {
import bloop.config.Config
Expand Down Expand Up @@ -366,6 +367,7 @@ object Bloop {
def buildModule(projectPath: Path,
bloopPath: Path,
buildPath: Path,
bloopBuildPath: Path,
build: Build,
resolution: Coursier.ResolutionResult,
compilerResolution: List[Coursier.ResolutionResult],
Expand All @@ -379,25 +381,25 @@ object Bloop {
moduleOutputPath(buildPath, module.native, name + ".run")

writeJsModule(build, if (!isCrossBuild) name else name + "-js",
projectPath, bloopPath, buildPath, Some(jsOutputPath),
projectPath, bloopPath, bloopBuildPath, Some(jsOutputPath),
module.copy(scalaDeps = collectJsDeps(build, module)),
collectJsClassPath(buildPath, build, module),
collectJsClassPath(bloopBuildPath, build, module),
module.js, build.project, resolution, compilerResolution,
jsdom = module.js.exists(_.jsdom),
emitSourceMaps = module.js.exists(_.emitSourceMaps),
test = false)
writeJvmModule(build, if (!isCrossBuild) name else name + "-jvm",
projectPath, bloopPath, buildPath,
projectPath, bloopPath, bloopBuildPath,
module.copy(
scalaDeps = collectJvmScalaDeps(build, module),
javaDeps = collectJvmJavaDeps(build, module)
),
collectJvmClassPath(buildPath, build, module),
collectJvmClassPath(bloopBuildPath, build, module),
module.jvm, build.project, resolution, compilerResolution, test = false)
writeNativeModule(build, if (!isCrossBuild) name else name + "-native",
projectPath, bloopPath, buildPath, Some(nativeOutputPath),
projectPath, bloopPath, bloopBuildPath, Some(nativeOutputPath),
module.copy(scalaDeps = collectNativeDeps(build, module)),
collectJvmClassPath(buildPath, build, module),
collectJvmClassPath(bloopBuildPath, build, module),
module.native, build.project, resolution, compilerResolution, test = false)

module.test.foreach { test =>
Expand All @@ -406,35 +408,35 @@ object Bloop {
val emitSourceMaps = test.js.exists(_.emitSourceMaps)

writeJsModule(build, if (!isCrossBuild) name else name + "-js",
projectPath, bloopPath, buildPath, None,
projectPath, bloopPath, bloopBuildPath, None,
module.copy(
sources = test.sources,
scalaDeps = collectJsDeps(build, module) ++ test.scalaDeps,
targets = targets
),
collectJsClassPath(buildPath, build, module),
collectJsClassPath(bloopBuildPath, build, module),
test.js, build.project, resolution, compilerResolution, jsdom,
emitSourceMaps, test = true)

writeNativeModule(build, if (!isCrossBuild) name else name + "-native",
projectPath, bloopPath, buildPath, None,
projectPath, bloopPath, bloopBuildPath, None,
module.copy(
sources = test.sources,
scalaDeps = collectNativeDeps(build, module) ++ test.scalaDeps,
targets = targets
),
collectNativeClassPath(buildPath, build, module),
collectNativeClassPath(bloopBuildPath, build, module),
test.native, build.project, resolution, compilerResolution, test = true)

writeJvmModule(build, if (!isCrossBuild) name else name + "-jvm",
projectPath, bloopPath, buildPath,
projectPath, bloopPath, bloopBuildPath,
module.copy(
sources = test.sources,
scalaDeps = collectJvmScalaDeps(build, module) ++ test.scalaDeps,
javaDeps = collectJvmJavaDeps(build, module) ++ test.javaDeps,
targets = targets
),
collectJvmClassPath(buildPath, build, module),
collectJvmClassPath(bloopBuildPath, build, module),
test.jvm, build.project, resolution, compilerResolution, test = true)

if (isCrossBuild)
Expand All @@ -443,7 +445,7 @@ object Bloop {
name = name + "-test",
bloopPath = bloopPath,
dependencies = targets.map(t => name + "-" + t.id + "-test"),
classesDir = buildPath,
classesDir = bloopBuildPath,
classPath = List(),
sources = List(),
scalaCompiler = None,
Expand All @@ -458,7 +460,7 @@ object Bloop {
name = name,
bloopPath = bloopPath,
dependencies = module.targets.map(t => name + "-" + t.id),
classesDir = buildPath,
classesDir = bloopBuildPath,
classPath = List(),
sources = List(),
scalaCompiler = None,
Expand All @@ -467,34 +469,27 @@ object Bloop {
platform = None)
}

def getBuildPath(projectPath: Path, tmpfs: Boolean): Path = {
val baseBuildPath =
if (tmpfs) BuildConfig.tmpfsPath(projectPath)
else projectPath.resolve("build")

baseBuildPath.resolve("bloop")
}

def build(projectPath: Path,
build: Build,
resolution: Coursier.ResolutionResult,
compilerResolution: List[Coursier.ResolutionResult],
tmpfs: Boolean): Unit = {
val bloopPath = projectPath.resolve(".bloop")
val buildPath = getBuildPath(projectPath, tmpfs)
val buildPath = PathUtil.buildPath(projectPath, tmpfs)
val bloopBuildPath = buildPath.resolve("bloop")

Log.info(s"Build path: ${Ansi.italic(buildPath.toString)}")

if (!Files.exists(bloopPath)) Files.createDirectory(bloopPath)
if (!Files.exists(buildPath)) Files.createDirectories(buildPath)
if (!Files.exists(bloopBuildPath)) Files.createDirectories(bloopBuildPath)

import scala.collection.JavaConverters._
Files.newDirectoryStream(bloopPath, "*.json").iterator().asScala
.foreach(Files.delete)

build.module.foreach { case (name, module) =>
Log.info(s"Building module ${Ansi.italic(name)}...")
buildModule(projectPath, bloopPath, buildPath, build,
buildModule(projectPath, bloopPath, buildPath, bloopBuildPath, build,
resolution, compilerResolution, name, module)
}

Expand Down
34 changes: 8 additions & 26 deletions src/main/scala/seed/generation/Idea.scala
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
package seed.generation

import java.nio.file.{Files, Path, Paths}
import java.nio.file.{Files, Path}

import scala.collection.JavaConverters._
import org.apache.commons.io.FileUtils
import seed.config.BuildConfig.{collectJsDeps, collectJsModuleDeps, collectJvmJavaDeps, collectJvmModuleDeps, collectJvmScalaDeps, collectNativeDeps, collectNativeModuleDeps}
import seed.artefact.{Coursier, ArtefactResolution}
import seed.artefact.{ArtefactResolution, Coursier}
import seed.cli.util.Ansi
import seed.generation.util.IdeaFile
import seed.generation.util.{IdeaFile, PathUtil}
import seed.model.{Build, Resolution}
import seed.model.Build.Module
import seed.model.Platform.{JVM, JavaScript, Native}
import seed.Log
import seed.config.BuildConfig
import seed.generation.util.PathUtil.normalisePath

object Idea {
val ModuleDir = "$MODULE_DIR$"
Expand Down Expand Up @@ -42,22 +43,6 @@ object Idea {
.toFile, xml, "UTF-8")
}

def normalisePath(pathVariable: String, root: Path)(path: Path): String = {
val canonicalRoot = root.toFile.getCanonicalPath
val canonicalPath = path.toFile.getCanonicalPath

val rootElems = canonicalRoot.split("/").toList
val pathElems = canonicalPath.split("/").toList
val common = pathElems.zip(rootElems).takeWhile { case (a, b) => a == b }

if (common.length == 1) canonicalPath
else {
val levels = rootElems.length - common.length
val relativePath = (0 until levels).map(_ => "../").mkString
pathVariable + "/" + relativePath + pathElems.drop(common.length).mkString("/")
}
}

def createModule(build : Build,
root : Path,
name : String,
Expand Down Expand Up @@ -430,13 +415,10 @@ object Idea {
resolution: Coursier.ResolutionResult,
compilerResolution: List[Coursier.ResolutionResult],
tmpfs: Boolean): Unit = {
val baseBuildPath =
if (tmpfs) BuildConfig.tmpfsPath(projectPath)
else Paths.get("build")

val buildPath = baseBuildPath.resolve("idea")
val buildPath = PathUtil.buildPath(projectPath, tmpfs)
val ideaBuildPath = buildPath.resolve("idea")

Log.info(s"Build path: ${Ansi.italic(buildPath.toString)}")
Log.info(s"Build path: ${Ansi.italic(ideaBuildPath.toString)}")

val ideaPath = outputPath.resolve(".idea")
val modulesPath = ideaPath.resolve("modules")
Expand All @@ -460,7 +442,7 @@ object Idea {

val modules = build.module.toList.flatMap { case (name, module) =>
buildModule(
projectPath, buildPath, ideaPath, modulesPath, librariesPath, build,
projectPath, ideaBuildPath, ideaPath, modulesPath, librariesPath, build,
compilerResolution, resolution, name, module)
}

Expand Down
34 changes: 34 additions & 0 deletions src/main/scala/seed/generation/util/PathUtil.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package seed.generation.util

import java.nio.file.{Path, Paths}

import seed.Log
import seed.cli.util.Ansi

object PathUtil {
def tmpfsPath(projectPath: Path, log: Log = Log): Path = {
val name = projectPath.toAbsolutePath.getFileName.toString
log.info("Build path set to tmpfs")
log.warn(s"Please ensure that there is no other project with the name ${Ansi.italic(name)} that also compiles to tmpfs")
Paths.get("/tmp").resolve("build-" + name)
}

def buildPath(projectPath: Path, tmpfs: Boolean, log: Log = Log): Path =
if (tmpfs) tmpfsPath(projectPath) else projectPath.resolve("build")

def normalisePath(pathVariable: String, root: Path)(path: Path): String = {
val canonicalRoot = root.toFile.getCanonicalPath
val canonicalPath = path.toFile.getCanonicalPath

val rootElems = canonicalRoot.split("/").toList
val pathElems = canonicalPath.split("/").toList
val common = pathElems.zip(rootElems).takeWhile { case (a, b) => a == b }

if (common.length == 1) canonicalPath
else {
val levels = rootElems.length - common.length
val relativePath = (0 until levels).map(_ => "../").mkString
pathVariable + "/" + relativePath + pathElems.drop(common.length).mkString("/")
}
}
}
Loading

0 comments on commit 0776771

Please sign in to comment.