Imports from external libraries in views - scala

I'm trying to use classes from a dependant project in my views, but it seems the scala compiler isn't able to pick it up.
The project is a sibling of the play project:
workspace/lib
workspace/play-project
But I get an error when compiling the project:
#import lib.TheClass
Error:
[error] scala-2.9.1/src_managed/main/views/html/index.template.scala:28: not found: value lib
[error] _display_ {import lib.TheClass
How can I set up a project dependency for the scale compiler?
I found the following related SO questions, but they seem to talk about projects stored in central repositories:
Play 2.0 Framework external Model in Template
Dependency Management with Play 2.0 Applications

You have to declare the dependency on the lib project in your sbt configuration. There is a guide in the sbt wiki. First you declare your lib project.
lazy val lib = Project(id = "lib",
base="../lib/")
Then you define the main project and let it depend on the lib project.
lazy val play = Project(id = "play-app",
base = file(".")) dependsOn(lib)

Related

How to make scalajs project depend on a subproject?

I use a case class from a sub project and receive error: Referring to non-existent at runtime
In build.sbt, I have:
lazy val scalaJsProject = (project in file("scala-project/"))
.dependsOn(modelProject)
I guess dependsOn does not work for scalaJs?
I followed instruction here https://github.com/scala-js/scalajs-cross-compile-example to create crossProject. And put all models into shared folder of crossProject. And it recoginizes both in JVM and JS project.

Add plugins under a same project in sbt

I'm trying to build a Scala project aggregated by multiple projects, one of which is an sbt plugin. I would like to use this plugin in another subproject under the same parent project, but I don't quite understand how to do this.
My "build.sbt" in the project root is like this:
lazy val plugin = project
.in(file("sbt-Something"))
.dependsOn(lib)
.settings(common: _*)
.settings(name := "My plugin",
sbtPlugin := true)
lazy val examples = project
.in(file("examples"))
.dependsOn(lib, plugin)
.settings(common: _*)
.settings(name := "Examples")
How to add the plugin as a plugin to project examples?
I don't think you can have a plugin at the same "level" that project which is using it.
If you think of it, the plugin must be available before the compilation of the project that is using it. This is because it may, for example modify the build settings, which would influence the way the project is built.
If you want to keep your plugin within your project you can do so by declaring a project in the project/project directory.
$YOUR_PROJECT_ROOT/project/build.sbt
lazy val plugin = project
.in(file("sbt-plugin"))
.dependsOn(lib)
.settings(name := "My plugin", sbtPlugin := true)
lazy val lib = project.in(file("lib"))
lazy val root = project.in(file(".")).dependsOn(plugin)
Then you can put your code to sbt-plugin directory, and your shared library code to the lib folder.
In your normal build you can reference the shared library and the plugin.
$YOUR_PROJECT_ROOT/build.sbt
val lib = ProjectRef(file("project/lib"), "lib")
val root = project.in(file(".")).dependsOn(lib).enablePlugins(MyPlugin)
Please note that maybe it would be better to keep the shared library as a separate project, because I think this setup may be a bit tricky. For example if you change something in the shared library the main project should recompile and should use new code. The plugin however will only use new code after issuing the reload command on the project.
If you want to share settings between the projects you can check answers to How to share version values between project/plugins.sbt and project/Build.scala?

Compiling my first DSL in Delite

I am trying to follow the tutorial on compiling a simple DSL using Delite+LMS. I compiled LMS and Delite succesfully. Now, following this tutorial closely: http://stanford-ppl.github.io/Delite/myfirstdsl.html I run into problems when I try to build my profiling dsl. It seems that the compiler cannot find the delite-collection classes:
felix#felix-UX32VD:~/Documents/phd/delite/Delite$ sbt compile
Loading /home/felix/sbt/bin/sbt-launch-lib.bash
[info] Loading project definition from /home/felix/Documents/phd/delite/Delite/project
[info] Set current project to delite (in build file:/home/felix/Documents/phd/delite/Delite/)
[info] Compiling 5 Scala sources to /home/felix/Documents/phd/delite/Delite/dsls/profiling/target/scala-2.10/classes...
[error] /home/felix/Documents/phd/delite/Delite/dsls/profiling/src/example/profiling/Profile.scala:7: object DeliteCollection is not a member of package ppl.delite.framework.datastruct.scala
[error] import ppl.delite.framework.datastruct.scala.DeliteCollection
[error] ^
[error] /home/felix/Documents/phd/delite/Delite/dsls/profiling/src/example/profiling/Profile.scala:69: not found: type ScalaGenProfileArrayOps
[error] with ScalaGenDeliteOps with ScalaGenProfileOps with ScalaGenProfileArrayOps
[error]
^
Does someone have some insights to what I'm doing wrong?
From SBT manual:
Library dependencies can be added in two ways:
unmanaged dependencies are jars dropped into the lib directory
managed dependencies are configured in the build definition and downloaded
automatically from repositories (through Apache Ivy, exactly like Maven)
In any case, adding code inside a framework project is a bad idea, because you will have to change the build process (for example, adding an extra module). In addition, you might have to recompile all the code of the framework and this would be very slow.
The right way to make your code depending on a framework is:
Reference the library as a managed dependency available in some kind of repository (best solution).
Copy the jar inside the lib folder of your project and add it as an unmanaged dependency.
Since apparently Delite is not available on any Ivy repo, the best approach is to clone the Git repo and publish it locally. See http://www.scala-sbt.org/release/docs/Detailed-Topics/Publishing.html
Publishing Locally
The publishLocal command will publish to the local
Ivy repository. By default, this is in ${user.home}/.ivy2/local. Other
projects on the same machine can then list the project as a
dependency. For example, if the SBT project you are publishing has
configuration parameters like:
name := 'My Project'
organization := 'org.me'
version :=
'0.1-SNAPSHOT'
Then another project can depend on it:
libraryDependencies += "org.me" %% "my-project" % "0.1-SNAPSHOT"

Play Framework project with sub-projects, how to make SBT work correctly

I've started off with a single Play Framework 2.x project (Scala) that I've been working on.
This has now reached a point where I'd like to break down the project into a number of sub and 'sibiling' projects. Specifically - I'm writing a Play REST API service that I wish to also build a Javascript project alongside of like an 'SDK' for the service.
I 'think' this is possible using SBT - but I'm stuck and the documentation seems thin on the ground in this area.
I'd like to have three projects underneath one 'main' project that is nothing but a container for the other three and where the main build files are.
This would be something like:
main
service (play + scala)
common files (scala only)
sdk (javascript)
When I try and run 'play' to build the hierachy I've got - I get variations on the following error:
[error] Not a valid command: play (similar: apply, last, alias)
[error] Not a valid project ID: play
[error] Expected ':' (if selecting a configuration)
[error] Not a valid key: play (similar: playConf, play-conf, playReload)
[error] play
[error] ^
When I have a Build.scala (in the 'main' project) look like this:
object ApplicationBuild extends Build {
val appName = "my service"
val appVersion = "1.0-SNAPSHOT"
// tell the couchbase infrastructure to use the built in logger - which will get redirected to our main logger
System.setProperty("net.spy.log.LoggerImpl", "net.spy.memcached.compat.log.SunLogger")
// project dependencies
val appDependencies = Seq(
...
)
val common = Project("common", file("common"))
val service = play.Project(appName, appVersion, appDependencies, path = file("service")).settings(
scalacOptions ++= Seq("-feature") // turn on normal warnings and feature warnings with scalac
).dependsOn(common)
val sdk = Project("sdk", file("sdk"))
val base = Project("base", file("."))
.dependsOn(service)
.dependsOn(sdk)
.dependsOn(common)
}
The folder hierachy I've got is:
\
\service
\common
\sdk
\project
\target
build.sbt
Am I on the right track and can someone help me out syntax wise, or am I approaching the problem in completely the wrong way and play cannot be used like that? (use sbt directly?).
I think your base project should look like this:
val base = Project("base", file("."))
.aggregate(service,sdk,common)
First, a project is defined by declaring a lazy val of type Project because you may encounter initialization problems.
lazy val base = Project("base", file(".")).aggregate(sdk, service, common)
If you have SBT installed and configured classpath for SBT, try sbt command in the terminal. The current project should be set to "base" automatically.
The reason I suggested you to try sbt command instead of play command is: If the root project is not a PlayProject then the play build script will fail.

Custom SBT Build file to not compile views in Play 2.0

I have a Play 1.2.4 app that I'm trying to migrate to Play 2.0.2. I currently have a structure in Play 1.2.4 like this:
Website depends on Frontend
Catalog depends on Frontend
Frontend depends on (a routes file being defined when compiling views)
Where Frontend contains a bunch of views that are used by both Website and Catalog. This decision was made because Catalog is really lightweight and is used for quick development of Frontend. While Website has a lot more code in it and takes longer to code/compile/test.
I cannot setup these projects as subprojects like is decribed here http://www.playframework.org/documentation/2.0/SBTSubProjects because there is a circular dependency. The views use Asset.of which requires the routes file to be defined. But the Website and Catalog each define a routes file and Play 2.0 does not support routes files from dependencies (this is supposed to come in Play 2.1). And in the Catalog the views are referenced in the controllers.
I was thinking that if I could change my build logic for Frontend to not try to compile the views, but instead just publish an artifact containing them then I could have Website and Catalog add those artifacts to the views it defines and build them together. This would break the circular dependency I have.
Has anyone else done this before? I'm too much of a beginner with SBT to even know if this is possible. Could anyone tell me how I could modify the Build.scala file to stop compiling the views but export them instead? Would it make sense for me to make this an SBT plugin? Of if you know of any code that shows how to do this another could you post a link to the code?
I used the play new to create two projects. The LDAPInterface was an interface to LDAP that we wanted to use across several applications. The Second Project was the Access manger. In the AccessManager\project\build.scala file, we structured it this way in order to use the LDAPInterface project. In eclipse, we just included the LDAPInterface in the project dependency section so we could debug. You could always compile a jar file and include that, but ... not as good if you want to drill down on project dependencies within eclipse. If we used play.Project it recognized it as a web project. If we just used Project it seemed to think it was a console application.
import sbt._
import Keys._
import play.Project._
object LDAPInterface {
lazy val depProject = RootProject(file("../LDAPInterface"))
}
object ApplicationBuild extends Build {
val appName = "AccessManager"
val appVersion = "1.0-SNAPSHOT"
val appDependencies = Seq(
//Add your project dependencies here,
javaCore,
javaJdbc,
javaEbean
)
// lazy val root = Project(id = "AccessManager",
// base = file(".")
//).dependsOn(LDAPInterface.depProject)
lazy val main = play.Project(appName, appVersion, appDependencies).settings(
// Add your own project settings here
).dependsOn(LDAPInterface.depProject)
}