Let me start by saying that I quite like SBT, in theory.
In practice, the threshold is steep, or maybe the documentation simply not suffucient to explain or ratify why things work as they do. Anyway, after having sunk 10+ hours into trying to set up a simple project in a manner that to me would seem intuitive, I’m left feeling frustrated and frankly quite stupid.
I will use my project as an example. What I am trying to achieve is the following structure
root-project
'- core
'- admin-web (Play-project, depends on core)
'- user-web (Play-project, depends on core)
I create this structure by issuing
mkdir root-project
cd root-project
mkdir core
activator new admin-web play-scala
activator new user-web play-scala
My reason for having this structure is I want the two web-artifacts to be individually deployable. Seems reasonable enough, I think.
Running sbt projects
gives the following output
[info] Loading global plugins from /Users/martin/.sbt/0.13/plugins
[info] Set current project to root-project (in build file:/Users/martin/dev/scala/root-project/)
[info] In file:/Users/martin/dev/scala/root-project/
[info] * root-project
SBT doesn’t look for sub-projects on its own. That’s ok I guess; I need to define the web project’s dependency on core
anyhow. Still, I would expect it to consider sub-projects part of the build by default.
I add a build.sbt-definition at root-project/build.sbt:
name := "my project"
scalaVersion := "2.11.2"
lazy val root = project in file(".")
lazy val core = project
lazy val `admin-web`, `user-web` = project.dependsOn(core)
And running SBT:
martin@mbp ~/dev/scala/root-project]$ sbt
[info] Loading global plugins from /Users/martin/.sbt/0.13/plugins
/Users/martin/dev/scala/root-project/user-web/build.sbt:5: error: not found: value PlayScala
lazy val root = (project in file(".")).enablePlugins(PlayScala)
^
sbt.compiler.EvalException: Type error in expression
at [stacktrace of death]
This is totally unintuitive to me. Both Play-projects have their own plugin dependencies declared in their corresponding projects/-directories but for some reason I am forced to pull it out to the root-project level. Why? Shouldn’t it be turtles all the way down?
So I copy the projects-folder up one level from one of the web projects (cp -R admin-web/project .
) and add the dependencies to my build.sbt
lazy val `admin-web`, `user-web` = project.dependsOn(core).enablePlugins(PlayScala)
Let’s try it again
[martin@mbp ~/dev/scala/root-project]$ sbt projects
[info] Loading global plugins from /Users/martin/.sbt/0.13/plugins
[info] Loading project definition from /Users/martin/dev/scala/root-project/project
[info] Set current project to my project (in build file:/Users/martin/dev/scala/root-project/)
[info] In file:/Users/martin/dev/scala/root-project/
[info] admin-web
[info] core
[info] * root
[info] user-web
Looks good! Let’s try running one of the projects
[martin@mbp ~/dev/scala/root-project]$ sbt 'admin-web/run'
[info] Loading global plugins from /Users/martin/.sbt/0.13/plugins
[info] Loading project definition from /Users/martin/dev/scala/root-project/project
[info] Set current project to my project (in build file:/Users/martin/dev/scala/root-project/)
[info] Updating {file:/Users/martin/dev/scala/root-project/}admin-web...
[info] Resolving core#core_2.11;0.1-SNAPSHOT ...
[warn] module not found: core#core_2.11;0.1-SNAPSHOT
[warn] ==== local: tried
[warn] /Users/martin/.ivy2/local/core/core_2.11/0.1-SNAPSHOT/ivys/ivy.xml
[warn] ==== public: tried
[warn] http://repo1.maven.org/maven2/core/core_2.11/0.1-SNAPSHOT/core_2.11-0.1-SNAPSHOT.pom
[warn] ==== Typesafe Releases Repository: tried
[warn] http://repo.typesafe.com/typesafe/releases/core/core_2.11/0.1-SNAPSHOT/core_2.11-0.1-SNAPSHOT.pom
[info] Resolving jline#jline;2.11 ...
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn] :: UNRESOLVED DEPENDENCIES ::
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn] :: core#core_2.11;0.1-SNAPSHOT: not found
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
sbt.ResolveException: unresolved dependency: core#core_2.11;0.1-SNAPSHOT: not found
Say what? Ok, so the core-directory is empty but the declaration is right there in my build.sbt. Why is SBT looking for this artifact on Maven and Ivy?
To get the ball rolling I decide to remove the dependency on the core-project for now, then
[martin@mbp ~/dev/scala/root-project]$ sbt 'admin-web/run'
[info] Loading global plugins from /Users/martin/.sbt/0.13/plugins
[info] Loading project definition from /Users/martin/dev/scala/root-project/project
[info] Set current project to my project (in build file:/Users/martin/dev/scala/root-project/)
[info] Updating {file:/Users/martin/dev/scala/root-project/}admin-web...
[info] Resolving jline#jline;2.11 ...
[info] Done updating.
--- (Running the application from SBT, auto-reloading is enabled) ---
[info] play - Listening for HTTP on /0:0:0:0:0:0:0:0:9000
(Server started, use Ctrl+D to stop and go back to the console...)
Looks good! A quick curl to make sure it’s up and running..
> curl localhost:9000
[error] application -
! Internal server error, for (GET) [/] ->
java.util.NoSuchElementException: None.get
at scala.None$.get(Option.scala:313) ~[scala-library-2.11.1.jar:na]
at scala.None$.get(Option.scala:311) ~[scala-library-2.11.1.jar:na]
at play.PlayReloader$$anon$1.reload(PlayReloader.scala:88) ~[na:na]
at play.core.ReloadableApplication$$anonfun$get$1.apply(ApplicationProvider.scala:122) ~[play_2.11-2.3.4.jar:2.3.4]
at play.core.ReloadableApplication$$anonfun$get$1.apply(ApplicationProvider.scala:120) ~[play_2.11-2.3.4.jar:2.3.4]
[warn] play - No application found at invoker init
In all fairness this is probably a Play oddity… but why does it have to be so complicated?
Now, I’ve thought about this post for a couple of days. I’m sorry if it’s written in an unpalatable manner but I’m not quite sure how to present the issue in a friendly manner while conveying my frustration and experience of new beginner’s intuition-failing-repeatedly.
I have delved deeper than this into SBT (and Play Framework) trying to get everything set up like I want, but it seems I’m always touching on a corner-case or plain oddity. Maybe I’m just not cut out to set up build definitions..
Finally, I have a list of a few humble questions/suggestions that may be totally outrageous according to the grander scheme of things SBT. If they are I would be happy to have someone explain why they are. I have been googling for weeks trying to figure this stuff out.
lazy val
declarations; inter-project dependencies would be specified using paths of project rather than name ((project in file("a")) dependsOn (project in file("b"))
(but it should maybe be called path rather than file);in ThisBuild
(maybe these should indeed be considered build settings and be separated from the project settings?)--
You received this message because you are subscribed to the Google Groups "simple-build-tool" group.
To unsubscribe from this group and stop receiving emails from it, send an email to simple-build-t...@googlegroups.com.
To post to this group, send email to simple-b...@googlegroups.com.
Visit this group at http://groups.google.com/group/simple-build-tool.
For more options, visit https://groups.google.com/d/optout.