Add folder to unmanagedResourceDirectories only for "sbt run" - scala

I am new to Scala and sbt (0.13.13) - I started using Play Framework (2.5.10) a few weeks ago.
My question:
I added
unmanagedResourceDirectories in Compile += baseDirectory( _ / "devstuff" ).value
to the build.sbt. This is because I want all the files (these are not source files) in devstuff on the classpath (only) during developing my app (when running sbt run). Also, when editing a file in devstuff the application gets restarted/re-compiled. That's fine and that's what I want for development.
However when running sbt dist, sbt stage, universal:packageZipTarball, etc. - when I create the final distribution package - I do not want that this folder gets included. The folder only contains stuff needed during developing, but I don't want it packaged in my final package.
How can I achieve that the myfolder is in unmanagedResourceDirectories for sbt run (and also sbt test) but not for creating the distribution packages?

According to the sbt documentation you should be able to use the Runtime scope to achieve this:
unmanagedResourceDirectories in Runtime += baseDirectory( _ / "devstuff" ).value

Related

Scala "not found: object com" - should i really add entry in build.sbt if there are no other dependencies?

I have created basic Scala Play application with https://www.playframework.com/getting-started play-scala-seed. This project compiles and runs with sbt run. But I have another Scala project that compiles and runs and which I have submitted to my local Ivy repository with command sbt publishLocal. This other project was saved at C:\Users\tomr\.ivy2\local\com.agiintelligence\scala-isabelle_2.13\master-SNAPSHOT as a result of this command.
Then I imported (exactly so - imported, no just opened) my Play project in IntelliJ and I used Project - Open Module Settings - Project Settings - Libraries to add com.agiintelligence jar from my ivy2 location. After such operations IntelliJ editor recognizes com.agiintelligence classes. That is fine.
But when I am trying to run my Play application with sbt run, I experience the error message not found: object com that is exactly when compiling import com.agiintelligence line in my Scala controller file of Play application.
Of course - such error has been reported and resolved with, e.g. object play not found in scala application
But that solution suggests to append build.sbt file. My build.sbt file is pretty bare:
name := """agiintelligence"""
organization := "com.agiintelligence"
version := "1.0-SNAPSHOT"
lazy val root = (project in file(".")).enablePlugins(PlayScala)
scalaVersion := "2.13.5"
libraryDependencies += guice
libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "5.0.0" % Test
// Adds additional packages into Twirl
//TwirlKeys.templateImports += "com.skaraintelligence.controllers._"
// Adds additional packages into conf/routes
// play.sbt.routes.RoutesKeys.routesImport += "com.skaraintelligence.binders._"
My Play application contains (as can bee seen from the IntelliJ project pane) some tens of 'external libraries' (it shows my com.agiintelligence jar as well), but why should I add my own ivy2 library in build.sbt file if no other libraries are listed here? What is different with my library? It is on my computer, in the repository as expected already?
Of course, I can try to add it build.sbt and issue sbt update and see what happens, but I can not understand this logic? Can someone explain it and provide some clue to intelligible solution of my error message?
My Play application contains (as can bee seen from the IntelliJ project pane) some tens of 'external libraries'
Those are probably just transitive dependencies of your Play dependency, that is why sbt downloaded all of them and put them in your classpath so you could use them without you needing to tell it about them; because the pom of Play already did.
It is not that the build tool or the IDE magically added all those dependencies for you because they read your mind and magically understood you wanted them. And that for some reason the magic stopped working for your own library.
Why it is not sufficient to list it Project-Setting--External Libraries in IntelliJ only?
That is sufficient for the IDE to work, but not for the build tool. The build tool is independent of the IDE; it doesn't know about it. sbt just knows about the dependencies you configured in your definition file.
Even more, you should always configure your dependencies on your build tool and then import that in the IDE; rather than the opposite. IDEs are graphical tools, so their state can not be committed, can not be shared, can not keep track of changes, can not be used in CI / CD environments; additionally, different teammates may want to use different IDEs.
I resolved the error message by adding line in build.sbt file
libraryDependencies += "de.unruh" %% "scala-isabelle" % "master-SNAPSHOT"
and by subsequent run of sbt update.
Error is solved, but the main question still stand - why I had to do this? Why there are tens of dependencies that are not listed in build.sbt and why should I list my dependency in build.sbt and why it is not sufficient to list it Project-Setting--External Libraries in IntelliJ only?
OK, comment by #Luis_Miguel_Mejía_Suárez gave the explanation, that comment is the actual and expected answer to my question.

Scala's build.sbt not recognised by IntelliJ

I'm having an issue where my build.sbt file is not being picked up properly using IntelliJ (Ultimate 2020.2.3). I create a new Scala sbt project using the IntelliJ wizard (file > new > project > scala / sbt) and add a new dependancy to the buid.sbt file but when I try to import it into one of my class files, IntelliJ will not compile my project due to a dependancy issue.
The sbt tool window picks up the external dependancies but my project "external dependancies" doesn't contain the library at all, even after I refresh the project. Also, my build.sbt file has a bunch of errors in it like it's not being recognised properly by IntelliJ but I've installed the Scala plugin so I don't know what else I could do?
Here you can see that I've added the org.slf4j dependancy into my build.sbt; It's picked up by the sbt tool window (on the right) but not by my project (on the left)
When I hover over the libraryDependencies in the build.sbt file it doesn't seem to recognise the sbt syntax:
I cannot import the library into my class file and the project wont build:
I'm new to Scala and I'm simply trying to create a basic hello world project but I can't seem to get past this frustrating issue.
You can try first to create an SBT project manually in some directory. build.sbt alone would be enough.
Then run sbt in that directory to see that SBT shell works properly. Try some commands like sbt compile, sbt run with some helloworld app. When you create helloworld app mind the directory structure where you put it, i.e.: src/main/scala/HelloWorld.scala.
If all that works go to IntelliJ and import/open project from there - select build.sbt.
When you create or import SBT project from IntelliJ it takes a while to bootstrap everything and download compiler, etc. Just leave it until it's done. Same goes for first time compilation when the compiler needs to be compiled :).
To setup a sample project you can issue these shell commands:
mkdir untitled
cd untitled/
echo 'name := "untitled"
version := "0.1"
scalaVersion := "2.13.3"
libraryDependencies ++= Seq(
"org.slf4j" % "slf4j-simple" % "1.7.26",
)
' > build.sbt
mkdir -p src/main/scala/
echo 'object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello World")
}
}
' > src/main/scala/HelloWorld.scala
sbt run
If there are not issues with these steps then import build.sbt into IntelliJ.
I was finally able to get past this issue. I'm not 100% sure what solved it in the end unfortunately but disabling a bunch of plugins I wasn't using seemed to fix the issue for me.
I suspect it may have been the Gradle plugin since I saw some errors in the idea.log file but after re-enabling the Gradle plugin to test everything is still working so not sure.

How do you delete a directory before running in ScalaTest/sbt/Intellij?

I am currently using ScalaTest 3.0.1 for my Scala 2.11.8 project, with sbt 0.13.18 as the build tool. The IDE is Intellij.
The project is a Spark project, and I'm using a temp directory at root/temp/ for checkpoints and warehousing. When I run the tests multiple times the checkpoints keep getting added to, eventually reaching a very large size. I want to keep the checkpoints around after the test runs so they can be used for verification, but I would like to delete them before the next run.
How can you accomplish this using sbt and ScalaTest in Intellij?
I've been looking into setting up an sbt clean with my temp directory in build.sbt but I can't seem to get it to delete the directory, and reading the documentary hints it will only delete the files sbt has created, so I abandoned that idea.
I'm currently looking into setting up my ScalaTest set up to have a BeforeAll event which will delete the directory, but I'm not sure this is the correct approach and I've been having issues getting it to work.
Based on https://stackoverflow.com/a/48659771/5205022 clean can include temp directory
cleanFiles += baseDirectory.value / "temp"
Another option is to create a custom task that cleans temp, for example using better-files
lazy val deleteTestTemp = taskKey[Unit]("Delete test temp directory")
deleteTestTemp := {
import better.files._
val temp = (baseDirectory.value / "temp").toScala
if (temp.exists) temp.delete()
}
where project/plugins.sbt contains
libraryDependencies += "com.github.pathikrit" %% "better-files" % "3.9.1"
we could clean and then test like so
deleteTestTemp;test

How do I use shared configurations across SBT (Play) multi-projects?

I have several SBT 0.13 / Play 2.2 projects (websites). They are all multi-module as they share some common functionality. This makes their project configuration files both complex and almost identical, but not quite.
I would like to be able to share as much as possible of these configuration files across the projects (frequent play updates makes keeping 5+ websites up to date a royal pain, not to mention all the almost-identical-but-evolving dependency lists across the projects).
build.properties and plugins.sbt are identical across projects and can be overwritten by a simple script. Great.
Build.scala is trickier - I would like to introduce a shared base class like so:
abstract class MyBuildBase extends Build { ... }
that in Build.scala do:
object ApplicationBuild extends MyBuildBuild { ... }
In order for this to make any sense at all, MyBuildBase.scala needs to be shared across projects. This can be done with svn:external, which operates on directories. Which means I need to somehow make this shared directory accessible when Build.scala is compiled (otherwise sbt complains loudly).
Reading http://www.scala-sbt.org/0.13.0/docs/Detailed-Topics/Classpaths.html and http://www.scala-sbt.org/0.13.0/docs/Getting-Started/Full-Def.html it seems like this should be possible.
However, it is exceptionally unclear to me what to actually put in the project/project/Build.scala file to actually achieve this - I can't find an example of "an sbt build file that's intended to build an sbt build file and include some extra source files in the build".
Any suggestions?
What you probably want to do is create a plugin, or shared library.
You can make an sbt project with a build like follows:
build.sbt
sbtPlugin := true
organization := "you"
name := "common-build"
version := "1.0"
Then create in src/main/scala your abstract class "MyBuildBase". Release this project as an sbt plugin.
Then in your other projects, you can use this as a library/plugin. In project/plugins.sbt add:
addSbtPlugin("you" % "common-build" % "1.0")
And this will resolve your common build library when building your build.
If you need more information, look up more about sbt plugins and ignore the part about making something that extends a Plugin. Plugins are just libraries versioned with sbt's version number and your own. You should be able to put whatever code you want in there to share between builds.
Note: in 2016, Build.scala is deprecated for Build.sbt.
Here is the new (Dec. 2016) multi-module with App Scala sbt template by Michael Lewis.
Usage
sbt new lewismj/sbt-template.g8
You can then run:
sbt compile
sbt publish-local
sbt assembly
It is based on Scala SBT template (Library)
This giter8 template will write SBT build files for a Scala library.

Create Simple Project SBT 0.10.X

(This is a follow up to sbt not creating projects correctly. The question wasn't answered.)
Basically, that question says "I don't know how to create a project under the new sbt. With the old one, I just ran sbt in a new folder and there was a guided wizard that led me through the setup."
The accepted answer does not explain how to create a new project, it just points to the documentation, which also doesn't explicitly say how to create a new project -- only how to write a build.sbt file.
So I tried first writing a build.sbt and then running sbt in the directory with the build.sbt file, but I still don't see a src directory to work with.
Could someone post a simple step-by-step (I'm assuming there are like 3 steps at most) guiding how to create a new project under sbt 0.10.X?
I found the answer I was looking for at this webpage: Scala 2.9.1, sbt 0.10 and ScalaTest step-by-step.
The high-level steps are:
mkdir my_project make a folder for your project
Create a simple my_project/build.sbt file, e.g.:
name := "A Project"
version := "0.1"
scalaVersion := "2.9.1"
libraryDependencies ++= Seq(
"org.scalatest" %% "scalatest" % "1.6.1" % "test"
)
Create a file my_project/src/main/scala/HelloWorld.scala, where you create all the directories you need as you go (e.g. create the directory structure src/main/scala/)
object Main extends App {
Console.println("Hello World!")
}
Execute your sbt commands: e.g. sbt run
I am surprised that noone gave another solution which is the closest to the old way (as mentioned by #dsg) to create a simple project in sbt:
Just run sbt in your project directory, then issue the following commands in the sbt REPL:
> set name := "MyProject"
> set version := "1.0"
> set scalaVersion := "2.9.0"
> session save
> exit
Granted, it is only mildly useful as it will just create the build.sbt file (enough to make it a proper sbt project) with the corresponding properties set, and you might as well create the file by hand (I usually prefer to do so myself). It won't create the src directory either.
Just a few days ago np (new project) plugin to sbt was released. It intended to dealt exactly with that problem:
Initial release. Provides a minimal interface for generating new sbt
projects via,... sbt.
Basic use is to install the plugin globally and start up a new project
with
$ sbt
$ np name:my-project org:com.mypackage version:0.1.0-SNAPSHOT
This will generate a simple build.sbt project for you along with the
standard project directory structure for main and test sources.
For more advanced usage, see the project's readme for more info
You can use https://github.com/n8han/giter8 to generate project layout using various templates
In newer versions of sbt, you can just install sbteclipse:
// ~/.sbt/plugins/build.sbt
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.1.0")
then from sbt's console you can run:
eclipse with-source=true
In version 0.10.x I think this post can help you:
http://dcsobral.blogspot.fr/2011/06/very-quick-guide-to-project-creation-on.html
I've been using https://github.com/ymasory/sbt-prototype skeleton. See also my other answer.
It was the first one that just worked and I've been a quite happy with it since then.
Don't forget the recent sbt 0.13.3 new command:
Example:
First, you need sbt’s launcher version 0.13.13 or above.
Normally the exact version for the sbt launcher does not matter because it will use the version specified by sbt.version in project/build.properties; however for new sbt’s launcher 0.13.13 or above is required as the command functions without a project/build.properties present.
Next, run:
$ sbt new eed3si9n/hello.g8
....
name [hello]:
scala_version [2.11.8]:
Template applied in ./hello
This ran the template eed3si9n/hello.g8 using Giter8, prompted for values for “name” and “scala_version” (which have defaults “hello” and “2.11.8”, which we accepted hitting [Enter]), and created a build under ./hello.
Check out the GitHub repo Scala SBT Template. In particular the buildt.sbt file.
Just clone the repo, go to that directory, then call the sbt command.
$ git clone git://github.com/dph01/scala-sbt-template.git
$ cd scala-sbt-template
$ ./sbt
From inside of sbt, you can type run to execute provided code. Have fun!
An alternative way to generate the project structure using Intellij:
Create the directory for the project and include there a basic sbt file. You just need to specify the project name.
name := "porjectName"
With Intellij import the project. During the process check the options "Use auto-import" and "Create directories for empty content roots automatically"
That will create for you the basic skeleton for the sbt project.