Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SBT multiproject setup where a subproject's build files depend on unmanaged JARs

Scenario:

  • I want to develop a projectA written in Scala, which depends on projectB, also written in Scala.
  • It will often be the case that I need to modify projectB as well. Hence, I will have a local Git clone of projectB (as in my repository as a submodule).
  • Now projectA should pull the dependency on projectB directly from that cloned Git repository of projectB.

I now have the following setup, which is also available at GitHub: https://github.com/ComFreek/sbt-multi-project-question

| - .git
|
| - projectA
| | - src
| | - build.sbt
|
| - projectB (Git submodule)
| | - src
| | | - build.sbt
| | | - project
| | | - project.sbt
| | | - ...

In projectA/build.sbt tried:

unmanagedBase := baseDirectory.value / ".." / "projectB" / "deploy" / "lib"

lazy val projectB = RootProject(file("../projectB/src/project"))

lazy val projectA = Project(id = "projectA", base = file(".")).settings(
  name := "projectA",
  version := "0.1",
  scalaVersion := "2.12.8",
  scalacOptions in ThisBuild ++= Seq("-unchecked", "-deprecation")
).dependsOn(projectB)

However, it seems that projectB/src/build.sbt uses unmanaged libraries put into projectB/deploy/lib which cannot be found when sbt compile is run from within the scope of projectA - even with the unmanagedBase property set.

Concretely, you can reproduce it as follows:

  1. Open an SBT shell in projectA
  2. Run compile and get
    [IJ]sbt:projectA> compile
    [info] Compiling 13 Scala sources to ...\sbt-multi-project-question\projectB\src\project\target\scala-2.12\classes ...
    [error] ...\sbt-multi-project-question\projectB\src\project\File.scala:19:11: object tools is not a member of package scala
    [error]     scala.tools.nsc.io.File(f.toString).appendAll(strings:_*)
    [error]           ^
    [error] ...\sbt-multi-project-question\projectB\src\project\Utils.scala:31:14: object Keys is not a member of package sbt
    [error]   import sbt.Keys.packageBin
    [error]              ^
    [error] ...\sbt-multi-project-question\projectB\src\project\Utils.scala:33:36: not found: value Def
    [error]   def deployPackage(name: String): Def.Initialize[Task[Unit]] =
    [error]                                    ^
    [error] ...\sbt-multi-project-question\projectB\src\project\Utils.scala:34:5: not found: value packageBin
    [error]     packageBin in Compile map {jar => deployTo(Utils.deploy / name)(jar)}
    [error]     ^
    [error] ...\sbt-multi-project-question\projectB\src\project\Utils.scala:34:19: not found: value Compile
    [error]     packageBin in Compile map {jar => deployTo(Utils.deploy / name)(jar)}
    [error]                   ^
    [error] ...\sbt-multi-project-question\projectB\src\project\Utils.scala:45:39: type File is not a member of package sbt
    [error]   def deployTo(target: File)(jar: sbt.File): Unit = {
    [error]                                       ^
    [error] ...\sbt-multi-project-question\projectB\src\project\Utils.scala:39:36: not found: value Def
    [error]   def deployMathHub(target: File): Def.Initialize[Task[Unit]] =
    [error]                                    ^
    [error] ...\sbt-multi-project-question\projectB\src\project\Utils.scala:40:5: not found: value packageBin
    [error]     packageBin in Compile map {jar => deployTo(target)(jar)}
    [error]     ^
    [error] ...\sbt-multi-project-question\projectB\src\project\Utils.scala:40:19: not found: value Compile
    [error]     packageBin in Compile map {jar => deployTo(target)(jar)}
    [error]                   ^
    [error] ...\sbt-multi-project-question\projectB\src\project\Utils.scala:123:25: not found: type Logger
    [error]   def delRecursive(log: Logger, path: File): Unit = {
    [error]                         ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:8:44: not found: type Project
    [error] case class VersionSpecificProject(project: Project, excludes: Exclusions) {
    [error]                                            ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:13:48: not found: type Project
    [error]   def aggregate(projects: ProjectReference*) : Project = project.aggregate(excludes(projects.toList) :_*)
    [error]                                                ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:13:27: not found: type ProjectReference
    [error]   def aggregate(projects: ProjectReference*) : Project = project.aggregate(excludes(projects.toList) :_*)
    [error]                           ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:17:48: not found: type Project
    [error]   def dependsOn(projects: ProjectReference*) : Project = {
    [error]                                                ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:17:27: not found: type ProjectReference
    [error]   def dependsOn(projects: ProjectReference*) : Project = {
    [error]                           ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:18:47: not found: type ClasspathDep
    [error]     def toClassPathDep(p: ProjectReference) : ClasspathDep[ProjectReference] = p
    [error]                                               ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:18:27: not found: type ProjectReference
    [error]     def toClassPathDep(p: ProjectReference) : ClasspathDep[ProjectReference] = p
    [error]                           ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:23:59: not found: type Project
    [error]   def aggregatesAndDepends(projects: ProjectReference*) : Project = {
    [error]                                                           ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:23:38: not found: type ProjectReference
    [error]   def aggregatesAndDepends(projects: ProjectReference*) : Project = {
    [error]                                      ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:24:47: not found: type ClasspathDep
    [error]     def toClassPathDep(p: ProjectReference) : ClasspathDep[ProjectReference] = p
    [error]                                               ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:24:27: not found: type ProjectReference
    [error]     def toClassPathDep(p: ProjectReference) : ClasspathDep[ProjectReference] = p
    [error]                           ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:30:37: not found: type Project
    [error]   implicit def fromProject(project: Project) : VersionSpecificProject = VersionSpecificProject(project, Exclusions())
    [error]                                     ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:34:28: not found: type ProjectReference
    [error] case class Exclusions(lst: ProjectReference*) {
    [error]                            ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:31:61: not found: type Project
    [error]   implicit def toProject(vProject: VersionSpecificProject): Project = vProject.project
    [error]                                                             ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:35:68: not found: type ProjectReference
    [error]   private def javaVersion(versions: List[String], exclusions: List[ProjectReference]) : Exclusions = {
    [error]                                                                    ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:43:22: not found: type ProjectReference
    [error]   def :::(lst2: List[ProjectReference]) = Exclusions(lst.toList ::: lst2 : _*)
    [error]                      ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:39:25: not found: type ProjectReference
    [error]   def java7(exclusions: ProjectReference*): Exclusions = javaVersion(List("1.7", "7"), exclusions.toList)
    [error]                         ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:40:25: not found: type ProjectReference
    [error]   def java8(exclusions: ProjectReference*): Exclusions = javaVersion(List("1.8", "8"), exclusions.toList)
    [error]                         ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:41:25: not found: type ProjectReference
    [error]   def java9(exclusions: ProjectReference*): Exclusions = javaVersion(List("1.9", "9"), exclusions.toList)
    [error]                         ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:46:18: not found: value ScopeFilter
    [error]   def toFilter : ScopeFilter.ProjectFilter = {
    [error]                  ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:47:5: not found: value inAnyProject
    [error]     inAnyProject -- inProjects(lst :_*)
    [error]     ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:47:21: not found: value inProjects
    [error]     inAnyProject -- inProjects(lst :_*)
    [error]                     ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:51:28: not found: type ProjectReference
    [error]   private def equals(left: ProjectReference, right: ProjectReference) : Boolean = {
    [error]                            ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:51:53: not found: type ProjectReference
    [error]   private def equals(left: ProjectReference, right: ProjectReference) : Boolean = {
    [error]                                                     ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:61:25: not found: type ProjectReference
    [error]   def excludes(project: ProjectReference) : Boolean = lst.exists(equals(_, project))
    [error]                         ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:62:54: not found: type ProjectReference
    [error]   def apply(projects: List[ProjectReference]) : List[ProjectReference] = projects.filterNot(this.excludes)
    [error]                                                      ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:62:28: not found: type ProjectReference
    [error]   def apply(projects: List[ProjectReference]) : List[ProjectReference] = projects.filterNot(this.excludes)
    [error]                            ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:64:17: not found: type ProjectReference
    [error]   def map[B](f: ProjectReference => B) : Seq[B] = lst.map(f)
    [error]                 ^
    [error] ...\sbt-multi-project-question\projectB\src\project\VersionSpecificProject.scala:65:21: not found: type ProjectReference
    [error]   def foreach[U](f: ProjectReference => U) : Exclusions = {lst.foreach[U](f); this }
    [error]                     ^
    [error] 39 errors found
    [error] (ProjectRef(uri("file:/.../sbt-multi-project-question/projectB/src/project/"), "project") / Compile / compileIncremental) Compilation failed
    [error] Total time: 5 s, completed 04.03.2019, 10:10:34
    [IJ]sbt:projectA>
    

However, the following works:

  1. Open an SBT shell in projectB/src.
  2. Run compile
    Beware that it takes ~12 minutes on my machine and outputs a lot of warnings, but no errors.

Research. There are some resources explaining how to share unmanaged libraries between subprojects (e.g. 1 and 2 below), but none them seem to face the issue that the build setup (not only the code!) also depends on those unmanaged libraries.

  1. How to inherit unmanaged dependencies in submodules in sbt?
  2. How to have sbt multi-project builds configure setting for subprojects?)
like image 475
ComFreek Avatar asked Mar 04 '19 09:03

ComFreek


People also ask

How do we specify library dependencies in sbt?

The libraryDependencies key Most of the time, you can simply list your dependencies in the setting libraryDependencies . It's also possible to write a Maven POM file or Ivy configuration file to externally configure your dependencies, and have sbt use those external configuration files.

Which is the correct way to add dependencies in sbt file?

If you have JAR files (unmanaged dependencies) that you want to use in your project, simply copy them to the lib folder in the root directory of your SBT project, and SBT will find them automatically.

How do I run a jar file in sbt?

When you uses Simple Build Tool Command 'sbt package', it creates a jar file that includes the class files from your source code and also the content from your src/main/resources folder. Your project dependencies (JAR files in your project's lib folder or managed dependencies declared in build. sbt).

What does sbt clean do?

clean Deletes all generated files (in the target directory). compile Compiles the main sources (in src/main/scala and src/main/java directories). test Compiles and runs all tests. console Starts the Scala interpreter with a classpath including the compiled sources and all dependencies.


2 Answers

I managed to compile the projects with the following changes.

First, I got compilation errors when trying to compile the projectB @ b558245 revision, which is referenced in your GitHub project. I checked the latest tag, v15.0.0, and it compiled.

Second, in projectA/build.sbt, projectB should be defined as

lazy val projectB = RootProject(file("../projectB/src"))

../projectB/src/project is the builder project that builds projectB. It requires things in scala compiler and sbt, and thus produced the errors you saw when you tried to compile it directly.

Third, projectB failed to compile as a dependency of projectA. That's because, the Utils object (in projectB/src/project/Utils.scala) which was intended to refer to the layout of projectB, was initialized with a wrong directory (../projectA)

object Utils {
   /** MMT root directory */
   val root = File("..").canonical  // Got the wrong directory when compiled with projectA

So, we have to do some modifications to Utils.scala and it dependents, to ensure it always find the right position of projectB. Here is the patch to projectB to make it compile from projectA. Might not be the best solution, but it works on my laptop.

diff --git a/src/build.sbt b/src/build.sbt
index 059ef9c8e..b7495c8eb 100644
--- a/src/build.sbt
+++ b/src/build.sbt
@@ -1,10 +1,13 @@
 import scala.io.Source
 import sbt.Keys._
+import Utils.utils
+
+utils in ThisBuild := Utils((baseDirectory in src).value)

 // =================================
 // META-DATA and Versioning
 // =================================
-version in ThisBuild := {Source.fromFile("mmt-api/resources/versioning/system.txt").getLines.mkString.trim}
+version in ThisBuild := {Source.fromFile(baseDirectory.value / "mmt-api/resources/versioning/system.txt").getLines.mkString.trim}

 val now = {
   import java.text.SimpleDateFormat
@@ -106,7 +109,7 @@ def mmtProjectsSettings(nameStr: String) = commonSettings(nameStr) ++ Seq(

   unmanagedBase := baseDirectory.value  / "lib",

-  publishTo := Some(Resolver.file("file", Utils.deploy.toJava / " main")),
+  publishTo := Some(Resolver.file("file", utils.value.deploy.toJava / " main")),

   install := {},
   deploy := Utils.deployPackage("main/" + nameStr + ".jar").value
@@ -153,8 +156,12 @@ lazy val mmt = (project in file("mmt")).
   settings(
     exportJars := false,
     publish := {},
-    deploy := {
-      assembly in Compile map Utils.deployTo(Utils.deploy / "mmt.jar")
+    deploy := Def.taskDyn {
+      val jar = (assembly in Compile).value
+      val u = utils.value
+      Def.task {
+        Utils.deployTo(u.deploy / "mmt.jar")(jar)
+      }
     }.value,
     assemblyExcludedJars in assembly := {
       val cp = (fullClasspath in assembly).value
@@ -172,13 +179,13 @@ lazy val mmt = (project in file("mmt")).

 // MMT is split into multiple subprojects to that are managed independently.

-val apiJars = Seq(
+def apiJars(u: Utils) = Seq(
   "scala-compiler.jar",
   "scala-reflect.jar",
   "scala-parser-combinators.jar",
   "scala-xml.jar",
   "xz.jar",
-).map(Utils.lib.toJava / _ )
+).map(u.lib.toJava / _ )

 // The kernel upon which everything else depends. Maintainer: Florian
 lazy val api = (project in file("mmt-api")).
@@ -188,8 +195,8 @@ lazy val api = (project in file("mmt-api")).
   settings(
     scalacOptions in Compile ++= Seq("-language:existentials"),
     scalaSource in Compile := baseDirectory.value / "src" / "main",
-    unmanagedJars in Compile ++= apiJars,
-    unmanagedJars in Test ++= apiJars,
+    unmanagedJars in Compile ++= apiJars(utils.value),
+    unmanagedJars in Test ++= apiJars(utils.value),
   )


@@ -226,7 +233,7 @@ lazy val jedit = (project in file("jEdit-mmt")).
     resourceDirectory in Compile := baseDirectory.value / "src/resources",
     unmanagedJars in Compile ++= jeditJars map (baseDirectory.value / "lib" / _),
     deploy := Utils.deployPackage("main/MMTPlugin.jar").value,
-    install := Utils.installJEditJars
+    install := utils.value.installJEditJars
   )

 // MMT IntelliJ-Plugin. Maintainer: Dennis
@@ -299,7 +306,7 @@ lazy val concepts = (project in file("concept-browser")).
     libraryDependencies ++= Seq(
       "org.ccil.cowan.tagsoup" % "tagsoup" % "1.2"
     ),
-    unmanagedJars in Compile += Utils.lib.toJava / "scala-xml.jar"
+    unmanagedJars in Compile += utils.value.lib.toJava / "scala-xml.jar"
  )

 // =================================
@@ -389,7 +396,7 @@ lazy val oeis = (project in file("mmt-oeis")).
   dependsOn(planetary).
   settings(mmtProjectsSettings("mmt-oeis"): _*).
   settings(
-    unmanagedJars in Compile += Utils.lib.toJava / "scala-parser-combinators.jar"
+    unmanagedJars in Compile += utils.value.lib.toJava / "scala-parser-combinators.jar"
   )

 // =================================
@@ -416,11 +423,15 @@ lazy val lfcatalog = (project in file("lfcatalog")).
   settings(commonSettings("lfcatalog")).
   settings(
     scalaSource in Compile := baseDirectory.value / "src",
-    publishTo := Some(Resolver.file("file", Utils.deploy.toJava / " main")),
-    deployLFCatalog := {
-      assembly in Compile map Utils.deployTo(Utils.deploy / "lfcatalog" / "lfcatalog.jar")
+    publishTo := Some(Resolver.file("file", utils.value.deploy.toJava / " main")),
+    deployLFCatalog := Def.taskDyn {
+      val jar = (assembly in Compile).value
+      val u = utils.value
+      Def.task {
+        Utils.deployTo(u.deploy / "lfcatalog" / "lfcatalog.jar")(jar)
+      }
     }.value,
-    unmanagedJars in Compile += Utils.lib.toJava / "scala-xml.jar"
+    unmanagedJars in Compile += utils.value.lib.toJava / "scala-xml.jar"
   )

 // =================================
diff --git a/src/project/Utils.scala b/src/project/Utils.scala
index 2f9b94fd4..8f862666e 100644
--- a/src/project/Utils.scala
+++ b/src/project/Utils.scala
@@ -1,9 +1,84 @@
 import java.nio.file.Files
 import java.nio.file.StandardCopyOption._
+import sbt.Keys.packageBin
+import sbt._

 object Utils {
+
+  val utils = settingKey[Utils]("Utils")
+
+  def apply(base: java.io.File) = new Utils(File(base))
+
+  def error(s: String) = throw new Exception(s)
+
+  // ************************************************** deploy-specific code (see also the TaskKey's deploy and deployFull)
+
+  /*
+   * copies files to deploy folder
+   */
+  def deployTo(target: File)(jar: sbt.File): Unit = {
+    Files.copy(jar.toPath, target.toPath, REPLACE_EXISTING)
+    println("copied file: " + jar)
+    println("to file: " + target)
+  }
+
+  /**
+    * packages the compiled binaries and copies to deploy
+    */
+  def deployPackage(name: String) : Def.Initialize[Task[Unit]] = Def.taskDyn {
+    val j = (packageBin in Compile).value
+    val u = utils.value
+    Def.task {
+      deployTo(u.deploy / name)(j)
+    }
+  }
+
+  /**
+    * packages the compiled binaries and copies to deploy
+    */
+  def deployMathHub(target: File): Def.Initialize[Task[Unit]] =
+    packageBin in Compile map {jar => deployTo(target)(jar)}
+
+  // ************************************************** file system utilities
+
+  /** copy a file */
+  def copy(from: File, to: File) {
+    println(s"copying $from to $to")
+    if (!from.exists) {
+      error(s"error: file $from not found (when trying to copy it to $to)")
+    } else if (!to.exists || from.lastModified > to.lastModified) {
+      Files.copy(from.toPath, to.toPath, REPLACE_EXISTING)
+    } else {
+      println("skipped (up-to-date)")
+    }
+    println("\n")
+  }
+
+  /**
+    * Recursively deletes a given folder
+    * @param log
+    * @param path
+    */
+  def delRecursive(log: Logger, path: File): Unit = {
+    def delRecursive(path: File): Unit = {
+      path.listFiles foreach { f =>
+        if (f.isDirectory) delRecursive(f)
+        else {
+          f.delete()
+          log.debug("deleted file: " + path)
+        }
+      }
+      path.delete()
+      log.debug("deleted directory: " + path)
+    }
+    if (path.exists && path.isDirectory) delRecursive(path)
+    else log.warn("ignoring missing directory: " + path)
+  }
+}
+
+class Utils(base: File) {
    /** MMT root directory */
-   val root = File("..").canonical
+   val root = (base / "..").canonical
    /** source folder */
    val src = root / "src"
    /** MMT deploy directory */
@@ -21,33 +96,6 @@ object Utils {
    /** executes a shell command (in the src folder) */
    def runscript(command: String) = sys.process.Process(Seq(command), src.getAbsoluteFile).!!

-   def error(s: String) = throw new Exception(s)
-
-  // ************************************************** deploy-specific code (see also the TaskKey's deploy and deployFull)
-
- /**
-   * packages the compiled binaries and copies to deploy
-   */
-  import sbt.Keys.packageBin
-  import sbt._
-  def deployPackage(name: String): Def.Initialize[Task[Unit]] =
-    packageBin in Compile map {jar => deployTo(Utils.deploy / name)(jar)}
-
- /**
-   * packages the compiled binaries and copies to deploy
-   */
-  def deployMathHub(target: File): Def.Initialize[Task[Unit]] =
-    packageBin in Compile map {jar => deployTo(target)(jar)}
-
-  /*
-   * copies files to deploy folder
-   */
-  def deployTo(target: File)(jar: sbt.File): Unit = {
-    Files.copy(jar.toPath, target.toPath, REPLACE_EXISTING)
-    println("copied file: " + jar)
-    println("to file: " + target)
-  }
-

   // ************************************************** MathHub-specific code

@@ -79,7 +127,7 @@ object Utils {
       settings.get(killJEdit).foreach {x => runscript(x)}
      Thread.sleep(500)
       val fname = settings.get(jeditSettingsFolder).getOrElse {
-        error(s"cannot copy jars because there is no setting '$jeditSettingsFolder' in $settingsFile")
+        Utils.error(s"cannot copy jars because there is no setting '$jeditSettingsFolder' in $settingsFile")
         return
       }
       val jsf = File(fname) / "jars"
@@ -92,47 +140,10 @@ object Utils {
    }
    /** copy all jEdit jars to a directory */
    def copyJEditJars(to: File) {
-      copy(deploy/"mmt.jar", to/"MMTPlugin.jar")
+      Utils.copy(deploy/"mmt.jar", to/"MMTPlugin.jar")
       // all other jars are bundled with the above
       // val jEditDeps = List("scala-library.jar","scala-parser-combinators.jar","scala-reflect.jar","scala-xml.jar","tiscaf.jar")
       // jEditDeps.foreach {f => copy(deploy/"lib"/f, to/f)}
       // copy(deploy/"lfcatalog"/"lfcatalog.jar", to/"lfcatalog.jar")
    }
-
-
-  // ************************************************** file system utilities
-
-   /** copy a file */
-   def copy(from: File, to: File) {
-      println(s"copying $from to $to")
-      if (!from.exists) {
-         error(s"error: file $from not found (when trying to copy it to $to)")
-      } else if (!to.exists || from.lastModified > to.lastModified) {
-         Files.copy(from.toPath, to.toPath, REPLACE_EXISTING)
-      } else {
-         println("skipped (up-to-date)")
-      }
-      println("\n")
-   }
-
-  /**
-    * Recursively deletes a given folder
-    * @param log
-    * @param path
-    */
-  def delRecursive(log: Logger, path: File): Unit = {
-    def delRecursive(path: File): Unit = {
-      path.listFiles foreach { f =>
-        if (f.isDirectory) delRecursive(f)
-        else {
-          f.delete()
-          log.debug("deleted file: " + path)
-        }
-      }
-      path.delete()
-      log.debug("deleted directory: " + path)
-    }
-    if (path.exists && path.isDirectory) delRecursive(path)
-    else log.warn("ignoring missing directory: " + path)
-  }
 }
diff --git a/src/project/build.properties b/src/project/build.properties
index 9f782f704..1fc4b8093 100644
--- a/src/project/build.properties
+++ b/src/project/build.properties
@@ -1 +1 @@
-sbt.version=1.1.1
\ No newline at end of file
+sbt.version=1.2.8
\ No newline at end of file
diff --git a/src/travis.sbt b/src/travis.sbt
index 88fb446d3..a71be9d2e 100644
--- a/src/travis.sbt
+++ b/src/travis.sbt
@@ -2,6 +2,7 @@ import sbt._
 import sbt.Keys._
 import travis.Matrix._
 import travis.Config._
+import Utils.utils

 import scala.io.Source

@@ -86,11 +87,11 @@ travisConfig := {
 val genTravisYML = taskKey[Unit]("Print out travis.yml configuration")
 genTravisYML := {
   // read the prefix and the config
-  val prefix = Source.fromFile(Utils.src / "project" / "prefix.travis.yml").getLines.filter(!_.startsWith("##")).mkString("\n")
+  val prefix = Source.fromFile(utils.value.src / "project" / "prefix.travis.yml").getLines.filter(!_.startsWith("##")).mkString("\n")
   val config = travisConfig.value.serialize

   // and write it into .travis.yml
-  val outFile = Utils.root / ".travis.yml"
+  val outFile = utils.value.root / ".travis.yml"
   IO.write(outFile, prefix + "\n" + config)
   streams.value.log.info(s"Wrote $outFile")
 }
like image 61
thirstycrow Avatar answered Nov 15 '22 04:11

thirstycrow


Ok I think my first answer hit a dead-end;(.

Here a total new idea:

Add your project (projectA) as a submodule of projectB.

This is the structure:

enter image description here

The build.sbt from projectB needs a small adjustment:

// added for my project 
lazy val projectA = (project in file("projectA")).
  dependsOn(api)

If you can handle the git stuff - this may be the solution you are looking for;).

like image 22
pme Avatar answered Nov 15 '22 06:11

pme