Problems with SBT dependencies in Intellij Idea - scala

This is a problem that is really getting on my nerves. I'm writing proofs for the Welder proof assistant. I was doing so without the help of an IDE and following an SBT-based building approach. This is the build file:
name := "proofs"
scalaVersion := "2.11.8"
lazy val welder = RootProject(uri("git://github.com/epfl-lara/welder.git#2b9dd10a7a751777cc9cda543ce888294113c0b1"))
lazy val root = (project in file(".")).dependsOn(welder)
I tried to bring my project into an Intellij Idea project. However, while doing so, the IDE won't recognize the imports of the external library:
import inox._
How can I solve this issue?
Edit
I stress that the compile errors are produced in the files from Welder
Here is the welder project/Build.scala file
import sbt._
object WelderBuild extends Build {
lazy val root = Project("root", file(".")) dependsOn(inoxProject)
lazy val inoxProject = RootProject(uri("git://github.com/epfl-lara/inox.git#53ea4533a957050bd6a968d5a340890bd54998a5"))
}

See my answer to your other question and the issue on the Scala plugin issue tracker.
Renaming the modules and manually adding a dependency from the welder-root to the inox-root module will solve the compile path issue, but the build will still fail because one of the project uses source generators, which are not supported in IDEA directly.
Instead, enable the "use sbt for build and import" option in the sbt preferences:

Related

sbt subProject: dependsOn

I have the following build.sbt with two sub projects. Everything compiles and runs fine.
One is a thin scala play project. dataextractor has a lot of util classes I want to call in the play project.
However, the configurarion below still leads to the following compilation error:
[error]
/Users/foo.bar/_vws/com.corp.enablement.scripts/sirf_extract_serve/tools_sirf_server/app/corp/tools/es_result_server/service/SystemInitializer.scala:6:21:
object dataextraction is not a member of package corp.tools [error]
import corp.tools.dataextraction.providers.confluence
This is my first sbt multi-project. Advice would be genuinley appreciated
lazy val tools_dataextractor = (project in file("tools_dataextractor")).settings(
Defaults.itSettings,
libraryDependencies += scalatest % "it,test",
name := "corp_tools_dataextractor",
version := "0.1",
mainClass in Compile := Some("corp.tools.ExtractionStartUp")
)
lazy val tools_sirf_server = (project in file("tools_sirf_server")).settings(
).enablePlugins(PlayScala).dependsOn(tools_dataextractor)
lazy val root = (project in file("."))
.aggregate(tools_dataextractor, tools_sirf_server)
The configuration looks good.
2 possibilities what the problem might be:
You are in a sbt-console and haven't reloaded the console after you changed build.sbt
You work with Intellij and did not reload the sbt projects
If this does not help - adjust your question with the steps you take.
OK, the answer is neophyte error.
I had a build.sbt in the root and a build.sbt in each sub project (which is permissible).
Everything will built fine.... Until I started adding dependencies from one sub-project to another. In this case, the super build.sbt "dependsOn" is ignored and compilation errors occur.
Side note, the main reason for keeping sub-project build.sbt was simply laziness. It took half a day to get everything working in a single build.sbt at the root level. However, it is defintiely worth the effort.

Setting a module project in Scala as an sbt project?

I'd like to know how to convert a regular scala project into an sbt project. I've tried manually creating an sbt file on the root directory, correctly implemented, but Intellij still doesn't recognize this as a sbt project, i.e, it won't show me in the "View -> Tool Windows" the "SBT" option.
How should I go about this? What I'm actually attempting to do is to create an empty project with multiple (independent) modules.
From what I've gathered there seems to be no way to add a module directly with sbt support, am I right?
Thanks
Here is an example of a multi-project build. The root project "aggregates" them all in case you want to compile them all together or package them all together, etc. The "coreLibrary" project depends on the code of "coreA" and "coreB".
import sbt.Keys._
import sbt._
name := "MultiProject"
lazy val root = project.in(file(".")).aggregate(coreA, coreB, coreLibrary)
lazy val coreA = Project("CoreA", file("core-a")).settings(
organization := "org.me",
version := "0.1-SNAPSHOT"
)
lazy val coreB = Project("CoreB", file("core-b")).settings(
organization := "org.me",
libraryDependencies += "org.apache.kafka" %% "kafka" % "0.8.2-beta",
version := "0.3-SNAPSHOT"
)
lazy val coreLibrary = Project("UberCore", file("core-main")).dependsOn(coreA, coreB).settings(
organization := "org.me",
version := "0.2-SNAPSHOT"
)
You can (for example) compile each project from the command line:
>sbt CoreB/compile
Or you can do this interactively:
>sbt
>project CoreB
>compile
I recommend you to use a single multiple-module SBT project. sbt is a great build tool for scala, you can do a lot of things with sbt, including checking out from the repository one module and built it.
sbt
projects
project <helloProject>
Actually, this feature allows multiple people to work on the same project in parallel. Please take a look at this: http://www.scala-sbt.org/0.13.5/docs/Getting-Started/Multi-Project.html.

Using a custom sbt plugin

I've created a new scala project and written an AutoPlugin underneath it in a src/main/scala/com/company/plugin directory and a corresponding namespace. The plugin code is a cut and paste of HelloPlugin3 from [1], however I have changed the names.
Then, in a second sbt project I've updated the project/plugins.sbt file to include my new Hello World plugin. This second project has other 'business code' in. When I run sbt in that second project, the plugin is resolved and I've tested that by deleting the jar from underneath the ~/.ivy/local/... and then reloading the project and witnessing sbt complain that it can't find the plugin. When I publishLocal my plugin project again, that error goes away.
So I'm happy that the plugin is resolved and the jar file is not empty because I have checked its contents.
However, when I do an sbt> about my custom plugin isn't listed and the command I was expecting to be available isn't. ("[error] Not a valid command: hello"). But the other plugin I list in plugins.sbt (io.spray sbt-revolver) does appear in the output.
Both the plugin project and the second project have scalaVersion := "2.10.3" specified in their build.sbt files.
I'm using sbt 0.13.6. Interestingly, and perhaps related, is the sbt command plugins is not apparently valid in this project either, although it works just fine in the plugin project.
What extra step am I missing to make the command available to my second project? How do I check to see if I've got some particularly messed up sbt config happening?
For convenience, the plugin code is below, but as mentioned, it's a copy from the link underneath it.
package com.company.plugin
import sbt._
import Keys._
object HelloPlugin extends AutoPlugin {
object autoImport {
val greeting = settingKey[String]("greeting")
}
import autoImport._
override def trigger = allRequirements
override lazy val buildSettings = Seq(
greeting := "Hi",
commands += helloCommand)
lazy val helloCommand =
Command.command("hello") { (state: State) =>
println("fred")
state
}
}
Edit:
The build.sbt for the plugin project as as follows;
sbtPlugin := true
scalaVersion := "2.10.3"
organization := "com.company"
name := "name"
version := "0.0.1-SNAPSHOT"
The only other file I've created in this project is the .scala file for the plugin itself.
[1] http://www.scala-sbt.org/release/docs/Plugins.html
The problem ended up being with the project/build.properties of the project trying to use the plugin. This file set the sbt version to 0.13.1, which for some reason cases both my plugin and the sbt plugins command to not work.
Changing the value to 0.13.6 made all the problems go away.

What is the difference between build.sbt and build.scala?

I started to learn Scala and almost in every tutorial I see a build.sbt file which describes project settings. But now I have installed giter8 and created a project from template. And generated project from template missed build.sbt file, but it have build.scala (which seems used for same purposes, but it is more flexible).
So what is the difference between build.sbt and build.scala?
Which is more preferred and why?
To give a brief example, this build.sbt:
name := "hello"
version := "1.0"
is a shorthand notation roughly equivalent to this project/Build.scala:
import sbt._
import Keys._
object Build extends Build {
lazy val root = Project(id = "root", base = file(".")).settings(
name := "hello",
version := "1.0"
)
}
The .sbt file can also include vals, lazy vals, and defs (but not objects and classes).
See the SBT document called ".scala build definition", particularly the section "Relating build.sbt to Build.scala".
Consider a .scala build definition if you're doing something complicated where you want the full expressiveness of Scala.
Update July 2016 (3 years later)
Build.scala is officially deprecated in sbt 0.13.12
The Build trait is deprecated in favor of the .sbt format
PR 2530 implements that deprecation.
"Appendix: .scala build definition" has been updated.
When .sbts are being compiled, they are before that sort of merged with the .scala files inside project directory. They can't be used in recursive tasks, that is, you can't customize sbt from sbt, for example. For more detailed information, consider reading related section is sbt documentation: http://www.scala-sbt.org/release/docs/Getting-Started/Basic-Def.html#sbt-vs-scala-definition

How to get Intellij to use dependencies from SBT scala

I am trying to figure out how idea will recognize thrid party dependencies when using SBT. When I use the sbt plugin gen-idea it seems to download all the necessary dependencies which get put into my ~/.ivy/ directory as expected. How can intellij use these deps?
EDIT:
One thing I noticed is if I make a new idea project instead of just a module then this works? Any idea why this would be? I would like to be able to have multiple sbt modules in the same project.
The sbt-idea plugin works with multi-module sbt project. We have been using it since somewhere around sbt-0.10.0, and currently are at sbt-0.11.2. It seems like you have the dependency part of the build file set up ok, so here's an example of how we do the project setup from a full specification Build.scala file:
object Vcaf extends Build {
import Resolvers._
import Dependencies._
import BuildSettings._
lazy val vcafDb = Project(
id = "vcaf-db",
base = file("./vcaf-db"),
dependencies = Seq(),
settings = buildSettings ++ /* proguard */ SbtOneJar.oneJarSettings ++ Seq(libraryDependencies := dbDeps, resolvers := cseResolvers)
)
lazy val vcaf = Project(
"vcaf",
file("."),
dependencies = Seq(vcafDb),
aggregate = Seq(vcafDb),
settings = buildSettings ++ Seq(libraryDependencies := vcafDeps, resolvers := cseResolvers) ++ webSettings
)
}
In the example, the vcaf-db project is in the a folder within the vcaf project folder. The vcaf-db project does not have it's own build.sbt or Build.scala file. You'll notice that we are specifying libraryDependencies for each project, which may or may not be your missing link.
As ChrisJamesC mentioned, you need to do a "reload" from within SBT (or exit sbt and come back in) to pick up changes to your build definition. After the project is reloaded, you should be able to do a "gen-idea no-classifiers no-sbt-classifiers" and get an intellij project that has the main project, modules, and library access as defined in the build file.
Hope it helps!
If you want multiple SBT modules in one IDEA project, you can use sbt multi-project builds (aka subprojects). Just create a master project that refers to the modules as sub-projects, then run gen-idea on the master. To specify dependencies among the modules you have to use Build.scala (not build.sbt), as in jxstanford's answer or like this:
lazy val foo = Project(id = "foo", base = file("foo"))
lazy val bar = Project(id = "bar", base = file("bar")) dependsOn(foo)
One level of subprojects works fine (with the dependencies correctly reflected in the resulting IDEA project), but nested subprojects don't seem to work. Also, it seems to be an sbt restriction that the subprojects must live in subdirectories of the master project (i.e., file("../foo") is not allowed).
See also How to manage multiple interdependent modules with SBT and IntelliJ IDEA?.